Problem saving data using Nested Attributes - ruby-on-rails-3

I'm
I'm building a website on Ruby On Rails 3.0.7 and I want to save a store object and its languages. So, I have the following models:
class Store < ActiveRecord::Base
belongs_to :user
has_many :languages, :through => :store_languages
has_many :store_languages
accepts_nested_attributes_for :store_languages
#Validations
validates :title, :presence => true, :length => 5..100
validates :contact_email, :presence => true, :format => { :with => /^([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})$/i }
end
class Language < ActiveRecord::Base
has_many :stores, :through => :store_languages
has_many :store_languages
end
class StoreLanguage < ActiveRecord::Base
belongs_to :store
belongs_to :language
validates :store_id, :presence => true
validates :language_id, :presence => true
end
StoresController's relevant actions:
def new
#store = Store.new
#store.store_languages.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #store }
end
end
# POST /stores
# POST /stores.xml
def create
#raise params.inspect
#store = current_user.stores.new(params[:store])
respond_to do |format|
if #store.save
format.html { redirect_to(#store, :notice => 'Store was successfully created.') }
format.xml { render :xml => #store, :status => :created, :location => #store }
else
#store.store_languages.build
format.html { render :action => "new" }
format.xml { render :xml => #store.errors, :status => :unprocessable_entity }
end
end
end
View: /stores/new.html.erb:
<%= form_for(#store) do |f| %>
<% if #store.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#store.errors.count, "error") %> prohibited this store from being saved:</h2>
<ul>
<% #store.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<label for="title">Title*</label><br />
<%= f.text_field :title %>
</p>
<p>
<label for="description">Description</label><br />
<%= f.text_field :description %>
</p>
<p>
<label for="contact_email">Contact E-mail*</label><br />
<%= f.text_field :contact_email %>
</p>
<p>
<label for="logo">Logo</label><br />
<%= f.file_field :logo %>
</p>
<% f.fields_for :store_languages do |lf| %>
<%= lf.collection_select :language_id, #languages, :id, :name, {}, {:multiple => true } %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
So, I've got the following records in the languages table:
id | name
3 English
4 EspaƱol
What happens is that when I create a new store selecting the two languages from the list, it will save the following at the store_languages table:
id | store_id | language_id
4 4 1
And the language_id = 1 doesn't exist.
If I debug the application at the create action, I get the following:
"store"=>{"title"=>"asdasdsdsadasdasdasd", "description"=>"", "contact_email"=>"asdasdsa#asdasdsad.com", "logo"=>"", "store_languages_attributes"=>{"0"=>{"language_id"=>["3", "4"]}}}
You can see that the ids are correct here: 3 and 4. So, I don't know why it saves 1.
Any ideas?

Try
<%= lf.collection_select :language_ids, #languages, :id, :name, {}, {:multiple => true } %>
(ie using ids instead of id in the attribute name)

Related

Rails HABTM display and select

I am trying to set up in rails 3.2.0 with ruby 1.9.3 a
has_and_belongs_to_many relationship between two tables I have the proper join table migration set up with both foreign keys and my models are as such
student.rb
class Student < ActiveRecord::Base
attr_accessible :birthday, :id, :name, :year, :course_ids
has_and_belongs_to_many :courses
accepts_nested_attributes_for :courses
end
course.rb
class Course < ActiveRecord::Base
attr_accessible :id, :coursePrefix, :roomNumber, :name, :student_ids
has_and_belongs_to_many :students
end
_form.html.erb
<%= form_for(#student) do |f| %>
<% if #student.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#student.errors.count, "error") %> prohibited this student from being saved:</h2>
<ul>
<% #student.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :id %><br />
<%= f.text_field :id %>
</div>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :birthday %><br />
<%= f.date_select :birthday, :start_year => 1930 %>
</div>
<div class="field">
<%= f.label :year %><br />
<%= f.text_field :year %>
</div>
<div>
<%= f.collection_select(:courses, #courses, :id, :name)%>
</div>
<br />
<div class="actions">
<%= f.submit %>
</div>
<% end %>
and student_controller.rb
# GET /students/new
# GET /students/new.json
def new
#student = Student.new
#courses = Course.all
respond_to do |format|
format.html # new.html.erb
format.json { render json: #student }
end
end
# GET /students/1/edit
def edit
#student = Student.find(params[:id])
#courses = Course.all
end
# POST /students
# POST /students.json
def create
#student = Student.new(params[:student])
respond_to do |format|
if #student.save
format.html { redirect_to #student, notice: 'Student was successfully created.' }
format.json { render json: #student, status: :created, location: #student }
else
format.html { render action: "new" }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
# PUT /students/1
# PUT /students/1.json
def update
#student = Student.find(params[:id])
#courses = #student.courses.find(:all)
respond_to do |format|
if #student.update_attributes(params[:student])
format.html { redirect_to #student, notice: 'Student was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
Again I am trying to get the form element to allow a student to select a course and be saved in that table under the JOIN method, however everytime I try to look for help I get different errors and cannot find a solution
Thank you for your help
You just have to give access to the :courses attribute of the Student model:
class Student < ActiveRecord::Base
attr_accessible :birthday, :id, :name, :year, :course_ids, :courses
# ^ ^ ^ ^
Why? Because your controller receive params formatted like this:
params = {
student: {
id: 12,
name: "Bob the Sponge",
courses: [5, 7], # Course ids
etc: ...
}
}
And the controller is trying to create a Student object directly with the params, so when he is trying to update the courses attribute of the Student, it can't because you didn't define it as accessible.

Nested fields not being created on form

I am trying to get a Project form to build the first (starting) time of several (up to 12) volunteer time blocks.
project.rb
class Project < ActiveRecord::Base
attr_accessible :title, ...
has_many :vol_times, :dependent => destroy
accepts_nested_attributes_for :vol_times, :reject_if => lambda { |a| a[:start_time].blank? }, :allow_destroy => true
...
end
vol_time.rb
class Vol_time < ActiveRecord::Base
attr_accessible :start_time, ...
belongs_to :project
end
ProjectsController
class ProjectsController < ApplicationController
before_filter :signed_in_user, only: :create
...
def new
#project = Project.new
#user = current_user
#project.vol_times.build
end
...
end
Vol_Times Controller
class Vol_TimesController < ApplicationController
def new
#reward = Reward.new
end
...
end
My view looks like this...
<%= form_for(#project) do |f| %>
<div class="form_field_block">
<p class="form_label"> Project Title</p>
<%= f.text_field :title, :size => 40, :placeholder => " Project Title...", :class => "frm" %>
</div>
<div class="form_field_block">
<p class="form_label"> Project Sub-title</p>
<%= f.text_field :sub_title, :size => 40, :placeholder => " Project Sub-title...", :class => "frm" %>
</div>
<p class="clearing"></p>
<div class="form_field_block">
<% f.fields_for :vol_times do |builder| %>
<%= render :partial => 'start_time', :f => builder %>
<% end %>
</div>
<p class="clearing"></p>
<%= button_tag "btn_start_project.png", :class => "btn_save" %>
<% end %>
And the _partial looks like this...
<%= f.label :start_time, "Starting Time" %>
<%= f.text_field :start_time %>
When I view the page, I see the containing <div>, but not the contents of the ERB, which should be parsed from the _partial.
Any ideas why this isn't working? I got the general context from Ryan Bates' RailsCast #196 - Here
you are missing a = on the fields_for. It should be
<%= f.fields_for :vol_times do |builder| %>

Nested form with complex model fails to create children

I have a bit of a complex model association:
class Company < ActiveRecord::Base
has_many :roles, :dependent => :destroy
has_many :users, :through => :roles
end
class Role < ActiveRecord::Base
belongs_to :user
belongs_to :company
attr_accessor :roles_attributes
attr_accessible :roles_attributes, :active, :company_id, :role
validates_presence_of :company_id, :role
validates_uniqueness_of :user_id, :scope => :company_id, :message => "Users may only have one role per company."
end
class User < ActiveRecord::Base
has_many :roles, :dependent => :destroy
accepts_nested_attributes_for :roles, :allow_destroy => true
has_many :companies, :through => :roles
end
The intent here is that a single user (email address) could login under different companies with different permissions (roles) per company.
I have users nested under company and my update controller works fine but now I can't seem to get the new/create controller to work:
Controller:
def new
#user = User.new
#role = #user.roles.build.company_id = session[:company_id]
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
and the View:
<%= simple_nested_form_for [:company, #user] do |f| %>
<fieldset>
<div class="form-horizontal">
<%= f.input :email %>
<%= f.input :name_first %>
<%= f.input :name_last %>
<%= f.input :title %>
<%= f.input :phone %>
<%= f.input :mobile %>
<%= f.simple_fields_for :roles, #role do |role_form| %>
<%= role_form.hidden_field :company_id %>
<%= role_form.input :active %>
<%= role_form.input :role, :collection => [ "Guest", "User", "Inspector", "Owner"] %></td>
<% end %>
<%= f.input :notes, :input_html => { :rows => 5, :cols => 70 } %>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to 'Cancel', company_users_path, :class => 'btn' %>
</div>
</fieldset>
<% end %>
When I submit the form it fails silently except that I notice in the logs that "roles_attributes" is being passed as:
"roles_attributes"=>{"0"=>{"company_id"=>"2", "active"=>"1", "role"=>"Inspector"}}
which I think should be:
"roles_attributes"=>[{"company_id"=>"2", "active"=>"1", "role"=>"Inspector"}]
I must be missing something obvious.
Turns out it was has_secure_password. I had deleted the password fields and the validation was failing.

Field_for in nested attributes is giving problem

I'm new to both programming and Ruby on Rails. I'm just trying with a sample 2 level deep nesting. When I followed Ryan's Scraps (http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes) for 1 level deep nesting everything well and good but when I extended for 2 level deep with following requirement:
Instead of creating parent, children and grandchildren at a time I want to create parent first then child and grandchild together.My code is
My model:
class Parent < ActiveRecord::Base
has_many :children
has_many :grand_children
accepts_nested_attributes_for :children, :allow_destroy => true
accepts_nested_attributes_for :grand_children, :allow_destroy => true
end
class Child < ActiveRecord::Base
belongs_to :parent
has_many :grand_children
accepts_nested_attributes_for :grand_children
end
class GrandChild < ActiveRecord::Base
belongs_to :parent
belongs_to :child
end
My children controller -new method:
def new
#parent = Parent.find(params[:parent_id])
child = Child.new
child.grand_children.build
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #child }
end
end
My children _form template is
<%= form_for([#parent, #parent.children.build]) do |form| %>
<div>
<%= form.label :name %><br />
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :sex %><br />
<%= form.text_field :sex %>
</div>
<div>
<%= form.fields_for :grand_children do |grand_child_form| %>
<%= render :partial => "grand_children/form", :locals => { :form => grand_child_form} %>
<% end %>
</div>
<% end %>
Here I'm not getting any error as such but when I select new child the grand_child is not appearing,
<%= form.fields_for :grand_children do |grand_child_form| %>
<%= render :partial => "grand_children/form", :locals => { :form => grand_child_form} %>
<% end %>
is not getting reflected at all .
Thanks in advance
Hey folks I got d solution by trial and error,
form template for children is
<div>
<%= form.fields_for :grandchildren, #grand_child do |grand_child_form| %>
<%= render :partial => "grandchildren/form", :locals => { :form => grand_child_form} %>
<% end %>
</div>

needs nested_form example

I give up. I'm trying to build a simple nested form with 2 models following Railscasts #196 episode and doesn't work. Can someone send a working example please so I can test on my environment. I'm using 3.1.0
For example when I try to build 3 questions on the form only 1 question field appears, then survey_id is never passed across.
I would appreciate your help after 2 days and nights on it. I got missing something really big. Thanks
Model
class Survey < ActiveRecord::Base
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions
attr_accessible :name, :questions_attributes
end
class Question < ActiveRecord::Base
belongs_to :survey
attr_accessible :survey_id, :name
end
Controller
def new
#survey = Survey.new
4.times { #survey.questions.build }
respond_to do |format|
format.html # new.html.erb
format.json { render json: #survey }
end
end
def create
#survey = Survey.new(params[:survey])
respond_to do |format|
if #survey.save
format.html { redirect_to #survey, notice: 'Survey was successfully created.' }
format.json { render json: #survey, status: :created, location: #survey }
else
format.html { render action: "new" }
format.json { render json: #survey.errors, status: :unprocessable_entity }
end
end
end
View
<%= form_for(#survey) do |f| %>
<% if #survey.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#survey.errors.count, "error") %> prohibited this survey from being saved:</h2>
<ul>
<% #survey.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<%= fields_for :questions do |builder| %>
<%= builder.label :name, "Question" %>
<%= builder.text_field :name %>
<% end %>
<br /><br />
<div class="actions">
<%= f.submit %>
</div>
<% end %>