是否有可能用相同名称的HTTP参数动态填充Rails对象的属性?



例如,我将以下两个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

最新更新