2012-12-03 56 views
2

我有一個功能,將嵌套屬性拆分爲數組,以便檢查唯一性並保存它們。問題是,我得到一個Can't mass-assign protected attributes: _destroy錯誤,因爲nested_form gem插入一個hidden_​​field來突出顯示哪些屬性應該被刪除。我該如何解決這個創建功能?

這裏的* Posts_Contoller.rb *創建功能:

def create 
    location_set = params[:post].delete(:locations_attributes) unless params[:post][:locations_attributes].blank? 

    @post = current_blogger.blog_posts.new(params[:post]) 

    @post.locations = Location.find_or_initialize_location_set(location_set) unless location_set.nil? 


if @post.save 
    redirect_to @post, notice: 'Blog post was successfully created.' 
    else 
    render action: "new" 
    end 
end 

下面是location.rb功能:

def self.find_or_initialize_location_set(location_set) 
    #create a locations array 
    locations = [] 
     locations = locations.delete_if { |elem| elem.flatten.empty? } 

    location_set.each do |key, location| 
     locations << find_or_initialize_by_name(location) 
    end 

locations 

end 

和這裏的日誌:

Started POST "/blog/posts" for 127.0.0.1 at 2012-12-03 17:31:54 +0000 
Processing by Blogit::PostsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"r74iCzC4tJgVI6FiCEH7XzfiTmaqKihF5JSs7Ow3MSI=", "post"=>{"title"=>"This 
is a post about Paris", "body"=>"This is a post about ParisThis is a post about Paris 
This is a post about ParisThis is a post about Paris", "tag_list"=>"", 
"locations_attributes"=>{"0"=>{"_destroy"=>"false", "name"=>"Paris", "longitude"=>"2.3522219", "latitude"=>"48.856614"}, "1354555760002"=>{"_destroy"=>"false", "name"=>"Los Angeles", "longitude"=>"-118.5155901", "latitude"=>"3 
4.03563310000001"}}}, "_wysihtml5_mode"=>"1", "name"=>"losds", "legname"=>"Los Angeles", "longitude"=>"-118.5155901", "latitud 
e"=>"34.03563310000001", "commit"=>"Submit"} 

User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1 
ActsAsTaggableOn::Tag Load (0.1ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" W 
HERE "taggings"."taggable_id" IS NULL AND "taggings"."taggable_type" = 'Blogit::Post' AND (taggings.context = 'tags' AND taggings.tagger_id IS NULL) 

Location Load (0.1ms) SELECT "locations".* FROM "locations" WHERE "locations"."name" = 'Paris' LIMIT 1 
LOGGER LOCATIONS ARE[#<Location id: 768, name: "Paris", latitude: #<BigDecimal:7f86aadf6230,'0.48856614E2',18(45)>, longitude: 
#<BigDecimal:7f86aadf5f60,'0.23522219E1',18(45)>, post_id: nil, created_at: "2012-12-01 17:27:33", updated_at: "2012-12-01 17 
:27:33", notes: nil>] 
Location Load (0.2ms) SELECT "locations".* FROM "locations" WHERE "locations"."name" = 'Los Angeles' LIMIT 1 
Completed 500 Internal Server Error in 97ms 

    ActiveModel::MassAssignmentSecurity::Error (Can't mass-assign protected attributes: _destroy): 
    app/models/location.rb:23:in `block in find_or_initialize_location_set' 
    app/models/location.rb:21:in `each' 
    app/models/location.rb:21:in `find_or_initialize_location_set' 
    app/controllers/blogit/posts_controller.rb:79:in `create' 

對於我如何適應這種情況的任何建議都包括刪除功能在之前的參數,但我沒有得到Can't mass-assign protected attributes: _destroy錯誤?

謝謝!

回答

0

你可以這樣做:

def self.find_or_initialize_location_set(location_set) 
    #create a locations array 
    locations = [] 
    locations = locations.delete_if { |elem| elem.flatten.empty? } 

    location_set.each do |key, location| 
    if location.delete(:_destroy) == "1" 
     locations.delete_if {|elem| elem[:name] == location[:name]} 
    else 
     locations << find_or_initialize_by_name(location) 
    end 
    end 

    locations 
end 

呼籲相關的哈希delete將改變哈希,並返回你刪除值(或nil如果不存在)。

或者,如果您需要在初始化位置刪除,你可以做到這一點有:

def find_or_initialize_by_name_with_delete(location) 
    if location.delete(:_destroy) 
    do_delete 
    end 

    find_or_initialize_by_name(location) 
end 
+0

嗨肖恩,對不起,我只是測試了這一點,並意識到這實際上發送所有屬性到刪除功能。我需要它拿起像'如果location.attributes = {:_destroy =>「1」}'任何想法? –

+0

您是否在刪除時使用了':_destroy'?我錯誤地刪除了......看到我的編輯。當你在一個散列上調用'delete'時,它應該通過刪除這個鍵並返回這個被刪除的鍵來修改這個散列。所以,你可以有'deleted_key = location.delete(:_銷燬)'和':_destroy'將從'location'被刪除並分配給'deleted_key'。 –

+0

嗨,是的,我注意到並改變了它。問題是所有的屬性有一個「破壞」屬性,但如果它是被刪除,然後「_destroy」設置爲1。這是它目前是如何讀取: 'location_set.each做|鍵,位置| 如果location.delete(:_銷燬) locations.delete_if {| ELEM | ELEM =「‘_destroy’=>‘1’」} end' 我認爲這是撿的所有屬性,因爲它們都具有摧毀的。有任何想法嗎? –

3

您可以通過添加給你的定位模型擺脫這種錯誤的:

# NOT PERSISTENT 
attr_accessor :_destroy 
# ... 
attr_accessible :_destroy 

沒有這個_destroy屬性進行保護,防止mass assignment,當你嘗試反正賦值給它拋出一個異常。

+2

這是一個骯髒的解決辦法,他應該檢查nested_form文檔的解決方案 –

+1

您好,感謝您的答覆!我試着添加上面的,並得到以下錯誤:未知屬性:_destroy。這種感覺也是一種混亂的工作。如果可能的話,我寧願通過模型中的一些if函數來實現它? –

+0

我更新了答案 - 至少現在應該可以工作 – krichard