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
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.
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| %>
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.
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>
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 %>