请原谅我的noob问题。我是ruby和rails的初学者,我在Rails中开发了一个向导或多步骤表单。我正在关注这篇文章
https://medium.com/@nicolasblanco/developing-a-wizard-or-multi-steps-forms-in-rails-d2f3b7c692ce
module Wizard
module User
STEPS = %w(step1 step2 step3 step4).freeze
class Base
include ActiveModel::Model
attr_accessor :user
delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user
def initialize(user_attributes)
@user = ::User.new(user_attributes)
end
end
class Step1 < Base
validates :email, presence: true, format: { with: /@/ }
end
class Step2 < Step1
validates :first_name, presence: true
validates :last_name, presence: true
end
class Step3 < Step2
validates :address_1, presence: true
validates :zip_code, presence: true
validates :city, presence: true
validates :country, presence: true
end
class Step4 < Step3
validates :phone_number, presence: true
end
endmodule Wizard
module User
STEPS = %w(step1 step2 step3 step4).freeze
class Base
include ActiveModel::Model
attr_accessor :user
delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user
def initialize(user_attributes)
@user = ::User.new(user_attributes)
end
end
class Step1 < Base
validates :email, presence: true, format: { with: /@/ }
end
class Step2 < Step1
validates :first_name, presence: true
validates :last_name, presence: true
end
class Step3 < Step2
validates :address_1, presence: true
validates :zip_code, presence: true
validates :city, presence: true
validates :country, presence: true
end
class Step4 < Step3
validates :phone_number, presence: true
end
end
end
1)以下代码段的作用是什么?
delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user
2)以下代码段的作用是什么?
def initialize(user_attributes)
@user = ::User.new(user_attributes)
end
任何帮助都是高度赞赏的。谢谢!
答案 0 :(得分:2)
太宽泛了。所以,我会在那里通过。
delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user
我将使用Person
执行此操作,因为这就是我的应用中的(不是User
)。
所以...... ::
表示应该在全局命名空间中查找该类(称为Constant
)。这表明该片段来自引擎(虽然,但不一定)。
::Person
.attribute_names
从array
表生成persons
个字段名称。
> ::Person.attribute_names
=> ["id", "first_name", "last_name", "date_of_birth", "created_at", "updated_at", "sex_id", "ethnicity_id"]
.map{ |attr| [attr, "#{attr}="] }
生成array
arrays
,其中每个array
的内容将成为委托getter
和setter
:
> ::Person.attribute_names.map{ |attr| [attr, "#{attr}="] }
=> [["id", "id="], ["first_name", "first_name="], ["last_name", "last_name="], ["date_of_birth", "date_of_birth="], ["created_at", "created_at="], ["updated_at", "updated_at="], ["sex_id", "sex_id="], ["ethnicity_id", "ethnicity_id="]]
但是,我们需要array
,而不是array
arrays
。所以,.flatten
完成了这项工作。
> ::Person.attribute_names.map{ |attr| [attr, "#{attr}="] }.flatten
=> ["id", "id=", "first_name", "first_name=", "last_name", "last_name=", "date_of_birth", "date_of_birth=", "created_at", "created_at=", "updated_at", "updated_at=", "sex_id", "sex_id=", "ethnicity_id", "ethnicity_id="]
借鉴this post:
splat运算符(即*)将原本将数组转换为赋值列表
基本上,数组中的每个元素都将成为delegate
的参数。
delegate告诉对象存在这行代码,将方法调用传递给另一个对象。
to: :user
表示将方法调用传递到哪个对象。在这种情况下,:user
是一个方法调用,可能包含::User
的实例。
如果您手动执行此操作,它将类似于:
delegate :id,
:id=,
:first_name,
:first_name=,
...,
to: :person
def initialize(user_attributes)
@user = ::User.new(user_attributes)
end
每个class constant
都来自Class
('root'class Constant
):
> class Foo; end
=> nil
> Foo.is_a?(Class)
=> true
每个class Constant
都将initialize
作为Class
的私有方法继承:
> Class.private_methods.include?(:initialize)
=> true
initialize
是您在new
(例如class Constant
或User.new
或其他)上致电Foo.new
时调用的方法:
class Foo
private
def initialize
puts "initializing"
end
end
> Foo.new
initializing
=> #<Foo:0x00000006fe5140>
initialize
(继承自Class
)不接受任何参数。
> Foo.new(:baz)
ArgumentError: wrong number of arguments (given 1, expected 0)
但是,您可以在任何给定的类定义中覆盖它:
class Foo
attr_accessor :bar
private
def initialize(bar)
puts "initializing"
@bar = bar
end
end
现在Foo
将接受new
的参数:
> @foo = Foo.new(:baz)
initializing
=> #<Foo:0x00000006f64720 @bar=:baz>
> @foo.bar
=> :baz
这是怎么回事:
def initialize(user_attributes)
此行只是创建::User
的新实例,并传递user_attributes
,该实例已分配给实例变量@user
:
@user = ::User.new(user_attributes)