さまざまな種類のデバイスのモーダルウィンドウと「通常の」ページからプロジェクトにログインする必要がありました。 検索後、必要なものが記述されていないことが多いことに気付きました。 したがって、
ここではフォームをモーダルウィンドウに配置し(実際に
はwiki deviseのページを使用)、ここ(
ログインおよび
登録 )でdeviseコントローラーのメソッドをオーバーライドして、常にJSONのみを返し、「モードレス」動作のために検証付きの多くの条件を記述する必要がありますリクエスト形式。 そのため、新しいアプリケーションで実験し、最小限の再定義とダーティハックで2つの形式のサポートを記述することにしました。
アプリケーション作成
- テストなしでアプリケーションを生成し、 バンドルインストールを実行します:
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 %>
これがすべて機能するためには、このコンテキストのリソースと関連するものを定義するいくつかのメソッドをapplication_helperに追加する必要があります。
app /ヘルパー/ application_helper.rb
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'