Ruby on Rails
ActionController
サーチ…
前書き
Action ControllerはMVCのCです。ルータが要求に使用するコントローラを決定した後、コントローラは要求を理解して出力を生成します。
コントローラは要求を受け取り、モデルからデータをフェッチまたは保存し、ビューを使用して出力を作成します。コントローラは、モデルとビューの間の仲介者と考えることができます。モデルデータをビューで使用できるようにしてユーザーに表示し、ユーザーデータをモデルに保存または更新します。
HTMLの代わりにJSONを出力する
class UsersController < ApplicationController
def index
hashmap_or_array = [{ name: "foo", email: "[email protected]" }]
respond_to do |format|
format.html { render html: "Hello World" }
format.json { render json: hashmap_or_array }
end
end
end
さらに、ルートが必要になります:
resources :users, only: [:index]
これは/users上のリクエストに対して2つの異なる方法で応答し/users :
-
/usersまたは/users.htmlアクセスすると、Hello Worldのコンテンツを含むhtmlページが表示されます -
/users.jsonにアクセスすると、以下を含むJSONオブジェクトが表示されます。
[
{
"name": "foo",
"email": "[email protected]"
}
]
あなたのルートがJSONリクエストだけに答えるformat.html { render inline: "Hello World" } は、 format.html { render inline: "Hello World" }を省略することができます。
コントローラ(基本)
class UsersController < ApplicationController
def index
respond_to do |format|
format.html { render html: "Hello World" }
end
end
end
これは基本的なコントローラであり、以下のルートが追加されています(routes.rb内)。
resources :users, only: [:index]
URL /usersアクセスすると、 Hello WorldメッセージがWebページに表示され/users
パラメーター
コントローラはHTTPパラメータにアクセスできます(URLで?name=fooとして認識されるかもしれませんが、Ruby on Railsもさまざまなフォーマットを処理します)。 GETパラメータとPOSTパラメータを区別する方法はありませんが、どのような場合でもそれを行うべきではありません。
class UsersController < ApplicationController
def index
respond_to do |format|
format.html do
if params[:name] == "john"
render html: "Hello John"
else
render html: "Hello someone"
end
end
end
end
end
いつものように私たちのルート:
resources :users, only: [:index]
URL /users?name=johnアクセスします/users?name=johnと出力はHello John 、access /users?name=whateverと出力はHello someoneなります
フィルタリングパラメータ(基本)
class UsersController < ApplicationController
def index
respond_to do |format|
format.html do
render html: "Hello #{ user_params[:name] } user_params[:sentence]"
end
end
end
private
def user_params
if params[:name] == "john"
params.permit(:name, :sentence)
else
params.permit(:name)
end
end
end
いくつかのパラメータを許可(または拒否)することで、必要なものだけを通過させることができ、変更するつもりはないユーザー設定オプションのような驚きはありません。
訪問/users?name=john&sentence=developer表示されますHello john developerしかし訪れ、 /users?name=smith&sentence=spy表示するHello smithので、唯一の:sentenceあなたのようにアクセスするときにのみ許可されているjohn
リダイレクト
ルートを想定します。
resources :users, only: [:index]
以下を使用して別のURLにリダイレクトすることができます。
class UsersController
def index
redirect_to "http://stackoverflow.com/"
end
end
ユーザーが訪問した前のページに戻ることができます:
redirect_to :back
Rails 5では、リダイレクトするための構文が異なることに注意してください。
redirect_back fallback_location: "http://stackoverflow.com/"
前のページにリダイレクトしようとしますが、可能でない場合(ブラウザはHTTP_REFERRERヘッダーをブロックしています)、 :fallback_locationリダイレクトされ:fallback_location
ビューの使用
ルートを想定します。
resources :users, only: [:index]
コントローラー:
class UsersController < ApplicationController
def index
respond_to do |format|
format.html { render }
end
end
end
ビューapp/users/index.html.erbがレンダリングされます。ビューが次の場合:
Hello <strong>World</strong>
出力は「Hello World 」というテキストのWebページになります。
別のビューをレンダリングする場合は、次のものを使用できます。
render "pages/home"
代わりにapp/views/pages/home.html.erbファイルが代わりに使用されます。
コントローラインスタンス変数を使用してビューに変数を渡すことができます:
class UsersController < ApplicationController
def index
@name = "john"
respond_to do |format|
format.html { render }
end
end
end
そして、 app/views/users/index.html.erbファイルで@nameを使うことができます:
Hello <strong><%= @name %></strong>
そして出力は次のようになります: "こんにちはジョン "
レンダリング構文について重要な注意点がありますが、 render構文を完全に省略することができます。省略すると、Railsはこれを仮定します。そう:
class UsersController < ApplicationController
def index
respond_to do |format|
format.html { render }
end
end
end
代わりに次のように書くことができます:
class UsersController < ApplicationController
def index
respond_to do |format|
format.html
end
end
end
Railsは、 app/views/users/index.html.erbファイルをレンダリングする必要があることを理解するのに十分スマートapp/views/users/index.html.erb 。
レコードが見つからない場合は404
例外または白いページを表示するのではなく、レコードから救助してください。
class ApplicationController < ActionController::Base
# ... your other stuff here
rescue_from ActiveRecord::RecordNotFound do |exception|
redirect_to root_path, 404, alert: 'Record not found'
end
end
基本的なRESTコントローラ
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def index
@posts = Post.all
end
def show
end
def new
@post = Post.new
end
def edit
end
def create
@post = Post.new(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to @post.company, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def destroy
@post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_post
@post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :body, :author)
end
end
例外のエラーページを表示する
単純な「申し訳ありませんが、何かが間違っていた」のではなく、意味のあるエラーをユーザに表示したい場合、Railsはこの目的のための素晴らしいユーティリティを持っています。
app/controllers/application_controller.rbファイルを開き、次のようなコードを見つけてください:
class ApplicationController < ActionController::Base protect_from_forgery with: :exception end
特定のエラーから回復するためにrescue_fromを追加できるようになりました。
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
private
def record_not_found
render html: "Record <strong>not found</strong>", status: 404
end
end
ExceptionまたはStandardErrorから救助しないことが推奨されます。さもなければ、Railsはエラーの場合に役立つページを表示できません。
フィルタ
フィルタは、コントローラアクションの前、後または後に実行されるメソッドです。これらは継承されているため、 ApplicationControllerに任意の値を設定すると、 ApplicationControllerが受け取る要求ごとに実行されます。
フィルタ前
フィルタがコントローラの動作の前に実行され、要求を停止する(および/またはリダイレクトする)前に、一般的な使い方は、ユーザーがログインしているかどうかを確認することです。
class ApplicationController < ActionController::Base
before_action :authenticate_user!
def authenticate_user!
redirect_to some_path unless user_signed_in?
end
end
リクエストがコントローラのアクションに到達する前にフィルタがリクエストで実行される前。応答自体を返し、アクションを完全にバイパスすることができます。
beforeフィルタのその他の一般的な使用法は、リクエストを処理するために指定されたアクションへのアクセスを許可する前に、ユーザーの認証を検証することです。また、データベースからリソースをロードしたり、リソースのアクセス権をチェックしたり、他の状況でリダイレクトを管理したりするのにも使用されています。
フィルターの後
フィルターは「前」と似ていますが、アクションの実行後に実行されるので、送信しようとしている応答オブジェクトにアクセスできます。したがって、アクションが完了した後でフィルタが実行された直後です。それは応答を変更することができます。たいていの場合、後のフィルタで何かが行われると、アクション自体で実行できますが、一連のアクションを実行した後に実行するロジックがある場合は、後のフィルタが適切な場所ですそれ。
一般的に、私はロギングに使用されたフィルターの前後を見てきました。
フィルターの周り
フィルターの周りには、アクションが実行される前後に論理がある場合があります。それは、必要な場所でアクションに結びつくだけです。それはアクションに降伏する必要はなく、前のフィルターのように実行する必要はありません。
フィルタの周りは、ラックミドルウェアがどのように動作するかと同様に、降伏によって関連する動作を実行する責任があります。
前後のコールバックはアクションの実行をラップします。折り返しコールバックを2つの異なるスタイルで書くことができます。最初は、コールバックはコードの単一のチャンクです。そのコードは、アクションが実行される前に呼び出されます。コールバックコードがyieldを呼び出すと、アクションが実行されます。アクションが完了すると、コールバックコードは実行を継続します。したがって、yieldの前のコードはbeforeアクションのコールバックのようになり、yieldの後のコードはafterアクションのコールバックになります。コールバックコードがyieldを呼び出さない場合アクションは実行されません。これは、前のアクションコールバックにfalseを返すことと同じです。
aroundフィルタの例を次に示します。
around_filter :catch_exceptions
private
def catch_exceptions
begin
yield
rescue Exception => e
logger.debug "Caught exception! #{e.message}"
end
end
これは任意のアクションの例外をキャッチし、メッセージをログに記録します。例外処理、セットアップとティアダウン、その他の無数の場合にフィルタを使用することができます。
のみと例外
すべてのフィルタは、以下を使用して特定のアクションに適用できます:onlyおよび:except :
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update]
# ... controller actions
# Define your filters as controller private methods
private
def set_product
@product = Product.find(params[:id])
end
end
フィルターをスキップする
すべてのフィルタ(継承されたフィルタも)は、特定のアクションに対してスキップすることもできます。
class ApplicationController < ActionController::Base
before_action :authenticate_user!
def authenticate_user!
redirect_to some_path unless user_signed_in?
end
end
class HomeController < ApplicationController
skip_before_action :authenticate_user!, only: [:index]
def index
end
end
継承されているので、フィルタはnamespace 「親」コントローラで定義することもできnamespace 。たとえば、 admin名前空間があり、 admin者ユーザーだけがアクセスできるようにしたいとします。次のようなことができます:
# config/routes.rb
namespace :admin do
resources :products
end
# app/controllers/admin_controller.rb
class AdminController < ApplicationController
before_action :authenticate_admin_user!
private
def authenticate_admin_user!
redirect_to root_path unless current_user.admin?
end
end
# app/controllers/admin/products_controller.rb
class Admin::ProductsController < AdminController
# This controller will inherit :authenticate_admin_user! filter
end
Rails 4.xでは before_filterをbefore_actionとbefore_actionすることができますが、 before_filterは現在Rails 5.0.0で非推奨であり、 5.1で削除されることに注意してください。
コントローラの生成
Railsはもちろん、コントローラー用の多くのジェネレーターを提供しています。
あなたのアプリケーションフォルダでこのコマンドを実行すると、新しいコントローラを生成することができます
rails generate controller NAME [action action] [options]
注意: rails gエイリアスを使用して、 rails generateを呼び出すこともできrails g
たとえば、 #indexアクションと#showアクションを#showしてProductモデル用のコントローラを生成するには
rails generate controller products index show
これにより、指定した両方のアクションを持つコントローラがapp/controllers/products_controller.rbに作成されます
class ProductsController < ApplicationController
def index
end
def show
end
end
また、コントローラのアクション用の2つのテンプレート( index.html.erbとshow.html.erb )を含むapp/views/中にproductsフォルダを作成します。 拡張子はテンプレートエンジンによって異なる可能性があるので注意してください。使用して「再slim例えば、発電機が作成され、 index.html.slimとshow.html.slim )
さらに、アクションを指定した場合は、 routesファイルにも追加されます
# config/routes.rb
get 'products/show'
get 'products/index'
Railsはapp/helpers/products_helper.rbヘルパーファイルを作成し、 app/assets/javascripts/products.jsとapp/assets/stylesheets/products.cssのアセットファイルも作成しapp/assets/stylesheets/products.css 。ビューについてはジェネレータがGemfile指定されたものに従ってこの動作を変更します。つまり、アプリケーションでCoffeescriptとSassを使用している場合、コントローラジェネレータはproducts.coffeeとproducts.sass products.coffeeしproducts.sass 。
最後に、Railsはコントローラ、ヘルパー、ビューのテストファイルを生成します。
Railsにそれらをスキップするように指示するためにこれらのものを作成したくない場合は、
--no-または--skip 、このように:
rails generate controller products index show --no-assets --no-helper
そしてジェネレータはassetsとhelper両方をスキップします
特定のnamespace用のコントローラを作成する必要がある場合は、 NAME前に追加しnamespace 。
rails generate controller admin/products
これで、コントローラはapp/controllers/admin/products_controller.rb内に作成されます
Railsは、完全なRESTfulコントローラを生成することもできます。
rails generate scaffold_controller MODEL_NAME # available from Rails 4
rails generate scaffold_controller Product
Rescue:ActiveRecord :: RecordNotFound with redirect_to
エラーページを表示するのではなく、リダイレクトを使ってRecordNotFound例外を救済することができます:
class ApplicationController < ActionController::Base
# your other stuff
rescue_from ActiveRecord::RecordNotFound do |exception|
redirect_to root_path, 404, alert: I18n.t("errors.record_not_found")
end
end