例如,我将以下两个HTTP POST参数传递给我的Rails应用程序:
fname=john&lname=doe
在我的应用程序中,控制器将参数哈希传递给'Person'模型类,定义为:
Class Person
attr_accessor :fname, :lname
def initialize(params)
@fname = params[:fname]
@lname = params[:lname]
end
end
可以看到,我用params散列中包含的值初始化Person对象。注意属性和参数的名称是相同的。
显然,在现实世界的例子中,我的对象中会有更多的属性,因此使用上面的初始化方法可能会变得乏味。
因此,我想知道是否有一种方法来动态填充具有相同名称的HTTP参数的对象的属性?
你可以在控制器和模型中做你所要求的。首先,这是一个如何与控制器一起工作的示例:
class PeopleController < ActionController::Base
attr_accessor :fname, :lname, :phone, :email
def some_action
params.each_pair do |key, value|
send(:"#{key}=", value) if respond_to?(:"#{key}=")
end
end
end
然而,这不是一个非常实际的应用;在控制器上使用访问器实例变量的理由很少,更不必使用此方法。
相反,你似乎想要做的是创建Person
模型的实例和params
的质量分配属性。Rails已经这样做了,因此默认的create
动作:
class PeopleController < ActionController::Base
def create
@person = Person.new(params[:person])
if @person.save
redirect_to @person, :flash => "Person created successfully."
else
render :action => :new
end
end
end
请注意,默认情况下,所有模型属性都是可批量分配的。当用户有可能操纵某些字段(如关联)时,这可能是一个安全问题。在这种情况下,您可以将模型上的属性列入白名单或黑名单,以防止这种类型的安全漏洞:
class Person < ActiveRecord::Base
attr_accessible :fname, :lname, :phone, :email
# or
attr_protected :non_user_changeable_attribute
end
你可以在这里阅读更多关于大规模赋值安全的内容。
如果您想将此行为添加到一组非activerecord类(没有保护器属性),您可以捕获此模块,只需在类定义中执行include MassAssignment
(不依赖于Rails):
module MassAssignment
def initialize(attributes = {})
mass_assign(attributes)
end
def mass_assign(attributes)
attributes.each do |attribute, value|
respond_to?(:"#{attribute}=") && send(:"#{attribute}=", value)
end
end
end
这避免了在每个初始化项中重复一些"丑陋"的代码。
通过:https://github.com/coreyward/typekit/blob/master/lib/typekit/base.rb