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

rya*_*yan 0 ruby ruby-on-rails http

比如说我将以下两个HTTP POST参数传递给我的Rails应用程序:

fname=john&lname=doe
Run Code Online (Sandbox Code Playgroud)

在我的应用程序中,控制器会将params散列传递给'Person'模型类,定义为:

Class Person
  attr_accessor :fname, :lname

  def initialize(params)
    @fname = params[:fname]
    @lname = params[:lname]
  end
end
Run Code Online (Sandbox Code Playgroud)

如您所见,我使用params哈希中包含的值初始化Person对象.请注意,属性和参数的名称相同.

显然,在一个真实世界的例子中,我的对象中会有更多属性,因此使用上面的初始化方法可能会变得乏味.

因此,我想知道是否有一种方法可以使用相同名称的HTTP参数动态填充对象的属性?

cor*_*ard 7

您可以在控制器和模型中执行您所要求的操作.首先,举例说明这将如何与控制器一起使用:

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
Run Code Online (Sandbox Code Playgroud)

但是,这不是一个非常实际的应用; 没有理由在控制器上安装访问器实例变量,远远不足以使用此方法.

相反,您似乎想要做的是创建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
Run Code Online (Sandbox Code Playgroud)

请注意,默认情况下,所有模型属性都是可批量分配的.当用户可以操作某些字段(如关联)时,这可能是一个安全问题.在这种情况下,您可以在模型上列入白名单或黑名单属性,以防止此类安全漏洞:

class Person < ActiveRecord::Base
  attr_accessible :fname, :lname, :phone, :email
  # or
  attr_protected :non_user_changeable_attribute
end
Run Code Online (Sandbox Code Playgroud)

您可以在此处详细了解质量分配安全性.


如果要将此行为添加到一组非ActiveRecord类(没有protector属性),则可以阻止此模块并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
Run Code Online (Sandbox Code Playgroud)

这避免了在每个初始化程序中复制有些"丑陋"的代码.

通过:https://github.com/coreyward/typekit/blob/master/lib/typekit/base.rb