Rails fields_for won't see my field inside - ruby-on-rails

I am trying to create two object at the same time. The best approach I have is to used fields_for. and the relationship is has_many.
model/location.rb
attr_accessible :address, :customer_id, :event_id, :latitude, :longitude
belongs_to :customer
belongs_to :event
model/event.rb
attr_accessible :locations_attributes
has_many :locations, :dependent => :destroy
accepts_nested_attributes_for :locations
The form is has follow:
<%= form_for(#event) do |f| %>
...
<%= f.fields_for :locations do |e| %>
<%= e.text_field :longitude %>
<%= e.text_field :latitude %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My fields won't show up, I have followed the documentation has_many from this section http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
and notice if in my f.fields_for :locations change it to singular than the fields will show up but i won't be able to create it because i am not allow to modify the locations_attributes.
UPDATE:
If i singular it. I change this to my event model
attr_accessible :description, :title, :location_attributes
The error is like this
app/controllers/events_controller.rb:60:in `new'
app/controllers/events_controller.rb:60:in `create'
My controller is like this
line 60: #event = Event.new(params[:event])

You should be doing this in your form: (location not locations)
<%= f.fields_for :location do |e| %>
<%= e.text_field :longitude %>
<%= e.text_field :latitude %>
<% end %>
and in your model event.rb
attr_accessible :description, :title, :locations_attributes (locations not location)

Related

Create multiple new records from checkboxes in form using nested attributes in Rails

I'm trying to come up with a contact form that creates a contact record and potentially multiple location records, if multiple locations are checked in a list of checkboxes. I thought of having all location records created and then destroyed, if they aren't checked. I don't think that's optimal though.
I'm using many to many relationships in the models.
This is what they look like at the moment:
contact.rb
class Contact < ApplicationRecord
has_many :contact_locations, dependent: :destroy
has_many :locations, through: :contact_locations
accepts_nested_attributes_for :contact_locations, allow_destroy: true, reject_if: :empty_location?
private
def empty_location?(att)
att['location_id'].blank?
end
end
location.rb
class Location < ApplicationRecord
has_many :locations, dependent: :destroy
has_many :contacts, :through => :contact_locations
has_many :contact_locations
end
contact_location.rb
class ContactLocation < ApplicationRecord
belongs_to :location
belongs_to :contact
end
contacts_controller.rb
def new
#contact = Contact.new
#locations = Location.all
4.times {#contact.contact_locations.new}
end
private
def contact_params
params.require(:contact).permit(:name, :phone, ..., contact_locations_attributes: [:location_ids])
end
new.html.rb
<%= form_with model: #contact do |f| %>
...
<%= #locations.each do |location| %>
<%= f.fields_for :contact_locations do |l| %>
<%= l.check_box :location_id, {}, location.id, nil %><%= l.label location.name %>
<% end %>
<% end %>
...
<% end %>
Does anyone how to make it work properly?
I'm working on Ruby 2.5.1 and Rails 5.2.1.
Thanks a lot.
I think your solution is the form objects pattern.
You can have something like this:
<%= form_for #user do |f| %>
<%= f.email_field :email %>
<%= f.fields_for #user.build_location do |g| %>
<%= g.text_field :country %>
<% end %>
<% end%>
And convert it in something more readable that permits you to instance the locations inside the registration object, checking the value of the checkboxes.
<%= form_for #registration do |f| %>
<%= f.label :email %>
<%= f.email_field :email %>
<%= f.input :password %>
<%= f.text_field :password %>
<%= f.input :country %>
<%= f.text_field :country %>
<%= f.input :city %>
<%= f.text_field :city %>
<%= f.button :submit, 'Create account' %>
<% end %>
Here you will find how to apply the pattern: https://revs.runtime-revolution.com/saving-multiple-models-with-form-objects-and-transactions-2c26f37f7b9a
I ended up making it work with Kirti's suggestion on the following question:
Rails Nested attributes with check_box loop
It turns out I needed to make a small adjustment in my form's fields_for tag.
Thanks a lot the help!

Nested form undefined method `model_name'

I have nested forms dealing with 3 models. Job, Employer, User
The form on the jobs controller needs to create a job, employer and user.
The Job and Employer forms are working correctly, however when I add the User nested form I get the error "undefined method `model_name' for NilClass:Class"
I'm completely confused as to why.
Here is my code:
Job Model
attr_accessible :category, :employer_id, :employer_attributes, :user_attributes
belongs_to :employer
accepts_nested_attributes_for :employer, :user
has_many :applications
has_many :users, :through => :applications
Employer model
attr_accessible :companyname, :email, :logo, :password, :url
has_many :jobs
belongs_to :user
User Model
attr_accessible :admin, :cv, :name, :password, :website, :password_confirmation
has_many :applications
has_many :jobs, :through => :applications
has_one :employer
_form.html.erb
<%= form_for(#job) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.fields_for :employer do |builder| %>
<%= builder.label :companyname, "Company Name" %>
<%= builder.text_field :companyname %>
<% end %>
<%= f.fields_for :user do |builder| %>
<%= builder.label :email, "Email" %>
<%= builder.text_field :email %>
<%= builder.label :password, "Password" %>
<%= builder.text_field :password %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Job Controller
def new
#job = Job.new
#job.employer = #job.build_employer
#job.user = #job.build_user
To doesn't look like your Job model has a user method. You may need to add
belongs_to :user

Nested form not rendering Rails 3.2

The nested form in the view just won't render, unless I remove the f attribute, in which case the submit button will not work. I have two models, job and employer. I've been following the railscast here
job.rb
attr_accessible :title, :location, :employers_attributes,
belongs_to :employers
accepts_nested_attributes_for :employers
employer.rb
attr_accessible :companyname, :url
has_many :jobs
jobs_controller.rb
def new
#job = Job.new
#employer = Employer.new
end
_form.html
<%= form_for(#job) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :location %>
<%= f.text_field :location %>
<%= f.fields_for :employers do |builder| %>
<%= builder.label :companyname, "Company Name" %>
<%= builder.text_field :companyname %>
<%= builder.label :url, "Web Address" %>
<%= builder.text_field :url %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Any input would be brilliant - thanks
This happens because your job has no employers.
Change your code to this:
def new
#job = Job.new
#job.employer = #job.build_employer
end
In your job.rb change:
attr_accessible :title, :location, :employer_attributes,
belongs_to :employer
accepts_nested_attributes_for :employer
This line:
belongs_to :employers
Should be singulars:
belongs_to :employer
With this association you not need nested form you can use select for pick employer for each job.
But if you need many employers for each job and each job can have many employers see this screencast

form_for with ckeckbox_tag from other model

I'm new to rails and just cant get that problem solved.
i have 3 models. Orders, Products and LineItems.
I want to have a order form with checkboxes for each product. User selects appropriate products and submits the order.
I cannot get the form to create the correct hash.
class Order < ActiveRecord::Base
attr_accessible :account_id, :user_id
has_many :line_items, :dependent => :destroy
end
class LineItem < ActiveRecord::Base
attr_accessible :account_id, :product_id, :order_id
belongs_to :orders
belongs_to :product
end
Here the view:
<%= form_for 'line_items[]' do |f| %>
<%= f.select :account_id, options_from_collection_for_select( Account.all,
:id, :name ), :prompt => 'Select Account' %>
<% Product.all.each do |product| %>
<div>
<%= check_box_tag 'line_items[product_ids][]', product.id %>
</div>
<% end -%>
<div>
<%= f.submit 'save' %>
</div>
thanks!
You would need to use accepts_nested_attributes_for in your model to enable nested atributes from associated models. You may also want to check out this railscast and adapt to your needs.
For example in the orders model:
class Order < ActiveRecord::Base
attr_accessible :account_id, :user_id
has_many :products #This makes the association to products
has_many :line_items, :dependent => :destroy
accepts_nested_attributes_for :products #This allows the attributes from products accessible
end
Then the form could be:
<%= form_for #order do |f| %>
<%= f.select :account_id, options_from_collection_for_select( Account.all,
:id, :name ), :prompt => 'Select Account' %>
<%= f.fields_for :product do |product_form| %>
<%= product_form.check_box :id %>
<% end %>
<%= f.submit %>
<% end %>

Rails 3 Nested Model Form

I am having some issues with nested models in a form, using Rails 3.1rc4.
I presently have models that look like this:
class Sale < ActiveRecord::Base
attr_accessible :customer_id, :vehicle_id, :sale_date
belongs_to :customer
accepts_nested_attributes_for :customer
end
and
class Customer < ActiveRecord::Base
attr_accessible :dealership_id, :first_name, :last_name, :address1, :email
belongs_to :dealership
has_many :sales
has_many :vehicles, :through => :sales
end
I've obviously truncated these slightly, but all the important info is there.
I am attempting to set up a sale form that will also allow me to create a new customer, hence the accepts_nested_attributes_for :customer line in the sale model.
My form view looks like (again truncated, only the important part):
<%= form_for #sale, :html => {:class => 'fullform'} do |f| %>
<%= f.error_messages %>
<%= field_set_tag 'Customer Details' do %>
<% f.fields_for :customer do |builder| %>
<%= builder.label :first_name %><br>
<%= builder.text_field :first_name %>
<% end %>
<% end %>
<% end %>
The problem I am having is that neither the text field nor the label for :first_name are showing up when the form is rendered - there is no error message, it just doesn't appear.
I should mention that I have tried both with and without #sale.customer.build in the new method of my controller, but it seems to have had no effect.
Thanks!
Can anyone suggest what I am doing wrong?
EDIT: For the avoidance of doubt, my sales controller's new method looks like:
def new
#sale = Sale.new
#sale.customer.build
end
Add customer_attributes to your attr_accessible in the Sale model.
Another mistake; Replace:
<% f.fields_for :customer do |builder| %>
With:
<%= f.fields_for :customer do |builder| %>

Resources