понимание использования cattr_accessor в классе моделей Rails

Я новичок в рубине и рельсах. В моем приложении Rails я пытаюсь использовать гем Wicked Wizard, и мне нужна помощь в понимании cattr_accessor, с которым я столкнулся в коде.

  create_table "pets", force: :cascade do |t|
            t.string   "name"
            t.string   "colour"
            t.string   "owner_name"
            t.text     "identifying_characteristics"
            t.text     "special_instructions"
            t.datetime "created_at"
            t.datetime "updated_at"
            t.string   "email"
            t.string   "password"
          end

модель

 class Pet < ActiveRecord::Base
  has_many :pet_photos
  cattr_accessor :form_steps do
    %w(identity characteristics instructions)
  end

  attr_accessor :form_step
  validates :email, presence: true
  validates :name, :owner_name, presence: true, if: -> { required_for_step?(:identity) }
  validates :identifying_characteristics, :colour, presence: true, if: -> { required_for_step?(:characteristics) }
  validates :special_instructions, presence: true, if: -> { required_for_step?(:instructions) }

  def required_for_step?(step)
    return true if form_step.nil?
    return true if self.form_steps.index(step.to_s) <= self.form_steps.index(form_step)
  end



end

и

      class Pet::StepsController < ApplicationController
        include Wicked::Wizard
        steps *Pet.form_steps

        def show
          @pet = Pet.find(params[:pet_id])
          render_wizard
        end

        def update
          @pet = Pet.find(params[:pet_id])
          @pet.update(pet_params(step))

            if params[:images]

                params[:images].each do |image|
                @pet.pet_photos.create(image: image)
              end
            end

          render_wizard @pet
        end

        private

        def pet_params(step)
          permitted_attributes = case step
                                 when "identity"
                                   [:name, :owner_name]
                                 when "characteristics"
                                   [:colour, :identifying_characteristics]
                                 when "instructions"
                                   [:special_instructions]
                                 end

          params.require(:pet).permit(permitted_attributes).merge(form_step: step)
        end

      end

маршруты

  PetThing::Application.routes.draw do
          resources :pets, only: [:new, :create, :index, :destroy] do
            resources :steps, only: [:show, :update], controller: 'pet/steps'
          end

          root to: 'pets#index'

Теперь мои вопросы

1) в чем разница между cattr_accessor и attr_accessor?

       cattr_accessor :form_steps do
       %w(identity characteristics instructions)
       end
       attr_accessor :form_step

2) почему два разных символа (:form_steps , :form_step) используются в качестве параметров методов для методов cattr_accessor и attr_accessor соответственно?

3) почему блок передается в качестве параметра методу cattr_accessor?

Любая помощь высоко ценится. Спасибо.


person current_user    schedule 05.12.2017    source источник
comment
Возможный дубликат cattr_accessor в Rails?   -  person jvillian    schedule 05.12.2017


Ответы (1)


Прежде всего, этот метод устарел или перемещен. Какую версию вы используете, Rails 4 или Rails?

cattr_accessor > заменен на mattr_accessor(*syms, &blk) на Module, который является суперклассом класса Class. Я рекомендую использовать attr_accessor, который является просто методом установки атрибутов для класса, он работает как геттер или сеттер для класса, но работает только для экземпляра (в памяти), атрибут сохраняется где угодно.

cattr_accessor похож на методы attr_*, но для уровня класса. Одна вещь, которую вы не ожидаете, заключается в том, что она использует резервную копию @@form_steps, значение, разделяемое между классом и всеми экземплярами.

Документы API:

Определяет методы доступа класса и экземпляра для атрибутов класса.

module HairColors
  mattr_accessor :hair_colors
end

class Person
  include HairColors
end

Person.hair_colors = [:brown, :black, :blonde, :red]
Person.hair_colors     # => [:brown, :black, :blonde, :red]
Person.new.hair_colors # => [:brown, :black, :blonde, :red]

Если подкласс изменяет значение, это также изменит значение для родительского класса. Точно так же, если родительский класс изменит значение, это также изменит значение подклассов.

class Male < Person
end

Male.hair_colors << :blue
Person.hair_colors # => [:brown, :black, :blonde, :red, :blue]

Чтобы отказаться от метода записи экземпляра, передайте instance_writer: false. Чтобы отказаться от метода чтения экземпляра, передайте instance_reader: false.

module HairColors
  mattr_accessor :hair_colors, instance_writer: false, instance_reader:             false
end

class Person
  include HairColors
end

Person.new.hair_colors = [:brown]  # => NoMethodError
Person.new.hair_colors             # => NoMethodError

Или передайте instance_accessor: false, чтобы отказаться от обоих методов экземпляра.

module HairColors
  mattr_accessor :hair_colors, instance_accessor: false
end

class Person
  include HairColors
end

Person.new.hair_colors = [:brown]  # => NoMethodError
Person.new.hair_colors             # => NoMethodError

Также вы можете передать блок, чтобы установить атрибут со значением по умолчанию.

module HairColors
  mattr_accessor :hair_colors do
[:brown, :black, :blonde, :red]
  end
end

class Person
  include HairColors
end

Person.class_variable_get("@@hair_colors") #=> [:brown, :black, :blonde, :red]

1)

  • attr_accessor: это метод ruby, который создает геттер и сеттер
  • cattr_accessor: метод ruby, который создает геттер и сеттер для класса (довольно странно).

2) Переменные класса имеют тенденцию переходить из класса в класс. Переменная класса @@form_steps может быть представлена ​​через дерево наследования.

3) Чтобы указать, какие атрибуты будут иметь этот класс. form_steps

p = Pet.new
p.form_steps = "var"

и используйте атрибут form_steps внутри вашего текущего экземпляра Pet (как вы делаете в методе required_for_step?).

person maguri    schedule 05.12.2017