2011-11-20 37 views
0

說,例如我通過以下兩個HTTP POST參數到我的Rails應用程序:是否可以使用同名的HTTP參數動態填充Rails對象的屬性?

fname=john&lname=doe 

而我的應用程序內的控制器將params哈希表傳遞給定義爲「人」模型類:

Class Person 
    attr_accessor :fname, :lname 

    def initialize(params) 
    @fname = params[:fname] 
    @lname = params[:lname] 
    end 
end 

正如你所看到的,我用包含在params散列中的值初始化一個Person對象。請注意,屬性和參數的名稱是相同的。

顯然,在現實世界的例子中,我會在我的對象中有更多的屬性,所以使用上面的初始化方法可能會變得單調乏味。

因此,我想知道是否有一種方法來動態填充具有相同名稱的HTTP參數的對象的屬性?

回答

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 

然而,這並不是一個非常實用的應用;在控制器上使用訪問器實例變量的理由很少,遠不足以至於您需要使用此方法。

相反,您似乎想要做的是創建一個Person模型的實例,並從params開始批量分配屬性。軌已經這樣做了,也就是默認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 

你可以閱讀更多有關質量分配安全here


如果要將此行爲添加到一組非的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

+0

很好的答案,謝謝。我已經接受了答案,但經過一些考慮後,我決定選擇使用初始化每個屬性的'醜陋'方法。最終,模型中不會有那麼多,因此我認爲這樣做更加可讀,而且這種方法很「醜」。 – ryan

相關問題