I recently followed a tutorial about nested forms by Ryan Bates and did basically the same thing as he did just with other names. I wanted to nest assignments in the order form and I would like to build an assignment for every bun to that order and the user should put a count in the form.
So my controller looks like this
def new
#order = Order.new
#buns = Bun.all
#buns.each do |bun|
#order.assignments.build(:bun_id => bun.id)
end
end
And the _form partial looks like this
<%= form_for(#order) do |f| %>
<div class="field">
<%= f.label :user_id %><br />
<%= f.number_field :user_id %>
</div>
<div id="assignments" class="field">
<% f.fields_for :assignments do |builder| %>
<div id="assignment" class="field">
<%= builder.label :count, "Anzahl" %>
<%= builder.text_field :count %>
<%= builder.object.bun_id %>
<% end %>
</div>
</div>
<div class="field">
<%= f.label :due_to %><br />
<%= f.datetime_select :due_to %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The Order model has this part
has_many :assignments
has_one :user
accepts_nested_attributes_for :assignments
And the Assignments model this one:
attr_accessible :bun_id, :order_id, :count
belongs_to :bun
belongs_to :order
As i log the assignments out there are all, which should be build, so why weren't the fields rendered?
Thanks for your help!
You are missing an equal sign (=) in your erb :
<%= f.fields_for :assignments do |builder| %>
Related
My models
class Game < ApplicationRecord
has_many :rounds
accepts_nested_attributes_for :rounds
end
class Round < ApplicationRecord
belongs_to :game
end
controller
def new
#game = Game.new
3.times { #game.rounds.build }
end
view
<%= form_with scope: :game, url: games_path, local: true do |form| %>
<p>
<%= form.label :title %><br>
<%= form.text_field :title %>
</p>
<p>
<%= form.label :game_date %><br>
<%= form.date_field :game_date %>
</p>
<ul>
<%= form.fields_for :rounds do |builder| %>
<li>
<%= builder.label :title %>
<%= builder.text_field :title %>
<%= builder.label :order %>
<%= builder.text_field :order %>
</li>
<% end %>
</ul>
<p>
<%= form.submit %>
</p>
<% end %>
The above code only generates one "round" of record when new is building 3 records.
I am on rails 5.2.1
It is because you have a different object (formbuilder) when using form.
<%= form_with model: #game, local: true do |form| %>
Or
<%= form_with scope: #game, url: games_path, local: true do |form| %>
instead of
<%= form_with scope: :game, url: games_path, local: true do |form| %>
which produces the desire result. Have a look at this blog for better understanding.
It turns out you have to use form_for instead of the new form_with.
Rails 5.0.1
Devise 4.2.0
Hello, I'm building an app in which the user must fill a form to sign up, which includes the registration info for devise, and some personal info por their profile. I have made the models for user and profile, established their one to one relation, and added accept_nested_attributes_for :profile inside the user. I have also modified the registrations views to include f.fields_for for the profile, and until that point everything seems to work fine.
But, when I try to create a new user, and fill the required information, I get an error inside the view (from devise I guess) saying:
1 error prohibited this user from being saved
Profile user must exist
I have already followed many guides on how to create a nested form with devise, and none of them seem to have this issue, and I have also searched a lot with no answer. Here are some snippets from my registration controller, user and profile model, and registrations/new view:
registrations_controller
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
def new
build_resources({})
resource.build_profile
respond_with self.resource
end
protected
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up,
keys: [:email, :password,
:password_confirmation,
profile_attributes: [:name, :art_name,
:birth_date, :location]])
end
User model
class User < ApplicationRecord
has_one :profile, dependent: :destroy
before_create :build_profile
accepts_nested_attributes_for :profile
# Devise configuration.....
end
Profile model
class Profile < ApplicationRecord
belongs_to :user
end
Registrations/new view
<h2>Nueva Cuenta</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= f.fields_for :profile do |b| %>
<div class="field">
<%= b.label :name, "Nombre" %><br />
<%= b.text_field :name %>
</div>
<div class="field">
<%= b.label :art_name, "Nombre artistico" %><br />
<%= b.text_field :art_name %>
</div>
<div class="field">
<%= b.label :birth_date, "Fecha de nacimiento" %><br />
<%= b.date_field :birth_date %>
</div>
<div class="field">
<%= b.label :location, "Ubicacion" %><br />
<%= b.text_field :location %>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true %>
</div>
<div class="field">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "off" %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "off" %>
</div>
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>
My guess is that it has something to do with the sanitizers, I'm not completely sure how do I pass each attribute through, since most of the guides that explained this did with an older version of devise.
Thanks for your attention.
in your profile model, try this:
belongs_to :user, optional: true
it works for me
i need your help to create parent-child relation.
i have a problem to make the create of the child working fine.
this is the model:
class Nccheklist < ActiveRecord::Base
has_many :children, class_name: "Nccheklist", foreign_key: "parent_id"
belongs_to :parent, class_name: "Nccheklist"
def has_parent?
parent.present?
end
def has_children?
children.exists?
end
end
the controller:
def create
#nccheklist = Nccheklist.new(nccheklist_params)
if #nccheklist.save
redirect_to nccheklists_url, notice: 'Nccheklist was successfully created.'
else
render :new
end
end
and the view :
<%= form_for(#nccheklist) do |f| %>
<% if #nccheklist.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#nccheklist.errors.count, "error") %> prohibited this nccheklist from being saved:</h2>
<ul>
<% #nccheklist.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div>
<%= f.collection_select(:parent_id, #rootcat, :id, :name) %>
</div>
<br/><br/>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
when i submit the form, parent_id always equal null on database !
can someone help me please.
thanks.
add the following to the class definition
accepts_nested_attributes_for :children, allow_destroy: true
I'm using nested_attributes and trying to implement the add/remove fields on-the-fly throu ajax following Ryan Bates screencast about Nested Model (#196)
Doing this, it won't work, but when removing the "link_to_add_fields" line, it works fine.
The problem is that I'm don't know if I doing this all associations right.
<%= form_for(#item) do |f| %>
<% if #item.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#item.errors.count, "error") %> prohibited this item from being saved:</h2>
<ul>
<% #item.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :item_type_id %><br />
<%= f.select :item_type_id, #item_types.collect { |p| [ p.title, p.id ]} %>
<br />
<%= f.fields_for :item_parts do |parts_form| %>
<%= render "item_part_fields", :p => parts_form %>
<% end %>
</div>
<%= link_to_add_fields "Add Part", f, :part %>
<div class="actions">
<%= button_for "Save Item", :class => 'positive pill button', :button_type => 'submit' %>
</div>
<% end %>
Actually my models are:
"ItemPart" model:
class ItemPart < ActiveRecord::Base
belongs_to :item
belongs_to :part
end
"Item" model:
class Item < ActiveRecord::Base
belongs_to :item_type
has_many :item_parts
has_many :parts, :through => :item_parts
accepts_nested_attributes_for :item_parts, :allow_destroy => true
after_save :save_id
validates :title, :presence => true
def save_id
item_part_attributes = [ { :item_id => self.id } ]
end
end
"Part" model:
class Part < ActiveRecord::Base
has_one :part_type
has_many :item_parts
has_many :items, :through => :item_parts
end
The error I'm getting doing this way:
undefined method `klass' for nil:NilClass
Extracted source (around line #26):
23: <%= render "item_part_fields", :p => parts_form %>
24: <% end %>
25: </div>
26: <%= link_to_add_fields "Add Part", f, :item %>
27: <div class="actions">
Application trace
app/helpers/application_helper.rb:44:in `link_to_add_fields'
app/views/items/_form.html.erb:26:in `block in _app_views_items__form_html_erb__1418129287024756954_2169222480__3228169100620818569'
app/views/items/_form.html.erb:1:in `_app_views_items__form_html_erb__1418129287024756954_2169222480__3228169100620818569'
app/views/items/edit.html.erb:3:in `_app_views_items_edit_html_erb___1857878264245794505_2169270380_890290209246324491'
Application_helper.rb
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new # error line :44
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to_function(name, "add_fields(this, '#{association}', '#{escape_javascript(fields)}')" )
end
After hours and hours doing tests and googling a lot, I get it finally solved.
Seems that I'd to use the same local variable name to render the partial used for the form_for and then use it again as a helper method parameter needed. (In this case, "f" variable.)
I pasting the cleaning working code below
<%= form_for(#item) do |f| %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<p>
<%= f.label :item_type_id %><br />
<%= f.select :item_type_id, #item_types.collect { |p| [ p.title, p.id ]} %><br />
</p>
<p>
<%= f.fields_for :item_parts do |parts_form| %>
<%= render "item_part_fields", :f => parts_form %>
<% end %>
</p>
<p><%= link_to_add_fields "Add Part", f, :item_parts %></p>
<p><%= button_for "Save Item", :class => 'positive pill button', :button_type => 'submit' %></p>
<% end %>
Hope this going to help someone someday :)
There is a mistake in your add more button. This should be,
<p><%= link_to_add_fields "Add Part", f, :item_parts %></p>
The association name should be the table name on which have many relation is.
I'm tring to set values for two models that have a has_one association using accepts_nested_attributes_for, but nothing in the fields_for is being shown on the view.
I have confirmed the same code works on Rails 2.x, and it works fine when its a has_many.
Code below.
Model
class Parent < ActiveRecord::Base
has_one :child
accepts_nested_attributes_for :child
end
class Child < ActiveRecord::Base
belongs_to :parent
end
Controller
def new
#parent = Parent.new
#parent.build_child
end
View
<%= form_for #parent do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<% f.fields_for :child do |builder| %>
<%= builder.label :childname %>
<%= builder.text_field :childname %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
..And after copying that and looking at it, that's a horrible class name.
In rails 3 you should use (notice the equal sign in <%=):
<%= f.fields_for [...]
instead of :
<% f.fields_for
same goes with form_for