Controllers

Intro

ПослС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠ»ΠΈ routes, ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Ρ‹ (это C Π² MVC ΠΏΠ°Ρ‚Ρ‚Π΅Ρ€Π½Π΅). Π­Ρ‚Π° ΡΡƒΡ‰Π½ΠΎΡΡ‚ΡŒ находится ΠΌΠ΅ΠΆΠ΄Ρƒ слоСм отобраТСния (View) ΠΈ слоСм ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ Π΄Π°Π½Π½Ρ‹Ρ… (Model).

Π’ Ruby ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ β€” класс, наслСдованный ΠΎΡ‚ ApplicationController (наслСдован ΠΎΡ‚ ActionController::Base). Когда ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ запрос, ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΡ опрСдСляСт ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€ ΠΈ дСйствиС для запуска; Rails создаСт инстанс ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π° ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄, ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΡΠ²Π»Π΅Π½Π½ΠΎΠΌΡƒ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡŽ

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°

# resources :clients, only: :new
# -> /clients/new -> Add new client

class ClientsController < ApplicationController
    def new
        @client = Client.new # @client becomes accessible in the view 
                             # Автоматом доступСн модСль Client
    end
end

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Π² ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π΅

Доступ ΠΊ GET/POST ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌ осущСствляСтся Ρ‡Π΅Ρ€Π΅Π· params

class ClientsController < ApplicationController
  # This action uses query string parameters because it gets run
  # by an HTTP GET request, but this does not make any difference
  # to how the parameters are accessed. The URL for
  # this action would look like this to list activated
  # clients: /clients?status=activated
  def index
    if params[:status] == "activated"
      @clients = Client.activated
    else
      @clients = Client.inactivated
    end
  end

  # This action uses POST parameters. They are most likely coming
  # from an HTML form that the user has submitted. The URL for
  # this RESTful request will be "/clients", and the data will be
  # sent as part of the request body.
  def create
    @client = Client.new(params[:client])
    if @client.save
      redirect_to @client
    else
      # This line overrides the default rendering behavior, which
      # would have been to render the "create" view.
      render "new"
    end
  end
end

rescue_from

ΠŸΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ эксСпшСна Π² Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΌ ΠΈ Π²ΠΎ всСх Π΄ΠΎΡ‡Π΅Ρ€Π½ΠΈΡ… ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°Ρ… кастомным способом

class WebController < ApplicationController
    rescue_from ActiveRecord::RecordNotFound, with: :error_not_found
    
    def error_not_found(error)
        return render template: 'errors/404', layout: false, status: :not_found
    end
end

Strong Parameter API

permit

Ѐункция Ρƒ params, которая позволяСт Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹ΠΉ список ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ². ДСлаСтся для ограничСния ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ использования.

params.permit(:id)

def product_params
    params.require(:product).permit(:name, data: {})
end

require

Π£ΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ обязатСлСн

Session

Your application has a session for each user in. The session is only available in the controller and the view and can use one of several of different storage mechanisms:

All session stores use a cookie to store a unique ID for each session.

If you need a different session storage mechanism, you can change it in an initializer:

# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
# (create the session table with "rails g active_record:session_migration")
# Rails.application.config.session_store :active_record_store

Rails sets up a session key (the name of the cookie) when signing the session data. These can also be changed in an initializer:

# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cookie_store, key: '_your_app_session'

You can also pass a :domain key and specify the domain name for the cookie:

# Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cookie_store, key: '_your_app_session', domain: ".example.com"

Rails sets up (for the CookieStore) a secret key used for signing the session data in config/credentials.yml.enc. This can be changed with bin/rails credentials:edit.

Accessing the Session

Session values are stored using key/value pairs like a hash:

class ApplicationController < ActionController::Base

  private

  # Finds the User with the ID stored in the session with the key
  # :current_user_id This is a common way to handle user login in
  # a Rails application; logging in sets the session value and
  # logging out removes it.
  def current_user
    @_current_user ||= session[:current_user_id] &&
      User.find_by(id: session[:current_user_id])
  end
end

To store something in the session, just assign it to the key like a hash:

class LoginsController < ApplicationController
  # "Create" a login, aka "log the user in"
  def create
    if user = User.authenticate(params[:username], params[:password])
      # Save the user ID in the session so it can be used in
      # subsequent requests
      session[:current_user_id] = user.id
      redirect_to root_url
    end
  end
end

To remove something from the session, delete the key/value pair:

class LoginsController < ApplicationController
  # "Delete" a login, aka "log the user out"
  def destroy
    # Remove the user id from the session
    session.delete(:current_user_id)
    # Clear the memoized current user
    @_current_user = nil
    redirect_to root_url
  end
end

flash

Π•ΡΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ flash, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌΡƒ запросу

Cookies

ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ для доступа ΠΊ cookie.

МоТно ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π»ΠΈΡ‚ΡŒ Π² ΠΊΠΎΠ½Ρ„ΠΈΠ³Π΅, ΠΊΠ°ΠΊ Π±ΡƒΠ΄ΡƒΡ‚ сСриализованы значСния

Rails.application.config.action_dispatch.cookies_serializer = :json
# :json β€” сСриализация ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ для Π½ΠΎΠ²Ρ‹Ρ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, для старый β€” :marshal.

# Custom serialized (implement load ΠΈ dump ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹):
Rails.application.config.action_dispatch.cookies_serializer = MyCustomSerializer

Filters

Π­Ρ‚ΠΎ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‚ΡΡ before, after ΠΈ around дСйствия ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°. Π€ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹ Π½Π°ΡΠ»Π΅Π΄ΡƒΡŽΡ‚ΡΡ. Если ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ Π² ApplicationController, Ρ‚ΠΎ ΠΎΠ½ Π±ΡƒΠ΄Π΅Ρ‚ ΡΡ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π΅ вашСго прилоТСния:

class ApplicationController < ActionController::Base
  before_action :require_login

  private

  def require_login
    unless logged_in?
      flash[:error] = "You must be logged in to access this section"
      redirect_to new_login_url # halts request cycle
    end
  end
end

Если ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ ΡΠΊΠΈΠΏΠ½ΡƒΡ‚ΡŒ ΠΊΠ°ΠΊΠΎΠΉ-Π½ΠΈΠ±ΡƒΠ΄ΡŒ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ для нашСго ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»Π»Π΅Ρ€Π°:

class LoginsController < ApplicationController
  skip_before_action :require_login, only: [:new, :create]
end

Last updated