multiple select - ruby-on-rails

I am trying to create a form that allows to assign multiple projectmembers to a project.
(User and Project model being related through UserProject )
here is my view:
<div class="field">
<%= fields_for :projectmember do |u| %>
<%= u.label :projectmember %><br />
<%= select_tag :projectmember, options_for_select(User.all.collect {|u| [u.id, u.lastname]}, :projectmember),:multiple => true, :prompt => 'Select Person' %>
<% end %>
</div>
i have put the projectmember tag all over the place but i can't figure it out how to save this field projectmember into my db projects and user_projects !!??
my projects_controller :
def new
#project = Project.new
#user_project=UserProject.new
#user=User.all
#user_lastnames = User.all.collect do |u|
u.lastname
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #project }
end
end
and
def create
#project = Project.new(params[:project])
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.json { render json: #project, status: :created, location: #project }
#user_project=UserProject.create(:project_id => #project.id, :user_id => #project.projectmember)
else
format.html { render action: "new" }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
After creating one instance, the command using the console : #project=Project.all gives :
Project id: 55, projectname: "fdfd", projectdescription: "fdfd", projectheader: "5", projectmember: nil, projecttypename: "dffd">]

Assuming your associations are something like this:
class Project < ActiveRecord::Base
has_many :project_users
has_many :users, :through=>:project_users
end
...for your project form, use the following helper with the "name" option (:name=>'project[user_ids][]') to pass the selected ids to your controller:
<%= select_tag :user_ids, options_for_select(User.all.collect {|u| [u.lastname, u.id]}),:multiple => true, :prompt => 'Select Person', :name=>'project[user_ids][]' %>
That will give you the selected ids in the params and then you'll have to hook up your controller actions to assign them. For example:
def create
#project = Project.new(params[:project])
users = User.find(params[:project][:user_ids]) rescue []
#project.users = users
if #project.save
...
else
...
end
end
def update
#project = Project.find(params[:id])
users = User.find(params[:project][:user_ids]) rescue []
#project.users = users
if #project.update_attributes(params[:project])
...
else
...
end
end
In order to get the selected items to re-select when you render the edit form, I'm assuming you'd have to add that as an argument to the options_for_select method. Not exactly sure about that. An alternative to doing all of the above would be to use checkboxes to select the users since the checked could be set for each assigned user when the form renders. Good luck.

my model was indeed like that :
class Project < ActiveRecord::Base
has_many :project_users
has_many :users, :through=>:project_users
attr_accessible :colourcode, :projectdescription, :user_id, :projectname, :projectheader, :projectmember, :projecttypename
end
i have needed to change in my view ( else Can't mass-assign protected attributes):
<%= select_tag :user_ids, options_for_select(User.all.collect {|u| [u.lastname, u.id]}),:multiple => true, :prompt => 'Select Person', :name=>'project[user_ids][]' %>
by
<%= select_tag :projectmember, options_for_select(User.all.collect {|u| [u.lastname, u.id]}),:multiple => true, :prompt => 'Select Person', :name=>'project[projectmember][]' %>
and in my controller:
def create
#project = Project.new(params[:project])
users = User.find(params[:project][:projectmember]) rescue []
#project.users = users
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.json { render json: #project, status: :created, location: #project }
#user_project=UserProject.create(:project_id => #project.id, :user_id => #project.projectmember)
#user_project=UserProject.create(:project_id => #project.id, :user_id => #project.projectheader)
i got now after creation :
#p=Project.all
Project id: 69, projectname: "test", projectdescription: "blabla", colourcode: "blue", projectheader: "5", projectmember: "---\n- '5'\n- '6'\n", projecttypename: "caucasian">]
#up=UserProject.all
UserProject id: 86, project_id: 69, user_id: 5, created_at: "2012-06-07 13:04:51", updated_at: "2012-06-07 13:04:51">
UserProject id: 87, project_id: 69, user_id: 6, created_at: "2012-06-07 13:04:51", updated_at: "2012-06-07 13:04:51">,
which i am happy about :)
still need to :
delete automatically the project/user couple if the project is deleted
show on the screen the corresponding member names rather than an id number...

Related

Rails - problema con il salvataggio di un array tramite check_boxes

I am trying to create a register for a school, I got to the point where I had to create the class lessons and save presences/absences in it.
I'm thinking about making appear a collection_check_boxes which gathers all the students who belong to the class we are recording the lesson for.
At this point the checkbox is properly displayed on the vista, but it doesn't fill the array student_id of Lesson when it's created.
Il controller
def new
#lesson = Lesson.new
#group_id = params[:group_id]
#students = Student.where(:group_id => #group_id)
end
def create
#lesson = Lesson.new(lesson_params)
respond_to do |format|
if #lesson.save
format.html { redirect_to #lesson, notice: 'Lesson was successfully created.' }
format.json { render :show, status: :created, location: #lesson }
else
format.html { render :new }
format.json { render json: #lesson.errors, status: :unprocessable_entity }
end
end
end
def lesson_params
params.require(:lesson).permit(:date, :starts_at, :finishes_at, :materials, :areas, :homework, :group_id, :student_id)
end
While the view that calls the check_boxes
<div class="field">
<%= form.collection_check_boxes :student_id, Student.where(:group_id => #group_id).order(name: :asc), :id, :name, {}, { multiple: true } %>
</div>
Can anybody help me, please?
Try this
<%= form.collection_check_boxes :student_ids, Student.where(:group_id => #group_id).order(name: :asc), :id, :name %>
ok, i solved
I had to declare the array between the parameters allowed in the controller
def lesson_params
params.require(:lesson).permit(:date, :starts_at, :finishes_at, :materials, :areas, :homework, :group_id, :student_id => [] )
end
i hope this can help someone else.

Unable to access Multiselect Values in Ruby on Rails Controller

I'm trying to implement a multi-select for a many to many relationship in Ruby on Rails, however I'm unable to access the array of strings representing the selected User Ids in the user_ids field.
The following is my project_params after clicking update
"project"=>{"name"=>"Project Name",
"client"=>"Client X", "project_url"=>""},
"user_ids"=>["2", "3", "4", "5"], "commit"=>"Update Project", "id"=>"1"}
The following is my ProjectsController code
def update
puts project_params[:user_ids=>[]]
respond_to do |format|
if #project.update(project_params)
format.html { redirect_to #project, notice: 'Project was successfully updated.' }
format.json { render :show, status: :ok, location: #project }
else
format.html { render :edit }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
def project_params
params.require(:project).permit(:id, :name, :client, :project_url, :user_ids => [])
end
The line puts project_params[:user_ids=>[]] prints a blank line. I've also tried puts project_params[:user_ids] and puts project_params[:user_ids[]] - none of which work
The following is my _form.html.erb Code
<%= select_tag "user_ids",
options_from_collection_for_select(User.all, "id", "name", #project.user),
{ :multiple => true, :size =>10}
%>
The select tag will use the first argument as the key. Hence the values is located on:
params[:user_ids]
or if you are using form builder
<%= form_for #project do |f| %>
<%= f.select :user_ids,
options_from_collection_for_select(User.all, "id", "name", #project.user),
{ :multiple => true, :size =>10}
%>
<% end %>
then it will be available in project_params

Rails form with nested attributes (accepts_nested_attributes_for)

I have this one to many relationship:
class Programa < ActiveRecord::Base
attr_accessible :descripcion, :nombre, :roles_attributes
has_many :roles, :dependent => :restrict
accepts_nested_attributes_for :roles
...
end
class Role < ActiveRecord::Base
attr_accessible :description, :name, :programa_id
belongs_to :programa
...
end
It works in rails console:
> params = { programa: { nombre: 'nuevo', roles_attributes: [ {name: 'role1'}, {name: 'role2'}] }}
> p = Programa.create(params[:programa])
> p
=> #<Programa id: 7, nombre: "nuevo", descripcion: nil, created_at: "2013-10-09 14:07:46", updated_at: "2013-10-09 14:07:46">
> p.roles
=> [#<Role id: 15, name: "role1", description: nil, created_at: "2013-10-09 14:07:46", updated_at: "2013-10-09 14:07:46", programa_id: 7>, #<Role id: 16, name: "role2", description: nil, created_at: "2013-10-09 14:07:46", updated_at: "2013-10-09 14:07:46", programa_id: 7>]
But I can not make it work in the app/views/programas/_form:
<%= form_for(#programa) do |f| %>
<%= render 'shared/form_error_messages', object: f.object %>
<div class="field">
<%= f.label :nombre %>
<%= f.text_field :nombre %>
</div>
<div class="field">
<%= f.label :descripcion %>
<%= f.text_field :descripcion %>
</div>
<% f.fields_for :roles do |builder| %>
<div class="field">
<%= builder.label :name %>
<%= builder.text_field :name %>
</div>
<div class="field">
<%= builder.label :description %>
<%= builder.text_field :description %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Is there anything else that I have to add or remove to make my form shows the roles nested attributes?
This is my the controller for programas:
class ProgramasController < ApplicationController
# GET /programas
# GET /programas.json
def index
#programas = Programa.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #programas }
end
end
# GET /programas/1
# GET /programas/1.json
def show
#programa = Programa.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #programa }
end
end
# GET /programas/new
# GET /programas/new.json
def new
#programa = Programa.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #programa }
end
end
# GET /programas/1/edit
def edit
#programa = Programa.find(params[:id])
end
# POST /programas
# POST /programas.json
def create
#programa = Programa.new(params[:programa])
respond_to do |format|
if #programa.save
format.html { redirect_to #programa, notice: 'Programa was successfully created.' }
format.json { render json: #programa, status: :created, location: #programa }
else
format.html { render action: "new" }
format.json { render json: #programa.errors, status: :unprocessable_entity }
end
end
end
# PUT /programas/1
# PUT /programas/1.json
def update
#programa = Programa.find(params[:id])
respond_to do |format|
if #programa.update_attributes(params[:programa])
format.html { redirect_to #programa, notice: 'Programa was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #programa.errors, status: :unprocessable_entity }
end
end
end
# DELETE /programas/1
# DELETE /programas/1.json
def destroy
#programa = Programa.find(params[:id])
#programa.destroy
respond_to do |format|
format.html { redirect_to programas_url }
format.json { head :no_content }
end
end
end
I just want the nested attributes to be shown in the edit and show actions only.
The form for the nested attributes will only show if there is actually data to show, ie. if your Programa instance has one or more Roles associated with it.
This can be as simple as #programa.roles.build in your controller, before rendering the form, to add a new Role. Any existing roles will be rendered.
edit: You also need to actually render the form, ie. <%= f.fields_for (note missing =).

Rails 3 - Does ID of an object have to be an integer value?

C:\Rails\actuirl5\app\controllers\emailinterests_controller.rb
C:\Rails\actuirl5\app\controllers\emailinterests_controller.rb
submission_id actually a member of emailinterest object. submission_id is suppose to contain the ID value of submission object.
def create
#emailinterest = Emailinterest.new(params[:emailinterest])
#submission = Submission.find(params[:submission_id])
respond_to do |format|
if #emailinterest.save
Notifier.emailinterest_notification(#emailinterest, #submission).deliver
format.html { redirect_to(#emailinterest, :notice => 'Email was successfully sent!') }
format.xml { render :xml => #emailinterest, :status => :created, :location => #emailinterest }
else
format.html { render :action => "new" }
format.xml { render :xml => #emailinterest.errors, :status => :unprocessable_entity }
end
end
end
I keep getting stuck at this line
#submission = Submission.find(params[:submission_id])
with this error.
Couldn't find Submission without an ID
Submission and Emailinterest are both objects.
Emailinterest need some information about the members of the Submission object to be created.
submission_id actually a member of Emailinterest object. submission_id is suppose to contain the ID value of Submission object.
Now I have submission_id as string value. Does it have to be an integer value?
FIX
C:\Rails\actuirl5\app\controllers\emailinterests_controller.rb
def create
#emailinterest = Emailinterest.new(params[:emailinterest])
#submission = Submission.find(params[:submission_id])
respond_to do |format|
if #emailinterest.save
Notifier.emailinterest_notification(#emailinterest, #submission).deliver
format.html { redirect_to(#emailinterest, :notice => 'Email was successfully sent!') }
format.xml { render :xml => #emailinterest, :status => :created, :location => #emailinterest }
else
format.html { render :action => "new" }
format.xml { render :xml => #emailinterest.errors, :status => :unprocessable_entity }
end
end
end
C:\Rails\actuirl5\app\views\submissions_form_new_emailinterest.html.erb
<%= form_for(emailinterest) do |f| %>
<%= hidden_field_tag :submission_id, value = #submission.id %>
<div class="field">
<%= f.label :sender_email %><br />
<%= f.text_field :sender_email %>
</div>
<div class="field">
<%= f.label :sender_email_content %><br />
<%= f.text_area :sender_email_content %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
C:\Rails\actuirl5\app\views\submissions\show.html.erb
<%= render :partial=>"form_new_emailinterest", :locals=>{:emailinterest=>Emailinterest.new} %>
This error:
Couldn't find Submission without an ID
is probably caused by
#submission = Submission.find(nil)
and nil is what a Hash will give when you ask it for a key it doesn't have (unless someone has supplied a different default of course but params and its contained Hashes should give you nil). So you don't have a :submission_id inside params[:emailinterest]. Based on your comments, I would guess that you do have params[:submission_id] so try this:
#submission = Submission.find(params[:submission_id])
and if that doesn't work, do a logger.debug params.inspect and look at your logs to see where :submission_id is (if anywhere at all).
It can be a string or anything, as long as it can be converted to an integer.
You can verify this using your rails console:
ruby-1.9.2-p0 > Product.find("1")
Product Load (0.2ms) SELECT "products".* FROM "products" WHERE "products"."id" = ? LIMIT 1 [["id", "1"]]
=> #<Product id: 1, collection_id: nil, name: "test", description: nil, price: 1000, picture_file_name: nil, picture_content_type: nil, picture_file_size: nil, picture_updated_at: nil, created_at: "2011-07-14 10:10:45", updated_at: "2011-07-14 10:10:45">
If you want to know what's really in submission_id, you can log the value by putting this at the beginning of your method:
logger.debug params[:emailinterest][:submission_id]

When submitting a form with a fields_for part, how can I assign the new id to the fields_for model

I have a form that handles 2 models, Vehiculo and Poliza. This is how I have them set up right now:
class Vehiculo < ActiveRecord::Base
has_one :poliza
end
class Poliza < ActiveRecord::Base
belongs_to :vehiculo
end
The create method on Vehiculo looks like this:
def create
#vehiculo = Vehiculo.new(params[:vehiculo])
#polizadeseguro = Polizadeseguro.new(params[:poliza])
respond_to do |format|
if #vehiculo.save #&& #poliza.save
format.html { redirect_to(#vehiculo, :notice => 'Vehiculo was successfully created.') }
format.xml { render :xml => #vehiculo, :status => :created, :location => #vehiculo }
else
format.html { render :action => "new" }
format.xml { render :xml => #vehiculo.errors, :status => :unprocessable_entity }
end
end
The form on /vehiculos/new has a #fields_for part with the fields from poliza. When I submit the form, it is saving all the fields, but it is not assigning the just created id from vehiculo, to vehiculo_id on the Polizas table. After reading many questions about this online, It seems that it should save it "automagically" based on the relationships on the model. Is this true? If so, why isn't it working? If not, what do I need to add to the create method so I resolve this?
Thanks!
Update:
After updating the create method with json as output as suggested here is what I get:
{
"utf8"=>"✓",
"authenticity_token"=>"tEhNC4J17h+KvNgXv1LLkVyufQwU2uAT18P7msQxiqA=",
"vehiculo"=>{
"marca_id"=>"2",
"modelo_id"=>"4",
"color"=>"Blanco",
"ano"=>"2011",
"chassis"=>"123456789",
"placa"=>"G123456",
"cliente_id"=>"1",
"entaller"=>"0",
"vip"=>"0"
},
"poliza"=>{
"compania"=>"Comp1",
"numeropoliza"=>"736458",
"vencimiento(1i)"=>"2011",
"vencimiento(2i)"=>"9",
"vencimiento(3i)"=>"21"
}
}
That's the output, so at least it is getting the fields from the form, but it is not inserting them to the polizas table.
You need to make sure that your parent model accepts nested attributes for the child model:
class Vehiculo < ActiveRecord::Base
has_one :poliza
accepts_nested_attributes_for :poliza
end
Assuming your form is set up correctly, your params will look something like this:
params = {
:vehiculo => {
:field => "value",
:another_field => "value",
:poliza => {
:poliza_field => "poliza value"
}
}
}
So all you should need in your controller is:
def create
#vehiculo = Vehiculo.new(params[:vehiculo])
respond_to do |format|
if #vehiculo.save #&& #poliza.save
format.html { redirect_to(#vehiculo, :notice => 'Vehiculo was successfully created.') }
format.xml { render :xml => #vehiculo, :status => :created, :location => #vehiculo }
else
format.html { render :action => "new" }
format.xml { render :xml => #vehiculo.errors, :status => :unprocessable_entity }
end
end
end
[Update]
Here's what you'll need to have to have this all work.
As mentioned above, you need accepts_nested_attributes_for.
Next, make sure your new action is building the child.
class VehiculosController < ApplicationController
def new
#vehiculo = Vehiculo.new
#vehiculo.build_poliza
end
def create
vehiculo = Vehiculo.new(params[:vehiculo])
if vehiculo.save
redirect_to root_path, :notice => "Success"
else
redirect_to root_path, :alert => "Failure"
end
end
end
Finally, in your view, reference the child model using fields_for :child_model, as such:
<%= form_for #vehiculo do |f| %>
<p>Whatever Field: <%= f.text_field :whatever %></p>
<%= f.fields_for :poliza do |p| %>
<p>Polizo Field: <%= p.text_field :something %></p>
<% end %>
<% end %>

Resources