请原谅我的菜鸟问题。我是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
任何帮助都非常感谢,谢谢!
问题 #1
太宽泛了。所以,我会在那里通过。
问题#2:这有什么作用?
delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user
我将使用Person
来执行此操作,因为这是我在我的应用程序中拥有的(不是User
)。
所以。。。该::
指示应在全局命名空间中查找该类(称为Constant
)。这表明代码片段来自引擎(尽管不一定)。
::Person
.attribute_names
从persons
表中生成字段名称的array
。
> ::Person.attribute_names
=> ["id", "first_name", "last_name", "date_of_birth", "created_at", "updated_at", "sex_id", "ethnicity_id"]
.map{ |attr| [attr, "#{attr}="] }
生成一个arrays
array
,其中每个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
,而不是arrays
的array
。 所以,.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="]
借用这篇文章:
splat 运算符(即 *)将原本是数组的内容转换为要赋值的列表
本质上,数组中的每个元素都将成为delegate
的参数。
delegate 告知对象此代码行所在的位置,以将方法调用传递给另一个对象。
to: :user
指示要将方法调用传递到哪个对象。在这种情况下,:user
是一个方法调用,它可能包含::User
的实例。
如果您手动执行此操作,它将如下所示:
delegate :id,
:id=,
:first_name,
:first_name=,
...,
to: :person
问题#3:这是做什么的?
def initialize(user_attributes)
@user = ::User.new(user_attributes)
end
每个class constant
都继承自Class
("根"class Constant
):
> class Foo; end
=> nil
> Foo.is_a?(Class)
=> true
每个class Constant
都继承initialize
作为私有方法来自Class
:
> Class.private_methods.include?(:initialize)
=> true
initialize
是在class Constant
(如User.new
或Foo.new
或其他)上调用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)