How to store select information - ruby-on-rails

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.

Related

rails 4 has_one nested forms not building still

I have looked at all the posts about this fairly common problem on stackoverflow and elsewhere but I have not yet been able to find an answer. Essentially my nested form is not building, and is therefore not visible when I show the page.
Here is the relevant part of my user controller, users_controller.rb:
def new
#user = User.new
#user.build_user_account
end
Here is the relevant section from my user.rb file:
class User < ActiveRecord::Base
has_one :user_account, :class_name => "UserAccount"
accepts_nested_attributes_for :user_account
And my user_account.rb file:
class UserAccount < ActiveRecord::Base
belongs_to :user
end
Here is my _form.html.erb file:
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br>
<%= f.text_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br>
<%= f.text_field :password_confirmation %>
</div>
<% f.fields_for :user_account, #user.user_account do |user_account| %>
<div class="field">
<%= user_account.label :email %>
<%= user_account.text_field :email %>
</div>
<div class="field">
<%= user_account.label :password %>
<%= user_account.text_field :password %>
</div>
<div class="field">
<%= user_account.label :password_confirmation %>
<%= user_account.text_field :password_confirmation %>
</div>
<% end %>
the first three show up as expected, but the three form fields for user_account do not show up. I've tried everything that I could find online, but I still haven't been able to work out what the problem is - help would be appreciated!
I think you have just missed the = sign in the f.fields_for line. Try like this:
<%= f.fields_for :user_account, #user.user_account do |user_account| %>
The #user.user_account is not necessary either but does not harm.

Rails controller saving from different table

I'm new to rails to bear with me.
This concerns two of my models: Product and Manufacturer.
When creating a new product the user can select which manufacturer the product belongs to from a drop down list. The problem is that I can't get this manufacturer to save.
I know I have to add some code to the controller and I've tried various things but to no avail.
Here's the view:
<h1>New Product</h1>
<%= form_for(#product) do |f| %>
<div>
<%= f.label :name, 'Name' %>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :market_price, 'Market Price' %>
<%= f.text_field :market_price %>
</div>
<div>
<%= f.label :sell_price, 'Sell Price' %>
<%= f.text_field :market_price %>
</div>
<div>
<%= f.label :stock_level, 'Stock Level' %>
<%= f.text_field :stock_level %>
</div>
<div>
<%= f.label :manufacturer, 'Manufacturer' %>
<%= f.collection_select(:manufacturer, Manufacturer.all, :id, :name, prompt: true) %>
</div>
<div>
<%= f.label :location, 'Location' %>
<%= f.collection_select(:location, Product.all, :id, :location, prompt: true) %>
</div>
<br> </br>
<div>
<%= f.submit "Create Product" %>
</div>
And here's part of the controller:
def create
#product = Product.new(params[:product].permit(:name, :market_price, :sell_price, :stock_level, :location))
#product.save
flash[:notice] = 'Product Created'
redirect_to #product
end
end
After hours of trying several nesting methods, I still can't get this to work.
Surely it's very common to save fields from various models on one page???
You would usually nest your routes, so that products were within manufacturer:
resources :manufacturer do
resources :products
end
Then your form would be a form for an array:
form_for([#manufacturer, #product]) do |f|
f.hidden_field :manufacturer_id, value: #manufacturer.id
This allows you to pass in the ID of both the manufacturer and the product.
Now in your controller you can use something like the following, provided the associations are set up, such as product belongs_to :manufacturer and manufacturer has_many :products
#manufacturer = find(params[:manufacturer_id])
#product = #manufacturer.products.create()
In your form, you need to have a field for manufacturer_id, not manufacturer. You would change f.collection_select(:manufacturer to be f.collection_select(:manufacturer_id.
Then, in your controller, you need to add manufacturer_id to the list of parameters you are permitting in your permit method call. So it would be Product.new(params[:product].permit(:name, :market_price, :sell_price, :stock_level, :location, :manufacturer_id)).

Ruby on Rails, two models in one form

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!!!

Ruby on Rails - Association issue :(

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.

How to have predefined categories?

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

Resources