Rails: Access params of a form with a nested model - ruby-on-rails

I have the following models
class GymUser < ActiveRecord::Base
belongs_to :user
belongs_to :gym
end
class User < ActiveRecord::Base
has_many :gym_users
has_one :gym
attr_accessible :gym_users_attributes, :gym_users
accepts_nested_attributes_for :gym_users
end
I have a form for a new user, with a nested model gym_user. I want to make sure the user doesn't exist already. This is what I'm trying:
def create_member
#user = User.new(params[:user])
#user.generate_password
#dupe = User.find_all_by_email(#user.email)
if(#dupe)
#gym_user = GymUser.new(params[:user][:gym_users_attributes])
#gym_user.user_id = #dupe.id
elsif #user.save
#gym_user = #user.gym_users.order('created_at DESC').first
#gym = Gym.find(#gym_user.gym_id)
end
end
I know there's only one nested model here, but I can't figure out how to access those nested parameters.
Here's the form itself
<%= form_for #user, :as => :user, :remote => true, :url => { :controller => 'users', :action => 'create_member'} do |f| %>
<table border="0" cellpadding="10" cellspacing="0">
<tr>
<td colspan="2">
<%= f.label :name %><br />
<%= f.text_field :name %>
</td>
<td colspan="2">
<%= f.label :email %><br />
<%= f.text_field :email %>
</td>
</tr>
<% f.fields_for :gym_users do |builder| %>
<tr>
<td>
<%= builder.label :role_id, "Role" %><br />
<%= builder.collection_select(:role_id, #roles, :id, :name, {:include_blank => true}, {:onchange => "new_member_role_changed()"}) %>
<%= builder.hidden_field :gym_id, :value => #gym.id %>
</td>
<td>
<%= builder.label :item_id, "Membership Level" %><br />
<%= builder.collection_select(:item_id, #gym.membership_items, :id, :name, {:include_blank => true}) %>
</td>
<td>
<%= builder.label :has_monthly_billing, "Recurring Billing?" %><br />
<%= builder.radio_button :has_monthly_billing, "1" %>Yes
<%= builder.radio_button :has_monthly_billing, "0" %>No
</td>
<td>
<%= builder.label :billing_date %><br />
<%= builder.collection_select(:billing_date, (1..31).to_a, :to_s, :to_s, {:include_blank => true}) %>
</td>
</tr>
<tr>
<td colspan="4">
<%= f.submit %>
Cancel
</td>
</tr>
<% end %>
</table>
<% end %>

I found the answer. I'm not sure if this is the best way but it works
params[:user][:gym_users_attributes].values.first

Your association should be
has_one :gym, :through => gym_users
Also, can you post your form paramaters?

Your focus is on not allowing creation of duplicate users, and you are using email to verify this. You should rather use the helper
validates_uniqueness_of :email
in your User model. As you have a nested attribute, your object will be created only after Rails validates that a user with same email doesn't exist already.
I hope I understood your problem right.

Related

Nested forms in ruby on rails using has_many through and belongs to associations

Lets say I have three objects/models; years, cars, and parts. Now, I have cars belong_to parts. The thought on this was that a part may be part of many cars but a car has only one of that part at a given time. and years has_many cars through car_years. I have successfully nested the cars form in the years form. However, when I try to nest the parts form in the cars form and create a new year I get cannot mass assign protected: parts. But, I can create a new car and it will successfully create the new part. I would like to know if I am on the right track or should I be looking elsewhere to solve this. I got the idea from rails cast #196.
Year model
class Year < ActiveRecord::Base
attr_accessible :year, :cars_attributes
has_many :car_years
has_many :cars, :through => :machine_years
accepts_nested_attributes_for :car_years,
:reject_if => lambda { |a| a[:num_cars].blank? },
:allow_destroy => true
accepts_nested_attributes_for :cars,
:reject_if => lambda { |a| a[:doors].blank? },
:allow_destroy => true
end
Car model
class Machine < ActiveRecord::Base
attr_accessible ..., :part_id, :part_attributes
has_many :car_years
has_many :years, :through => :car_years
belongs_to :part
accepts_nested_attributes_for :car_years
accepts_nested_attributes_for :years
accepts_nested_attributes_for :part,
:reject_if => lambda { |a| a[:name].blank? }
end
Parts Model
class Part < ActiveRecord::Base
attr_accessible :desc, :name
has_many :machines
end
Year_form View
<%= form_for(#year) do |f| %>
<% if #year.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#year.errors.count, "error") %> prohibited this year from being saved:</h2>
<ul>
<% #year.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :year %><br />
<%= f.date_select :year, :start_year => 1940, :end_year => Time.now.year, :discard_day => true, :discard_mon th => true %>
</div>
<h3>Cars</h3>
<div>
<%= f.fields_for :cars do |builder| %>
<%= render 'car_fields', :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add Car", f, :cars %></p>
</div>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Car_fields.html.erb
<div class="field">
<h3>New Car</h3>
<table>
<tbody>
<tr>
<th><%= f.label :name %></th>
<th><%= f.label :model %></th>
<th><%= f.label :part_id %></th>
</tr>
<tr>
<td><%= f.text_field :name %></td>
<td><%= f.text_field :model %></td>
<td>
<%= f.fields_for :part do |builder| %>
<%= render "cars/parts_fields", :f => builder %>
<% end %>
</td>
<td><%= f.number_field :memory_id %></td>
</tr>
<tr>
<th><%= f.label :install_dt, "Install Date" %></th>
<th></th>
<th><%= f.label :production_dt, "Production Date" %></th>
<th></th>
<th><%= f.label :remove_dt, "Remove Date" %></th>
</tr>
<tr>
<td><%= f.date_select :install_dt, :start_year => 1940, :end_year => Time.now.year %></td>
<td></td>
<td><%= f.date_select :production_dt, :start_year => 1940, :end_year => Time.now.year %></td>
<td></td>
<td><%= f.date_select :remove_dt, :start_year => 1940, :end_year => Time.now.year %></td>
</tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<th><%= f.label :history %></th>
<th></th>
<th><%= f.label :design %></th>
<th></th>
<th><%= f.label :notes %></th>
</tr>
<tr>
<td><%= f.text_area :history, :rows => 4 %></td>
<td></td>
<td><%= f.text_area :design, :rows => 4 %></td>
<td></td>
<td><%= f.text_area :notes, :rows => 4 %></td>
</tr>
</tbody>
</table>
<div style="padding: 2px;">
<%= f.label :image %><br />
<%= f.text_field :image %>
</div>
<%= link_to_function "remove", "remove_fields(this)" %>
</div>
cars/part_fields.html.erb
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %><br />
<%= f.label :desc %><br />
<%= f.text_area :desc, :rows => 3 %>
</div>
Hard to tell without seeing any of you code. However the following error cannot mass assign protected: parts means that you should add attr_accessible :parts to your model in order to be able to do something like this:
a_part = Part.new
another_part = Part.new
Car.new(parts: [a_part, another_part])
Otherwise, without it, you would have to do:
c = Car.new
c.parts << a_part
c.parts << another_part
OK, so the solution was in another post:
Getting fields_for and accepts_nested_attributes_for to work with a belongs_to relationship
In the car_fields form I needed to call
<%= f.fields_for :part_attributes do |builder| %>
not
<% =f.fields_for :parts do |builder| %>
However, now when I look at the year edit screen the part fields are empty, but the part_type does exist

Rails nested form edits

I am trying to figure out the whole nested form thing, and am having issues rending the form for editing.
I'm not doing this the "typical way" with a new and create action, because i'm not actually going to be saving anything. I'm just using this form to generate some tests.
Here is what I have..
model.rb
class Model < ActiveRecord::Base
has_many :columns
has_many :associations
accepts_nested_attributes_for :associations, :reject_if => lambda { |a| a[:type].blank? }
accepts_nested_attributes_for :columns, :reject_if => lambda { |a| a[:name].blank? }
attr_accessible :name, :associations_attributes, :columns_attributes
end
column.rb
class Column < ActiveRecord::Base
belongs_to :model
attr_accessible :db_index, :mass_assign, :max_length, :min_length, :name, :required, :unique, :columns_attributes
validates :name, :presence => true
end
generator_controller.rb
def model
if params['submit']
#model = Model.new(params[:model])
#model.columns.build
else
#model = Model.new
3.times { #model.columns.build }
end
render 'generator/model'
end
form view
<%= nested_form_for(#model, :url => '/model', :html => {:style => 'width:100%;'}) do |f| %>
<%= flash_helper() %>
<h3>Model Name</h3>
<%= f.text_field :name %>
<h3>Add Table Columns</h3>
<div id="columns">
<% f.fields_for :columns do |builder| %>
<div class="float_left column">
<%= builder.label :name %>
<br>
<%= builder.text_field :name, :size => 20 %>
</div>
<div class="float_left column">
<%= builder.label :mass_assign %>
<br>
<%= builder.check_box :mass_assign %>
</div>
<div class="float_left column">
<%= builder.label :required %>
<br>
<%= builder.check_box :required %>
</div>
<div class="float_left column">
<%= builder.label :unique %>
<br>
<%= builder.check_box :unique %>
</div>
<div class="float_left column">
<%= builder.label :db_index %>
<br>
<%= builder.check_box :db_index %>
</div>
<div class="float_left column">
<br>
<%= image_tag "delete-icon24x24.png", :class => "btnDel clickable" %>
</div>
<br class="clear_float">
<% end %>
<%= f.link_to_add image_tag('add-icon.png'), :columns %>
</div>
<br><br>
<input type="submit" name="submit">
<p>
<%= #results %>
</p>
<% end %>
So the problem is, the form when new is not displaying the columns that "3.times { #model.columns.build }" is supposed to do. Also, when I submit the form, I need to figure out why it is getting rid of all of those nested attributes that were added. So each time I submit the form, and it renders the form again, all the attributes are gone. (The "model" attributes are still there, but the "column" attributes reset each time)
Any ideas on what i'm doing wrong?
Thanks
I am embarrassed to even admit this, but hopefully it will help someone else with one more thing to check if they have the same problem.
<% f.fields_for :columns do |builder| %>
changed to:
<%= f.fields_for :columns do |builder| %>
Yeah.. can't believe I did that...

rails creating a new user

user.rb
class User < ActiveRecord::Base
# attr_accessible :title, :body
#validate :username ,:first_name ,:last_name ,:email ,:password ,:phone ,:location ,:require => true
# validates :username,:require => true
validates :username, :presence => true
has_many :ads
#validates :phone , :presence => true
attr_accessor :password,:password_confirmation
validates_confirmation_of :password
attr_protected :hashed_password ,:salt
users_controller
def create
#user = User.new(params[:user])
if #user.save
flash[:notice] = 'User successfully created.'
redirect_to :action => 'index'
else
render :action => 'index'
end
end
def new
if session[:user_id]
flash[:notice] = "You have already registered"
redirect_to(:controller => 'main',:action => 'index')
end
#user = User.new
end
alias :register :new
registration_form
<%= form_for #user do |f| %>
<%= f.error_messages %>
<table>
<tr>
<th>
<%= f.label :first_name %>
</th>
<td>
<%= f.text_field :first_name ,:placeholder => 'Please enter your real name.' %><br/>
</td>
</tr>
<tr>
<th>
<%= f.label :last_name %>
</th>
<td>
<%= f.text_field :last_name ,:placeholder => 'Please enter your real name.' %><br/>
</td>
</tr>
<tr>
<th>
<%= f.label :username %>
</th>
<td>
<%= f.text_field :username ,:placeholder => 'Enter your username here'%>
</td>
</tr>
<tr>
<th>
<%= f.label :email%>
</th>
<td>
<%= f.text_field :email ,:placeholder => 'sample#sample.com' %><br/>
</td>
</tr>
<% if !session[:user_id] %>
<tr>
<th>
<%= f.label :password %>
</th>
<td>
<%= f.password_field :password ,:placeholder => 'EnterPassword' %><br/>
</td>
</tr>
<tr>
<th>
<%= f.label :password_confirmation,'Confirm Password' %>
</th>
<td>
<%= f.password_field :password_confirmation ,:placeholder => 'Confirm password' %><br/>
</td>
</tr>
<% end %>
<tr>
<th>
<%= f.label :phone %>
</th>
<td>
<%= f.text_field :phone ,:placeholder => '09351270000' %><br/>
</td>
</tr>
<tr>
<th>
<%= f.label :location %>
</th>
<td>
<%= f.text_field :location ,:placeholder => 'Your address' %><br/>
</td>
</tr>
<tr>
<td></td> <td> <%= f.submit !session[:user_id] ? 'Register' : 'Save changes',:class => 'button',:style => 'height:50px' %></td>
</tr>
</table>
<% end %>
doubt
when i am logging in and updating user information using the same form its working fine , but when i am creating new user , i am redirected to users/index , while i am supposed to be registered
This basically means that the #user.save fails. There can be many reasons for this, it is hard to tell exactly what this is, since you don't give any error messages. The most probable case, I think, you are running into now is that you are trying to set a field (column of the user model) which is not accessible by the attr_accessible field.
Since you have commented that line out you are telling rails that there exists no fields in the user model which can be mass assigned. This is what happens when you call User.create(params[:user])
So to fix you problem now, try uncommenting your attr_accessible and add all the fields you need to set a user. In your case this would be:
attr_accessible :first_name, :last_name, :username, :email, :password, :phone, :location
I suggest you find some information on what attr_accessible and these others do. It is handy to know how these work.

How do I make a multiple Selection in a Rails From for one part of the form/table/model?

I have a nested table called products nested under the parties table and one of the comluns is "brand". A product has a quantity, color and "brand". For "brand" I want the user to be able to do a multiple selection and collection on as many brands as the users want per product. How would I do this? I installed the "rails chosen gem", but it seems I need allot more than that.
Is it even possible for one column in a table to have multiple collection per user and product? Also it seems I should use indexing?
Code:
Product.rb:
class Product < ActiveRecord::Base
attr_accessible :party_id, :party, :id, :brand, :color, :name, :quantity
belongs_to :party
BRAND_TYPES = ["Hugs", "Kisses", "Love" ]
end
Party.rb:
class Party < ActiveRecord::Base
validates :user_id, presence: true
attr_accessible :name, :products_attributes, :products, :user_id
belongs_to :user
has_many :products
accepts_nested_attributes_for :products, allow_destroy: true
end
_product_fields.html.erb:
<table>
<tr>
<td> <%= f.label :name, "Product Name" %> </td>
<td> <%= f.text_field :name %> </td>
<td> <%= f.label :color, "Color" %> </td>
<td> <%= f.text_field :color %> </td>
<td> <%= f.label :Quantity, "Quantity" %> </td>
<td> <%= f.text_field :quantity %> </td>
<td> <%= f.label :brand, "Brand" %> </td>
<td> <%= f.select :brand, Product::BRAND_TYPES, :multiple => true %> </td>
<td> <%= f.link_to_remove "Remove this task" %></td>
</tr>
</table>
Thanks, I appreciate it.

Rails 3: nested form rendered with belongs_to association

I am struggling to get the nested form rendered with belongs_to association.
I was expecting the address fields in the "_form.html.erb" (below) to be rendered correct, but apparently it is not, and i just cant wrap my head around it to figure why!
Rails version: 3.09
here is the code.
Model:
Store.rb
class Store < ActiveRecord::Base
has_and_belongs_to_many :products
belongs_to :store_address, :foreign_key => "address_id", :class_name => "Address"
......
end
Address doesn't have any reference to Store model (it is independent)
Controller
stores_controller.rb
def new
#store = Store.new
#store.build_store_address
respond_with(#store)
end
View
new.html.erb
<% form_for(#store, :url => collection_url) do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<p class="form-buttons">
<%= button t('continue') %>
</p>
<% end %>
_form.html.erb
<%=t(:store_name)%> : <%= text_field :store, :name %>
<%=t(:store_admin_email)%> : <%= text_field :store, :admin_email %>
<fieldset>
<legend><label><%=t(:address)%></label></legend>
<% f.fields_for :store_address do |address_form| %>
<table>
<tbody><tr>
<td width="200"><label><%=t(:line_1)%></label></td><td>
<%= address_form.text_area :address1, :rows => 2%>
</td>
</tr>
<tr>
<td><label><%=t(:line_2)%></label></td><td>
<%= address_form.text_area :address2, :rows => 2 %>
</td>
</tr>
<tr>
<td><label><%=t(:city)%></label></td><td>
<%= address_form.text_field :city %>
</td>
</tr>
.......
This renders the store name. but nothing on the address side. please help!
I think you missed an = at <% f.fields_for .... It should be <%= f.fields_for... .
This has happened to me so often in the past, missing this one thing, and then wondering why the nested form would not render.

Resources