アプリケーション作成
- テストなしでアプリケーションを生成し、 バンドルインストールを実行します:
rails new devise_modal -B -T
- Gemfileに必要なgemを追加します 。
-
gem 'therubyracer', platforms: :ruby
gem "less-rails"
gem 'twitter-bootstrap-rails', branch: 'bootstrap3'
モーダルウィンドウにはブートストラップを使用 -
gem 'devise'
認証はdeviseを介して行われます
すべてをインストールします:bundle install
-
- 必要なジェネレーターを起動します
rails g bootstrap:install static
bootstrapスタイルでは何も変更しないため、rails g bootstrap:install static
、staticをrails g bootstrap:install static
ます
rails g devise:install; rails g devise User; rake db:migrate
rails g devise:install; rails g devise User; rake db:migrate
- deviseをインストールしてユーザーを作成
- メインページを表示するコントローラーを作成します。
rails g controller welcome index --no-helper --no-assets
config / routes.rbで 、 インデックスをメインページにバインドします。
root 'welcome#index'
この段階の終わりに、
users/sign_in
標準リンクにログイン/登録フォームがあるアプリケーションがあります:
users/sign_in
と
users/sign_up
。
フォームのモーダルウィンドウ
フォームには目立ったものは何もありません。標準のデバイスを使用し、 リモートにし、フォーマットをjsonに変更します。 次に、 ブートストラップを適切なクラスでラップすることにより、モーダルにします。 その結果、このような部分的なを得ました:
app / views / shared / _sign_in.html.erb
<div class="modal hide fade in" id="sign_in"> <div class="modal-header"> <button class="close" data-dismiss="modal">x</button> <h2>Sign in</h2> </div> <div class="modal-body"> <%= form_for(User.new, url: session_path(:user), html:{id: 'sign_in_user', :'data-type' => 'json'}, remote: true) do |f| %> <div> <%= f.label :email %><br /> <%= f.email_field :email, autofocus: true %> </div> <div> <%= f.label :password %><br /> <%= f.password_field :password, autocomplete: "off" %> </div> <% if Devise.mappings[:user].rememberable? -%> <div> <%= f.check_box :remember_me %> <%= f.label :remember_me %> </div> <% end -%> <div> <%= f.submit "Sign in" %> </div> <% end %> </div> <div class="modal-footer"> </div> </div>
app / views / shared / _sign_up.html.erb
<div class="modal hide fade in" id="sign_up"> <div class="modal-header"> <button class="close" data-dismiss="modal">x</button> <h2>Sign up</h2> </div> <div class="modal-body"> <%= form_for(User.new, url: registration_path(:user), html: {id: 'sign_up_user', :'data-type' => 'json'}, remote: true) do |f| %> <div> <%= f.label :email %><br /> <%= f.email_field :email, autofocus: true %> </div> <div> <%= f.label :password %><br /> <%= f.password_field :password, autocomplete: "off" %> </div> <div> <%= f.label :password_confirmation %><br /> <%= f.password_field :password_confirmation, autocomplete: "off" %> </div> <div><%= f.submit "Sign up" %></div> <% end %> </div> <div class="modal-footer"> </div> </div>
これらのファイルとリンクの表示を追加して、 レイアウトで呼び出します :
<%= link_to "Sign in", "#sign_in", "data-toggle" => "modal", :class => 'btn btn-small' %> <%= link_to "Sign up", "#sign_up", "data-toggle" => "modal", :class => 'btn btn-small' %> <%= render 'shared/sign_in' %> <%= render 'shared/sign_up' %>
その後、ユーザーの存在を確認することにより、少し高貴になります。
app / views / layouts / application.html.erb
<% if current_user %> <%= "Hello, #{current_user.email}" %> <%= link_to "Sign out", destroy_user_session_path, :method => :delete %> <% else %> <%= link_to "Sign in", "#sign_in", "data-toggle" => "modal", :class => 'btn btn-small' %> <%= link_to "Sign up", "#sign_up", "data-toggle" => "modal", :class => 'btn btn-small' %> <%= render 'shared/sign_in' %> <%= render 'shared/sign_up' %> <% end %>
def resource_name :user end def resource @resource ||= User.new end def devise_mapping @devise_mapping ||= Devise.mappings[:user] end
printercuとDarthSimがコメントで述べたように、 リソースのグローバルヘルパーを再定義することはほとんど意味がありません
User.new
-
User.new
およびresource_name-
:user
代わりにフォームで直接設定する方が良いです。 また、 app / views / shared / _sign_in.html.erbで、
Devise.mappings[:user]
ではなく
Devise.mappings[:user]
指定します。 一般に、この状態を完全に取り除くことができます:
<% if devise_mapping.rememberable? -%>
ユーザーモデル( app / models / user.rb )で示すかどうかに基づいて:rememberable
。 さらに、 app / views / shared / _sign_up.html.erbにはdevise_error_messagesヘルパーもありました! 、 リソースを使用しますが、エラーテキストはjsonの応答から
<%= devise_error_messages! %>
れるため、フォームから
<%= devise_error_messages! %>
削除するだけ
<%= devise_error_messages! %>
不要として
<%= devise_error_messages! %>
。
現在、どのページからでもアクセスでき、入力および登録できるモーダルフォームがあります。 deviseがこれらのリクエストに応じてhtmlページを送信しないことを確認するためだけに残ります。
deviseからのJSON応答
devise gemでは、 FailureAppが入力関連のエラーを処理します。 ログイン要求を処理するSessionsControllerでエラーが発生した場合、 http_authを使用して応答が呼び出され ますか? チェック:401ステータスを送信するか、別のページにリダイレクトする必要があります。 デフォルトはdeviseであるため :
config / initializers / devise.rb
config.http_authenticatable_on_xhr = true
次に401が戻ります。
RegistrationsControllerは、AJAXリクエストへの応答としてhtmlページを送信し、これを修正するために少し再定義します。関心のある形式を明示的に示します。
rails g controller Registrations --no-helper --no-assets --no-views
config / routes.rb
devise_for :users, controllers: {registrations: 'registrations'}
app / controllers / registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController respond_to :html, :json end
登録試行が失敗すると、 responseJSON ['errors']にエラーテキストを含む422ステータスが表示され、成功した場合は201が表示されます。 JSONリクエストに正しく応答します。
rails g controller Sessions --no-helper --no-assets --no-views
config / routes.rb
devise_for :users, controllers: {sessions: 'sessions', registrations: 'registrations'}
app / controllers / sessions_controller.rb
class SessionsController < Devise::SessionsController respond_to :html, :json end
また、モーダルフォームからの応答を処理するjavascriptを記述することもできます。たとえば、次のようになります。
アプリ/アセット/ javascripts / welcome.js.coffee
$ -> $("form#sign_in_user, form#sign_up_user").bind("ajax:success", (event, xhr, settings) -> $(this).parents('.modal').modal('hide') ).bind("ajax:error", (event, xhr, settings, exceptions) -> error_messages = if xhr.responseJSON['error'] "<div class='alert alert-danger pull-left'>" + xhr.responseJSON['error'] + "</div>" else if xhr.responseJSON['errors'] $.map(xhr.responseJSON["errors"], (v, k) -> "<div class='alert alert-danger pull-left'>" + k + " " + v + "</div>" ).join "" else "<div class='alert alert-danger pull-left'>Unknown error</div>" $(this).parents('.modal').children('.modal-footer').html(error_messages) )
入り口で、エラーをalertにラップし、登録中に各パラメーターのエラーをラップし、その後、受信したメッセージをfooterに表示します。 リクエストが成功すると、モーダルフォームを削除するだけです( レイアウト内のブロックを更新することもできます。このブロックでは、ユーザーがユーザーデータを表示するようにチェックされます(回答も含まれます)。
コントローラーは、モーダルフォーム-jsonと標準( users / sign_in 、 users / sign_up ) -htmlの両方について、正しい形式で回答を提供します。 そして、これに必要なことは、コントローラーを再定義して、フォーマットのセットを拡張することだけでした。
respond_to :html, :json
ご注意
アプリケーションはRails 4で作成されましたが、3.2の違いは最小限に抑えられます。アプリケーションの作成時に
bundle install
が開始され、
public/index.html
を削除する必要があり、メインのパスは少し異なります。
config / routes.rb
root to: 'welcome#index'