수색…


소개

액션 컨트롤러는 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 에 대한 요청에 두 가지 다른 방식으로 응답 /users .

  • /users 또는 /users.html 을 방문하면 Hello World 콘텐츠가있는 html 페이지가 표시됩니다.
  • /users.json 을 방문하면 다음을 포함하는 JSON 객체가 표시됩니다.
[
  {
    "name": "foo",
    "email": "[email protected]"
  }
]

경로가 JSON 요청에만 응답하는지 확인하려면 format.html { render inline: "Hello World" } 생략 할 수 있습니다.

컨트롤러 (기본)

class UsersController < ApplicationController
  def index
    respond_to do |format|
      format.html { render html: "Hello World" }
    end
  end
end

이 컨트롤러는 다음과 같은 route (routes.rb에 있음)가 추가 된 기본 컨트롤러입니다.

resources :users, only: [:index]

URL /users 액세스 할 때 Hello World 메시지가 웹 페이지에 표시됩니다.

매개 변수

컨트롤러는 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 에 액세스하면 출력은 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=developerHello john developer /users?name=john&sentence=developer 를 표시하지만 /users?name=smith&sentence=spy 방문 /users?name=smith&sentence=spyHello smith 만 표시합니다. 왜냐하면 :sentencejohn 액세스 할 때만 허용됩니다.

리디렉션

가정 할 때 :

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

보기 사용

가정 할 때 :

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 "텍스트가있는 웹 페이지가됩니다.

다른보기를 렌더링하려면 다음을 사용할 수 있습니다.

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>

출력은 "Hello john "입니다.

렌더 구문을 둘러싼 중요한 점은 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 파일을 렌더링해야한다는 것을 알기에 충분히 똑똑합니다.

레코드를 찾을 수 없을 때 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 어떤 것을 설정하면 애플리케이션이받는 모든 요청에 ​​대해 실행됩니다.

필터 전

필터가 컨트롤러 동작 전에 실행되기 전에 요청을 중단 할 수 있습니다 (및 / 또는 리디렉션). 일반적인 사용은 사용자가 로그인했는지 확인하는 것입니다.

class ApplicationController < ActionController::Base
  before_action :authenticate_user!

  def authenticate_user!
    redirect_to some_path unless user_signed_in?
  end
end

요청이 컨트롤러의 동작에 도달하기 전에 필터가 요청에 대해 실행되기 전에. 응답 자체를 반환하고 작업을 완전히 무시할 수 있습니다.

before 필터의 다른 일반적인 용도는 요청을 처리하도록 지정된 작업에 액세스 권한을 부여하기 전에 사용자의 인증을 확인하는 것입니다. 또한 데이터베이스에서 리소스를로드하거나 리소스에 대한 사용 권한을 확인하거나 다른 상황에서 리디렉션을 관리하는 데 사용되는 것으로 나타났습니다.

필터 후

필터는 "before"필터와 유사하지만 액션이 실행 된 후에 실행되기 때문에 보내려는 응답 객체에 액세스 할 수 있습니다. 따라서 작업이 완료된 후에 필터가 실행 된 후 잠깐. 응답을 수정할 수 있습니다. 대다수의 시간이 후 필터에서 수행되면 액션 자체에서 수행 될 수 있지만 액션 세트를 실행 한 후에 어떤 로직이 실행되는 경우 애프터 필터를 수행하는 것이 좋습니다 그것.

일반적으로, 필자는 로깅에 사용 된 필터를 보았습니다.

필터 주변

주위의 필터는 동작이 실행되기 전후에 논리를 가질 수 있습니다. 어떤 장소에서 필요한 행동을하기 만하면됩니다. 액션에 양보 할 필요가 없으며 이전 필터와 유사하게 실행하지 않아도됩니다.

필터 주위는 랙 미들웨어의 작동과 유사하게 항복하여 관련 작업을 실행하는 책임이 있습니다.

주위의 콜백은 액션의 실행을 감싸줍니다. 두 가지 스타일로 둘러싼 콜백을 작성할 수 있습니다. 첫 번째로, 콜백은 단일 코드 덩어리입니다. 이 코드는 액션이 ​​실행되기 전에 호출됩니다. 콜백 코드가 yield를 호출하면 작업이 실행됩니다. 작업이 완료되면 콜백 코드가 계속 실행됩니다. 따라서 yield 이전의 코드는 before 액션 콜백과 같고 yield 후의 코드는 after 액션 콜백입니다. 콜백 코드가 yield를 호출하지 않는 경우. 액션이 실행되지 않습니다. 이전 액션 콜백이 false를 반환하는 것과 같습니다.

다음은 둘러보기 필터의 예입니다.

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 "상위"컨트롤러에서 필터를 정의 할 수도 있습니다. 예를 들어 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_filterbefore_action 과 함께 사용할 수 있지만 before_filter 는 현재 Rails 5.0.0 에서 사용되지 않으며 5.1 에서 제거됩니다.

컨트롤러 생성하기

Rails는 물론 컨트롤러 용으로 많은 발전기를 제공합니다.

앱 폴더에서이 명령을 실행하여 새 컨트롤러를 생성 할 수 있습니다.

rails generate controller NAME [action action] [options]

참고 : rails g 별칭을 사용하여 rails generate 를 호출 할 수도 있습니다

예를 들어 #index#show 액션을 사용하여 Product 모델에 대한 컨트롤러를 생성하려면

rails generate controller products index show

이렇게하면 지정한 작업과 함께 app/controllers/products_controller.rb 컨트롤러가 생성됩니다.

class ProductsController < ApplicationController
  def index
  end

  def show
  end
end

또한 컨트롤러의 동작에 대한 두 개의 템플릿 (예 : index.html.erbshow.html.erb )을 포함하는 app/views/ 내에 products 폴더를 만들 것 입니다. 확장자는 템플릿 엔진에 따라 다를 수 있으므로 사용하고 ' slim 예 발생기 만들 것이다 index.html.slimshow.html.slim )

또한 작업을 지정한 경우 routes 파일에도 추가됩니다

# config/routes.rb
get 'products/show'
get 'products/index'

Rails는 app/helpers/products_helper.rb 에 helper 파일을 만들고 app/assets/javascripts/products.jsapp/assets/stylesheets/products.css 있는 애셋 파일을 만듭니다. 뷰의 경우 생성기는 Gemfile 지정된 Gemfile 동작을 변경합니다. 즉, 응용 프로그램에서 CoffeescriptSass 를 사용하는 경우 컨트롤러 생성기는 대신 products.coffeeproducts.sass 를 생성 products.sass .

마지막으로 Rails는 컨트롤러, 도우미 및 뷰에 대한 테스트 파일을 생성합니다.

Rails가 이들을 건너 뛰도록 지시 할 수 있도록 이들 중 어느 것도 생성하지 않으려면 옵션을 앞에 붙이면됩니다.

--no- 또는 --skip , 다음과 같이 :

rails generate controller products index show --no-assets --no-helper

그리고 생성기는 assetshelper 건너 뜁니다.

특정 namespace 에 대한 컨트롤러를 생성해야하는 경우 NAME 앞에 추가하십시오.

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 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


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow