Mass-assign protected attributes (Nested-form) Ruby/Rails - ruby-on-rails

I'm trying to create a nested form but i got this error when trying to assign the parameters. I read a bunch of similar posts but cant figure out the problem. What could be wrong?
Can't mass-assign protected attributes: detalle_poliza
My models:
poliza_contable.rb
class PolizaContable < ActiveRecord::Base
has_many :detalle_polizas
accepts_nested_attributes_for :detalle_polizas
attr_accessible :concepto_poliza, :estatus, :fecha_aplicacion, :fecha_poliza, :no_poliza, :tipo, :tota_de_cargos, :total_de_abonos
end
detalle_poliza.rb
class DetallePoliza < ActiveRecord::Base
belongs_to :cuenta_contable
belongs_to :poliza_contable
attr_accessible :abono, :cargo,:cuenta_contable_id, :poliza_contable_id, :user_id, :id, :updated_at, :created_at
end
My form:
<%= form_for #poliza_contable, :html => { :class => 'form-horizontal' } do |f| %>
## OTHER FIELDS
<%= f.fields_for :detalle_poliza_attributes do |builder| %>
<% render :partial => "detalle_polizas/form", :locals => { :f => builder } %>
<% end %>
<% end %>
Rendered form:
<div class="control-group">
<%= f.label :cargo, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :cargo, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :abono, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :abono, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :poliza_contable_id, :class => 'control-label' %>
<div class="controls">
<%= f.number_field :poliza_contable_id, :class => 'number_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :cuenta_contable_id, :class => 'control-label' %>
<div class="controls">
<%= f.number_field :cuenta_contable_id, :class => 'number_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :user_id, :class => 'control-label' %>
<div class="controls">
<%= f.number_field :user_id, :class => 'number_field' %>
</div>
</div>
Request Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"mI23Nnj4oPX+IW3mCvvIV7Auij+pjX/a7bl/HsudEW8=",
"poliza_contable"=>{"tipo"=>"Diario",
"concepto_poliza"=>"",
"fecha_poliza"=>"2012-06-25",
"detalle_poliza"=>{"cargo"=>"34",
"abono"=>"34",
"poliza_contable_id"=>"34",
"cuenta_contable_id"=>"34",
"user_id"=>"1"}}
"commit"=>"Create Poliza contable"}`
I'll appreciate any comment to fix it.

With according to railscast 196 Nested Model Form Part 1 you need to allow DetallePoliza attributes to be saved with parent. To achieve this goal just add attr_accessible :detalle_polizas_attributes to PolizaContable model:
poliza_contable.rb
class PolizaContable < ActiveRecord::Base
has_many :detalle_polizas
accepts_nested_attributes_for :detalle_polizas
attr_accessible :concepto_poliza, :estatus, :fecha_aplicacion, :fecha_poliza, :no_poliza, :tipo, :tota_de_cargos, :total_de_abonos, :detalle_polizas_attributes
end

Just making some research, finally found the nestes_form gem
Its a very straight forward implementation!
Hope it helps someone.

Related

Failed to save the new associated seo_setting on has_one association

I have 2 models:
class Page < ApplicationRecord
enum page_type: STATIC_PAGE_TYPES, _suffix: true
has_one :seo_setting
accepts_nested_attributes_for :seo_setting, update_only: true
validates :title, :subtitle, length: { maximum: 50 }
validates :page_type, uniqueness: true
def to_param
"#{id}-#{page_type}".parameterize
end
end
and
class SeoSetting < ApplicationRecord
mount_uploader :og_image, SeoSettingsOgImageUploader
belongs_to :page
validates :seo_title, :seo_description, :og_title, :og_description, :og_image, presence: true
end
My Page objects are created from the seeds.rb file, and when I want to edit them, I get an error: Failed to save the new associated seo_setting.
In the form I have this:
<div class="card-body">
<%= form_for([:admin, #page]) do |f| %>
<%= render 'shared/admin/error-messages', object: #page %>
<div class="form-group">
<%= f.label :title, t('admin.shared.title') %>
<%= f.text_field :title, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :subtitle, t('admin.shared.subtitle') %>
<%= f.text_field :subtitle, class: 'form-control' %>
</div>
<h3>SEO Settings</h3>
<%= f.fields_for :seo_setting, f.object.seo_setting ||= f.object.build_seo_setting do |form| %>
<div class="form-group">
<%= form.label :seo_title, t('admin.shared.seo_title') %>
<%= form.text_field :seo_title, class: 'form-control' %>
</div>
<div class="form-group">
<%= form.label :seo_description, t('admin.shared.seo_description') %>
<%= form.text_area :seo_description, class: 'form-control' %>
</div>
<div class="form-group">
<%= form.label :og_title, t('admin.shared.og_title') %>
<%= form.text_field :og_title, class: 'form-control' %>
</div>
<div class="form-group">
<%= form.label :og_description, t('admin.shared.og_description') %>
<%= form.text_area :og_description, class: 'form-control' %>
</div>
<div class="form-group">
<%= form.label :og_image, t('admin.shared.og_image') %>
<div class="row">
<div class="col-lg-12">
<%= image_tag(form.object.og_image.url, style: 'width: 100px') if form.object.og_image? %>
</div>
</div>
<%= form.file_field :og_image %>
<%= form.hidden_field :og_image_cache %>
</div>
<% end %>
<div class="form-group">
<%= f.submit t('admin.actions.submit'), class: 'btn btn-success' %>
<%= link_to t('admin.actions.cancel'), admin_page_path(#page) , class: 'btn btn-default' %>
</div>
<% end %>
</div>
If I remove validations from my SeoSetting model, everything is working. It seems Rails doesn't like this part: f.object.build_seo_setting, because it creates a record in my database. Any ideas of how can I solve this issue? Thanks ahead.
Just had to change this line:
<%= f.fields_for :seo_setting, f.object.seo_setting ||= f.object.build_seo_setting do |form| %>
for this one:
<%= f.fields_for :seo_setting, #page.seo_setting.nil? ? #page.build_seo_setting : #page.seo_setting do |form| %>
Looks as if the problem lies here:
accepts_nested_attributes_for :seo_setting, update_only: true
in that you only allow the updating of the seo_setting on update.
Then, when you use this code:
f.object.seo_setting ||= f.object.build_seo_setting
You're falling back to a new seo_setting if the associated object is missing.
For this to work, you'll need to either remove the update_only: true, or only render the fields for the association if the seo_setting already exists.
Accepted answer, a conditional inside fields_for line, by OP, works also with polymorphic association and nested form (fields_for). Thnx Alex.

Rails form_for select default option

I have a form_for select where the options are being defined from within the model. I am trying to get it to display a placeholder option but cannot figure out how to.
The Model:
class Factoid < ActiveRecord::Base
attr_accessible :description, :name, :title
validates_presence_of :description, :name, :title
validates_uniqueness_of :title
NAMES = "Angela", "Geordie", "Jared", "Jennifer", "Kevin", "Matthew", "Oscar", "Owen", "Regina", "Todd", "Vaibhavi", "Zack"
UNRANSACKABLE_ATTRIBUTES = ["id", "updated_at"]
def self.ransackable_attributes auth_object = nil
(column_names - UNRANSACKABLE_ATTRIBUTES) + _ransackers.keys
end
end
The Form:
<%= form_for #factoid, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :title, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :title, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :description, :class => 'control-label' %>
<div class="controls">
<%= f.text_area :description, :class => 'text_area' %>
</div>
</div>
<div class="control-group">
<%= f.label :name, :class => 'control-label' %>
<div class="controls">
<%= f.select :name, :collection => Factoid::NAMES %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
factoids_path, :class => 'btn' %>
</div>
<% end %>
The second issue is that the dropdown menu is displaying the word "collection" at the top of it (See screenshot below). How do I get read of that. Ideally I want to have a dropdown menu with a placeholder of "Names" that is also displayed at the top when the dropdown menu is opened.
For your text field try something like:
<%= f.text_field :title, :class => 'text_field', value: 'my_default_value' %>
for your select try:
<%= f.select :name, Factoid::NAMES %>
See the docs for select and the rails guide for typical usage (I think the method I've shown you will not work upon submitting the form, see the guides linked for explanation, I'm not sure though).

Why won't my has_one relationship work

I have a few models Score ScoreAuthority ScoreColor and ScoreType. Score has_one authority, color, and type. Authority, color, and type each belong_to score. I am having trouble creating the form for Score.
I want users to create this relationship from Scores and everyone seems to handle only the reverse scenario creating from authorities, colors, types forms. What I mean specifically is for example:
Authorities
- foo
- bar
Colors
- red
- blue
I want the use to go into Score, chose to create a new score and then select foo from the drop down list, blue from the colors list, enter a score and submit. Authorities, colors and types will not change much and it would make any sense for the user to select Score from each of those.
When I currently do that I get the following error:
ScoreAuthority(#2248480380) expected, got String(#2155957040)
score/_form.html.erb
<%= form_for #score, :html => { :class => 'form-horizontal' } do |f| %>
<div class="control-group">
<%= f.label :product_id, "Products", :class => 'control-label' %>
<div class="controls">
<%= f.collection_select(:product_id, Product.order(:name), :id, :name) %>
</div>
</div>
<div class="control-group">
<%= f.label :score_authority, "Score Authority", :class => 'control-label' %>
<div class="controls">
<%= f.collection_select :score_authority, ScoreAuthority.order(:name), :id, :name, {}, {:class=>'chosen'} %>
</div>
</div>
<div class="control-group">
<%= f.label :score_type, "Score Types", :class => 'control-label' %>
<div class="controls">
<%#= f.collection_select(:score_type, ScoreType.order(:name), :id, :name) %>
<%= f.collection_select :score_type, ScoreType.order(:name), :id, :name, {}, {:class=>'chosen'} %>
</div>
</div>
<div class="control-group">
<%= f.label :score_color, "Score Types", :class => 'control-label' %>
<div class="controls">
<%= f.collection_select :score_color, ScoreColor.order(:name), :id, :name, {}, {:class=>'chosen'} %>
</div>
</div>
<div class="control-group">
<%= f.label :notation, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :notation, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= f.label :value, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :value, :class => 'text_field' %>
</div>
</div>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
scores_path, :class => 'btn' %>
</div>
<% end %>
score_authorities, score_colors, score_types tables all have score_id as a column. Each of these models also has belongs_to :score.
The score model
has_one :score_authority
has_one :score_type
has_one :score_color
Not sure what I am doing wrong here, any help would be appreciated. Thanks!
you should use :score_authority_id instead of :score_authority in form
<%= f.collection_select :score_authority_id, ScoreAuthority.order(:name), :id, :name, {}, {:class=>'chosen'} %>
<%= f.collection_select :score_color_id, ScoreColor.order(:name), :id, :name, {}, {:class=>'chosen'} %>
<%= f.collection_select :score_color_id, ScoreColor.order(:name), :id, :name, {}, {:class=>'chosen'} %>
see this How do I create the view for the has_one association? for more detail
or you can try
class Score
has_one :score_authority
accepts_nested_attributes_for :score_authority
end
<%= form_for #score ... do |f| %>
...
<%= f.fields_for :score_authority do |b| %>
<%= b.collection_select :id, ScoreAuthority.all, :id, :name %>
...
<% end %>
...
<% end %>

nested fields_for form not displaying

I'm using a nested fields_for that isn't displaying, any ideas? I think my relationships are setup correctly but the field isn't rendering at all.
MODEL EXCERPT
class DaysEvent < ActiveRecord::Base
belongs_to :event
belongs_to :location
accepts_nested_attributes_for :event
TRUNCATED VIEW
<%= form_for(DaysEvent.new, :remote => true, :html => { :class => "form-inline"} ) do |f| %>
<fieldset>
<%= f.fields_for :event do |event_form| %>
<div class="control-group">
<%= event_form.label :allow_user_to_suggest_dates, :class => 'control-label' %>
<div class="controls">
<%= event_form.check_box :allow_user_to_suggest_dates, :class => 'text_field' %>
</div>
</div>
</fieldset>
<% end %>

Fields_for disappear when adding accepts_nested_attributes_for

I'm doing a nested form in Rails 3.2.5, but when I add the accepts_nested_attributes_for my fields_for disappear (they just stop showing in my form).
This are my models:
class Product < ActiveRecord::Base
attr_accessible :title, :description, :variants_attributes
has_many :variants
accepts_nested_attributes_for :variants
validates :title, presence: true
end
My second model is
class Variant < ActiveRecord::Base
belongs_to :product
attr_accessible :price, :sku, :weight, :inventory_quantity, :product_id
end
And in my view I have
<%= form_for [:admin, #product], :html => {:multipart => true} do |f| %>
<%= render 'admin/shared/error_messages', object: f.object %>
<fieldset>
<legend>Producto Nuevo</legend>
<div class="control-group">
<%= f.label :title, 'Título', class: 'control-label' %>
<div class="controls">
<%= f.text_field :title %>
</div>
</div>
**<%= f.fields_for :variants do |variant| %>
<%= render 'inventory_fields', f: variant %>
<% end %>**
<div class="actions">
<%= f.submit 'Guardar', class: 'btn btn-primary' %>
</div>
<% end %>
_inventory_fields.html.erb
<div class="control-group">
<%= f.label :inventory_quantity, 'How many are in stock?', class: 'control-label' %>
<div class="controls">
<%= f.text_field :inventory_quantity, class: 'span1', value: '1' %>
</div>
</div>
The part between the ** is the one that is not being printed. And when I remove accepts_nested_attributes_for in my Product model fields_for start showing again but my form won't work.
What's happening?!?!
In the controller new action call
#product.varients.build
That should create 1 in memory varient in the product varient collection and it should bind to the fields for

Resources