ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign

Hej,

uruchamiam testy w aplikacji i aplikacja wypluwa:

ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: id, created_at, updated_at

w modelu mam:

attr_accessible :active, :description, :query, :title, :recipient_ids, :frequency_ids, :email_form, :yesterday, :category_ids

rails: 3.2.11
ruby: ruby 1.9.3p362 (2012-12-25 revision 38607) [x86_64-linux]

Czy to jest jakis bug ktory musze ominac poprzez dodanie do modelu:

attr_accessible :id, :created_at, :updated_at, :active, :description, :query, :title, :recipient_ids, :frequency_ids, :email_form, :yesterday, :category_ids

Nie, nie jest to żaden bug. Prawdopodobnie nigdy nie powinieneś przypisywać tych atrybutów ręcznie swojemu modelowi. Jeśli to robisz, prawdopodobnie robisz to źle.

Jeśli robisz gdzieś w teście Model.new(id: 1, active: true … created_at: 1.day.ago) bądź Model.find(1).update_attributes(id: 1 …), to jest to Twój błąd.

Jeśli natomiast generujesz formularz, upewnij się że nie ma on pól dla id, created_at i updated_at

uzywam takie metody:

[code]test “should create script” do
assert_difference(‘Script.count’) do
post :create, script: @script.attributes
end

assert_redirected_to script_path(assigns(:script))

end[/code]

OK,

zakomentowalem linijke w environments/test.rb:

Raise exception on mass assignment protection for Active Record models

#config.active_record.mass_assignment_sanitizer = :strict

[quote=wlodi]OK,

zakomentowalem linijke w environments/test.rb:

Raise exception on mass assignment protection for Active Record models

#config.active_record.mass_assignment_sanitizer = :strict[/quote]
Ale dlaczego? Skoro może to się pojawić w produkcji, to czemu wyłączasz w testach?

No to zobacz co Ci zwraca metoda @script.attributes.Prawdopodobnie z id, created_at i updatede_at.

Problem w tym ze ani w _form view, kontrolerze i modelu nie uzywam tych atrybutow bezsposrednio. Uzywam Bootstrap ktory wygenrowal views wlasnie z tymi atrybutami ale usunalem wszystko z widokow.

_form:

[code]<%= form_for @script, :html => { :class => ‘form-horizontal’ } do |f| %>

<%= f.label :title, :class => 'control-label' %>
<%= f.text_field :title, :class => 'text_field', :required => true %>
<%= f.label :description, :class => 'control-label' %>
<%= f.text_area :description, :class => 'text_area', :required => true, :rows => 3 %>
<%= f.label :query, :class => 'control-label' %>
<%= f.text_area :query, :class => 'text_area', :required => true %>
<%= f.label :recipients, :class => 'control-label' %>
<% Recipient.all.each do |recipient| %> <%= check_box_tag "script[recipient_ids][]", recipient.id, @script.recipients.include?(recipient) %> <%= recipient.name %> <% end %>
<%= f.label :frequencies, :class => 'control-label' %>
<% Frequency.all.each do |frequency| %> <%= check_box_tag "script[frequency_ids][]", frequency.id, @script.frequencies.include?(frequency) %> <%= frequency.name %> <% end %>
<%= f.label :categories, :class => 'control-label' %>
<% Category.all.each do |category| %> <%= check_box_tag "script[category_ids][]", category.id, @script.categories.include?(category) %> <%= category.name %> <% end %>
<%= f.label :email_form, :class => 'control-label' %>
<%= f.check_box :email_form, :class => 'checkbox' %>
<%= f.label :yesterday_date_in_excel, :class => 'control-label' %>
<%= f.check_box :yesterday, :class => 'checkbox' %>
<%= f.label :active, :class => 'control-label' %>
<%= f.check_box :active, :class => 'checkbox' %>
<%= f.submit nil, :class => 'btn btn-primary' %> <%= link_to t('.cancel', :default => t("helpers.links.cancel")), scripts_path, :class => 'btn' %>
<% end %>[/code] model: [code]class Script < ActiveRecord::Base attr_accessible :active, :description, :query, :title, :recipient_ids, :frequency_ids, :email_form, :yesterday, :category_ids end[/code] kontroler: [code]def new @script = Script.new end

def create
@script = Script.create(params[:script])
if @script.save
redirect_to script_path(@script)
else
render :action => ‘new’
end
end

def edit
@script = Script.find(params[:id])
end

def update
@script = Script.find(params[:id])
params[:script][:recipient_ids] ||= []
params[:script][:frequency_ids] ||= []
if @script.update_attributes(params[:script])
redirect_to script_path(@script)
else
render :action => ‘edit’
end
end[/code]

@script.attributes zwraca mi:

{"id"=>144709932, "title"=>"Daily active script", "description"=>"This is daily active query", "query"=>"select max(created_at) from ids.track_offer_clicks", "active"=>true, "created_at"=>Fri, 08 Feb 2013 12:03:38 UTC +00:00, "updated_at"=>Fri, 08 Feb 2013 12:03:38 UTC +00:00, "email_form"=>false, "yesterday"=>false}

czyli id, created_at, update_at

Nie wiem dlaczego i gdzie jest blad. Mozna usunac te atrybuty z tego testu za pomoca metody slice, ale chcialbym tego uniknac. Gdzie jescze moga byc te atrybuty?

Polecam przestać się przejmować attr_protected i attr_accessible i zaczac uzywac https://github.com/rails/strong_parameters

post :create, script: @script.attributes

tu masz problem. @script.attributes co zwraca?

Hej,

@script.attributes zwraca mi:

{"id"=>144709932, "title"=>"Daily active script", "description"=>"This is daily active query", "query"=>"select max(created_at) from ids.track_offer_clicks", "active"=>true, "created_at"=>Fri, 08 Feb 2013 12:03:38 UTC +00:00, "updated_at"=>Fri, 08 Feb 2013 12:03:38 UTC +00:00, "email_form"=>false, "yesterday"=>false}