I'm a newbie and have searched many posts and railscast tutorials and still cant get around this associations thing.
I have 2 models, a Hotel (created by scaffolding) and Facility.
The point is to associate a facility to a hotel, but since my facility table has all the columns it needs with boolean type), a row in that table would do for one hotel.
The thing is, I can't get it to show, and save/edit/update de facilities. I've created a hotel_id colum when creating the model Facility.
My code is:
Models:
class Facility < ActiveRecord::Base
belongs_to :hotel
attr_accessible :concierge, :hotel_id, :room24h
end
class Hotel < ActiveRecord::Base
has_one :facility, :dependent => :destroy
accepts_nested_attributes_for :facility, :allow_destroy => true
attr_accessible :name, :rating, :recommended, :facility_attributes
end
My form in the view is:
<%= form_for(#hotel) do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :rating %><br />
<%= f.number_field :rating %>
</div>
<div class="field">
<%= f.label :recommended %><br />
<%= f.check_box :recommended %>
</div>
<br />
Hotel Facilities
<%= f.fields_for :facility do |facility_fields| %>
<div class="field">
<%= facility_fields.label :room24h, "24h Room Service:" %>
<%= facility_fields.check_box :room24h %>
</div>
<div class="field">
<%= facility_fields.label "Concierge:" %>
<%= facility_fields.check_box :concierge %>
</div>
<%end%>
<div class="actions">
<%= f.submit %>
</div>
<%end%>
As for Controllers, the hotels_controller is the same as if you had just done scaffolding and my facilities_controller is empty.
It is now showing the facilities in the form, but when i click "Create" and it submits, I get:
"Can't mass-assign protected attributes: #hotel"
and
app/controllers/hotels_controller.rb:46:in `new'
app/controllers/hotels_controller.rb:46:in `create'
as for parameters input:
{"hotel"=>{"rating"=>"1",
"name"=>"aaa",
"recommended"=>"0",
"#hotel"=>{"room24h"=>"1",
"concierge"=>"1"}},
"commit"=>"Create Hotel",
"utf8"=>"✓",
"authenticity_token"=>"YU7KEJ8qz0iQcXPGkLP6BSJn7JL6df1HvuS5JnjK2eU="}
Any ideas? What is missing in the controllers? Thanks in advance again
In New/Edit action create #hotel.facility || #hotel.build_facility
Problem solved. To anyone who has the same issue: Added to the new controller:
#facility=#hotel.build_facility
#klump, that syntax was incorrect, after trying the correct one is:
<%= f.fields_for :facility do |fc|%>
So thank you Amar, for pointing me in the right direction.
Related
I have two very similar models Pretreatment and Diagnosis, that belong to the model Patient:
class Pretreatment < ActiveRecord::Base
belongs_to :patient
attr_accessible :content
end
class Diagnosis < ActiveRecord::Base
belongs_to :patient
attr_accessible :content
end
class Patient < ActiveRecord::Base
attr_accessible :age, :name, :city, :street, :number
has_many :anamneses
has_many :befunds
end
On the Patient show page I'm displaying two forms, one for the Preatreatment and another for the Diagnosis:
<%= form_for([#patient, #patient.preatreatments.build]) do |f| %>
<div class="field">
<%= f.label :conten %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<%= form_for([#patient, #patient.diagnosiss.build]) do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
My question is how can I bring the two forms together, so that the user only has to press once the submit button? Im not sure but I think nested attributes is not the right thing to handle it, maybe thefields_for` tag?
Update I tried to use fields_for tag:
<%= form_for([#patient, #patient.pretreatment.build]) do |f| %>
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<%= fields_for([#patient, #patient.diagnosiss.build]) do |u| %>
<div class="field">
<%= u.label :content %><br />
<%= u.text_field :content %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
But I get the error:
undefined method `model_name' for Array:Class in <%= fields_for([#patient,#patient.befunds.build]) do |u| %>
Use fields_for for the associated models.
There should be no square brackets arround the parameters of fields_for
In your code example, I cannot find the relation between Patient and Diagnosis, and the plural of diagnosis is diagnoses, you can specify this in config/initializers/inflections.rb:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'diagnosis','diagnoses'
end
So your Patient model should contain
class Patient < ActiveRecord::Base
attr_accessible :age, :name, :city, :street, :number
has_many :diagnoses
end
And you can write in your form:
<div class="field">
<%= f.label :content %><br />
<%= f.text_field :content %>
</div>
<%= fields_for(#patient, #patient.diagnoses.build) do |u| %>
<div class="field">
<%= u.label :content %><br />
<%= u.text_field :content %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
You can achieve that using nested attributes :
patient.rb
class Patient < ActiveRecord::Base
attr_accessible :age, :name, :pretreatments_attributes, :diagnosiss_attributes
has_many :pretreatments
has_many :diagnosiss
accepts_nested_attributes_for :pretreatments
accepts_nested_attributes_for :diagnosiss
end
patients_controller.rb
def show
#patient = Patient.find(params[:id])
#patient.pretreatments.build
#patient.diagnosiss.build
respond_to do |format|
format.html # show.html.erb
format.json { render json: #patient }
end
end
patients/show.html.erb:
<%= form_for #patient do |f|%>
<h3>Pretreatments:</h3>
<%= f.fields_for :pretreatments do |field| %>
<%= field.label "Content" %></div>
<%= field.text_field :content %>
<% end %>
<h3>Diagnosis:</h3>
<%= f.fields_for :diagnosiss do |field| %>
<%= field.label "Content" %></div>
<%= field.text_field :content %>
<% end %>
<%=f.submit %>
<% end %>
And that all
There are a few ways of doing this:
The way the fields_for works is you have a form_for for the parent model and within it you can place fields_for the models which belong to the parent. A good example is given in the Rails Docs
A simple and more extensible option over time but not very "semantic" one would be to use JavaScript/JQuery. You could trigger $("form #new_pretreatments").submit(); and the same for the Diagnosis once a button is clicked.
Maybe instead you could have just one model to store them both. For example a model called Disease. Each time a patient gets a disease a new one is created and it has columns for each the Diagnosis and Pretreatment. It's probably the best option instead of adding another model for each bit of info a patient can have.
You can use fields_for for the second model, which works like form_for but doesn't generate the form tags. See the docs.
There are some gems available for nested forms. one of them is awesome_nested_fields. I haven't used this earlier but that shows good code in documentation. Another one is simple_form.
Hope that helps!!!
I am a bit unsure on how to store the data from a collection_tag.
Here the model I am working on
Customer GenderManager Genders
Id Id Id
First Customer_id Description
Last Gender_id
Email Created_at
Password
Here the relationship
Customer::class
has_many :gender_managers
accepts_nested_attributes_for :gender_managers, allow_destroy: :true
Gender::class
has_many :gender_managers
GenderManagers:class
belongs_to :customer_id
belongs_to :gender_id
The form I have currently his has follow
<%= form_for #customer do |f| %>
<div class="customer_edit_error_message">
<%= render 'shared/error_messages' %>
</div>
<fieldset>
<div class="customer_edit_name">
<%= f.label :first_name %>
<%= f.text_field :first_name %>
</div>
<div class="customer_edit_middle_name">
<%= f.label :middle_name %>
<%= f.text_field :middle_name %>
</div>
<div class="customer_edit_last_name">
<%= f.label :last_name %>
<%= f.text_field :last_name %>
</div>
<div class="customer_edit_gender">
<%= f.collection_select(:customer, :id, Gender.all, :id, :description) %>
</div>
<div class="customer_edit_button">
<%= f.submit "Save changes", class: "button_accept" %>
</div>
<% end %>
In customerController not sure if I must do something. I know its not right its giving me errors. Its the form that worry me on the select like
Thanks in advance.
I recommend you add an attribute gender to your Customer model. If you want to keep track of changes you can create a GenderHistory model and do something like this in Customer:
class Customer < ActiveRecord::Base
has_many :gender_histories
before_update :track_gender
def track_gender
self.gender_histories.create(:gender => self.gender) if self.gender_changed?
end
end
Your Genders and GenderManager models are not necessary.
I have a polymorphic model and want to have a nested form use this model. I am getting no errors but the form is not displaying the nested field. Here are my models and stripped down form:
Polymorphic Model
class SeoMapping < ActiveRecord::Base
belongs_to :mappingtable, :polymorphic => true
attr_accessible :seo_url
validates :seo_url, :presence => true, :uniqueness => true
end
Page model using the Polymorphic Model
class Page < ActiveRecord::Base
has_one :seo_mappings, :as => :mappingtable, :dependent => :destroy
accepts_nested_attributes_for :seo_mappings
attr_accessible :content, :h1, :meta_description, :title, :seo_mappings_attributes
.........
end
Now stripped down form
<%= form_for(#page) do |f| %>
<% if #page.errors.any? %>
.......
<% end %>
<div class="field">
<%= f.fields_for :seo_mappings do |builder| %>
<%= builder.label :seo_url %><br />
<%= builder.text_field :seo_url %>
<% end %>
</div>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
.........
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I cant see why it does not display the fields_for elements. If I comment out accepts_nested_attributes_for the field then displays. Can you see where I am going wrong ?
TY
Possibly a silly question but is this the create or edit action you're talking about? And if it's create, did you call #page.build_seo_mapping or something in the controller?
Also (may be unrelated) if you use has_one, usually you want to use a singular noun, so has_one :seo_mapping instead of mappings.
I want my users to be able to select from predefined values of categories. I took a look at other Stackoverflow questions but didn't get them fully. Here is my code right now....
I have my Categories model and Users create prices (which is another name for Items).
class Category < ActiveRecord::Base
has_many :prices
def name
"#{category}"
end
end
My prices belong to categories. note: The prices table has a category_id.
class Price < ActiveRecord::Base
attr_accessible :name, :date, :price
belongs_to :user
belongs_to :category
end
Here is how the form and view look as of now:
Form
<%= form_for(#price) do |f| %>
<div class="field">
<%= f.label :date %><br />
<%= f.date_select :date %>
</div>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :price %><br />
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :category %><br />
<%= f.collection_select :category_id, Category.all, :id, :name, :prompt => true %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
View
<p><b>User:</b><%= #price.user_id %></p>
<p><b>Date:</b><%= #price.date %> </p>
<p><b>Name:</b><%= #price.price_name %></p>
<p><b>Price:</b><%= number_to_currency(#price.price) %></p>
<p><b>Category:</b><%= #price.category.name %></p>
How do i create the categories i want in the drop down menu?
Thank you I'm a very appreciative!
You probably want the collection_select form helper method: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select
It will look something like this:
<div class="category">
<%= f.label :category %><br />
<%= f.collection_select :category, Category.all, :id, :name %>
</div>
Then in the view:
<p><b>Category:</b><%= #price.category.name %></p>
This assumes that your categories table has a name field which stores the category names.
you can create your data in db/seeds.rb
rake db:seed to load them (Load the seed data from db/seeds.rb)
http://railscasts.com/episodes/179-seed-data for more details
I've been having some trouble trying to get *fields_for* to produce an output when trying to display my User and Profile model on a single form, these use a *has_one* and *belongs_to* relationship.
So here are extracts form the top of the model classes:
class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile
class Profile < ActiveRecord::Base
belongs_to :user
The controller is pretty simple and standard:
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
And here is a snippet out of the view as it currently stands:
<%= form_for(#user) do |f| %>
<% f.fields_for :profile do |profile_form| %>
<div class="field">
<%= profile_form.label :name %><br />
<%= profile_form.text_field :name %>
</div>
<% end %>
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I've tried other things, like this:
<% fields_for #user.profile do |profile_form| %>
And everything works fine if I manually add the field:
<div class="field">
<label for="user_name">Name</label><br>
<input id="user_name" name="user[profile_attributes][name]" size="30" type="text" value="<%= #user.profile.name %>">
</div>
It's worth mentioning that I'm fairly new to rails and not exactly sure how these functions work under the hood although I've read the documentation and guide. Also in my searches a lot of the examples of fields_for a one to many relationship so perhaps I'm going about this in the wrong way?
All help, advice and further reading is much appreciated :-)
Cheers,
Sam
In your code:
<% f.fields_for :profile do |profile_form| %>
Doesn't that need to be written like this (due to Rails 3 new behavior):
<%= f.fields_for :profile do |profile_form| %>