ruby-on-rails 理解cattr_accessor在Rails模型类中的用法

hc8w905p  于 2023-11-20  发布在  Ruby
关注(0)|答案(1)|浏览(111)

我是Ruby和Rails的新手。在我的Rails应用程序中,我试图使用Wicked Wizard gem,需要一些帮助来理解我在代码中遇到的cattr_accessor

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

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

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

# routes
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'
end

字符串
现在我的问题是:

1)cattr_accessorattr_accessor有什么区别?

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

**2)**为什么cattr_accessorattr_accessor的方法参数分别使用两个不同的符号(:form_steps:form_step)?
**3)**为什么一个块作为参数传递给cattr_accessor方法?

eufgjt7s

eufgjt7s1#

首先,这个方法已经被弃用或移动了。你使用哪个版本,Rails 4还是Rails?
cattr_accessor>为mattr_accessor(*syms, &blk)替换了Module,它是Class类的超类。我建议使用attr_accessor,这只是一个为类设置属性的方法,它的工作方式类似于类的getter或setter,但只适用于示例(在内存中),属性保存在任何地方。
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方法,用于创建getter和setter
  • cattr_accessor:是一个Ruby方法,为类创建getter和setter(很奇怪)。
    **2)**类变量有在类间游走的倾向,@@form_steps类变量可以通过继承树暴露。
    **3)**设置哪些属性会有这个类。form_steps
p = Pet.new
p.form_steps = "var"


并在当前示例Pet中使用form_steps属性(就像在方法required_for_step?中所做的那样)。

相关问题