Auxiliary parameter in a form - ruby-on-rails

I'm trying to manage invitations to an event with a "participation" model. I'd like that, when I invite a user, i could insert his name in the form, instead of user_id.
user.rb
class User < ActiveRecord::Base
attr_accessible :id, :name
has_many :participations
end
participation.rb
class Participation < ActiveRecord::Base
attr_accessible :event_id, :user_id
belongs_to :event
belongs_to :user
end
views/participations/new.html.erb
<%= form_for(#participation) do |f| %>
<%= f.hidden_field :event_id, value: #event.id %>
<%= f.label :user_id, 'User Id' %>
<%= f.number_field :user_id %>
<%= f.submit 'Invite' %>
<% end %>
How can i do?

Try by this:
<%= form_for(#participation) do |f| %>
<%= f.hidden_field :event_id, value: #event.id %>
<%= f.label :user_id, 'User Id' %>
<%=f.collection_select :user_id,User.all,:id,:name,:label => "User" ,:include_blank => false%>
<%= f.submit 'Invite' %>
<% end %>
You may turn include_blank to true or false as you wish to always have a user or not.
Feel free to ask for more if this doesn't solve your problem.

Related

Rails has_many :through create association and associated model on parent "show" view

I have three models in my rails 5 application... What I want to do is to be able to create a note on the person's "show" view, then the note should automatically link to that person and any other person I choose to attach the note to.
Here's where I got up to
Note
class Note < ApplicationRecord
has_many :person_notes
has_many :people, through: :person_notes
accepts_nested_attributes_for :person_notes
end
Person Note (Join table)
class PersonNote < ApplicationRecord
belongs_to :person
belongs_to :note
end
Person
class Person < ApplicationRecord
has_many :person_notes
has_many :notes, through: :person_notes
accepts_nested_attributes_for :person_notes
accepts_nested_attributes_for :notes
end
In my "show" section of my "people" controller I have the following:
def show
#notep = Note.new()
#person.notes << #notep
end
This is creating a join of a new note to my person record every time I open the page (obviously i only want the join to happen on the note I have created.)
I have rendered this in a modal as a partial in my "show" view (there is an "end" and a submit button but it's in between 3 divs and I know they weren't the cause of the issue so i didn't include them.:
<%= simple_form_for(#notep, remote: true) do |f| %>
<%= f.error_notification %>
<%= f.input :subject %>
<%= f.input :note %>
<%= f.input :date, html5: true %>
<div class="input-field">
<%= f.check_box :isalert, :id => "alert" %>
<%= f.label :isalert, :for => "alert" %>
</div>
<div class="input-field">
<%= f.check_box :archived, :id => "archived" %>
<%= f.label :archived, :for => "archived" %>
</div>
<div class="input-field">
<%= f.check_box :deleted, :id => "deleted" %>
<%= f.label :deleted, :for => "deleted" %>
</div>
<%= f.input :datecreated, html5: true %>
<%= f.input :user_id %>
<%= f.simple_fields_for :person_notes do |builder| %>
<%= builder.association :person, label_method: :lstfstfullname %>
<%= builder.input :deleted %>
<%= builder.input :datecreated, html5: true %>
<%= builder.input :user_id %>
<% end %>
You can probably tell I'm a total newb, but I'd appreciate any help I can get.
Thanks,
Leah
If I'm understanding this correctly, you'll want a separate Notes controller and create action to handle note creation. Then in your People show view, you can add a form and input field that submits to NotesController#create.

Syntax for select options helper method for second distant has_many through association

How do you correctly fill in the following syntax to create a dropdown select tag with each option being the data of another table?
<%= form_for(#celebrity, :html => { :multipart => true }) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :image %>
<%= f.file_field :image %>
<%= f.label :character %>
<%= f.collection_select(:character, :celebrity_id, #characters, :id, :name) %> #this line is the question
<%= f.submit 'Save' %>
<% end %>
I followed the API documentation here, but it doesn't seem to work.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select
class Celebrity < ActiveRecord::Base
has_many :characters, through: :char_celeb_joins
has_many :char_celeb_joins
has_many :universes, through: :characters
end
class Character < ActiveRecord::Base
has_many :universes, through: :univ_char_joins
has_many :univ_char_joins
has_many :celebrities, through: :char_celeb_joins
has_many :char_celeb_joins
end
class Universe < ActiveRecord::Base
has_many :characters, through: :char_univ_joins
has_many :char_univ_joins
has_many :celebrities, through: :characters
end
But I get a
undefined method 'merge' for :name:Symbol
in the browser, when I go to a view that brings up this code.
NoMethodError in Celebrities#edit
The error is due to this line
<%= f.collection_select(:character, :celebrity_id, #characters, :id, :name) %>
When using with form_for,you have to set it like this
<%= f.collection_select(:celebrity_id, #characters, :id, :name) %>
And also your form_for object is #celebrity and you are giving :character as object to collection_select.It should be :celebrity in the collection_select too.Ofcourse you have worry about this when using collection_select without form_for.In your case it would be
<%= collection_select(:celebrity, :celebrity_id, #characters, :id, :name) %>
You can use helper:
Writer this code in any of the helper:
def character_for_select
Character.all.collect { |m| [m.id, m.name] }
end
Update your form
<%= form_for(#celebrity, :html => { :multipart => true }) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :image %>
<%= f.file_field :image %>
<%= f.label :character %>
<%= f.select(:character, character_for_select, :prompt => 'Select character') %>
<%= f.submit 'Save' %>
<% end %>
You will get your answer :)
Have you tried to use options_for_select. In your case, your code should be something like this:
app/helpers...
def options_for_characters( selected=nil )
options = Character.all.map { |c| [d.id, c.name] }
options_for_select( options, selected )
end
app/views...
...
<%= f.select(:character, options_for_characters, :prompt => 'Select character') %>
...

Rails nested Attributes of join table won't be saved

Nested attributes of join model won't be saved. relation id's seems to be missing. The following error messages are added when the fields get validated:
* Assigned projects user can't be blank
* Assigned projects project can't be blank
The submitted params look like this ( <%= debug(params) %> )
--- !map:ActionController::Parameters
utf8: "\xE2\x9C\x93"
authenticity_token: HrF1NHrKNTdMMFwOvbYFjhJE1ltlKbuz2nsfBYYBswg=
project: !map:ActionController::Parameters
name: Peter Pan
assigned_projects_attributes: !map:ActiveSupport::HashWithIndifferentAccess
"0": !map:ActiveSupport::HashWithIndifferentAccess
position: Group Leader
currency: " Neverland Dollars"
commit: Add Project
action: create
controller: projects
I have 3 models, as followed:
class User < ActiveRecord::Base
has_many :assigned_projects
has_many :projects, :through => :assigned_projects
has_many :created_projects, :class_name => "Project", :foreign_key => :creator_id
end
class AssignedProject < ActiveRecord::Base
belongs_to :user, class_name: "User"
belongs_to :project, class_name: "Project"
attr_accessible :project_id, :user_id, :position, :project_attributes
accepts_nested_attributes_for :project
validates :user_id, presence: true
validates :project_id, presence: true
validates :position, presence: true
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :assigned_projects
has_many :users, :through => :assigned_projects
belongs_to :creator, :class_name => "User", :foreign_key => :creator_id
attr_accessible :name, :creator_id, :currency :assigned_projects_attributes
accepts_nested_attributes_for :assigned_projects
validates :name, presence: true, length: { minimum: 3, maximum: 100 }
validates :currency, presence: true, length: { minimum: 1, maximum: 5 }
validates :creator_id, presence: true
end
So each User can create a Project. He can add any User to the Project through the join model.
Each Project belongs to a User resp. Creator and has_many user through assigned_projects
I want to give each user of a project a "position", which should be saved in the join model: assigned_project :position
the Project controller looks like that:
class ProjectsController < ApplicationController
def new
#project = Project.new
#project.assigned_projects.build(user_id: current_user)
end
def create
#project = current_user.assigned_projects.build.build_project(params[:project])
#project.creator = current_user
if #project.save
redirect_to current_user
else
render 'new'
end
end
end
and the project/new.html.erb form looks like that:
<%= form_for( #project ) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.fields_for :assigned_projects do |ff| %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.label :currency %>
<%= f.text_field :currency %>
<%= f.submit "Add Project", class: "" %>
<% end %>
UPDATE: current controller & view
def create
#project = Project.new(params[:project])
if #project.save
redirect_to current_user
else
render 'new'
end
end
<%= form_for( #project ) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.hidden_field :creator_id, value: current_user.id %>
<%= f.fields_for :assigned_projects, #project.assigned_projects do |ff| %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.label :currency %>
<%= f.text_field :currency %>
<%= f.submit "Add Project", class: "" %>
<% end %>
View:
I think you need to pass the objects collection #project.assigned_projects you built in the new action to the fields_for:
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.fields_for :assigned_projects, #project.assigned_projects do |ff| %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.label :currency %>
<%= f.text_field :currency %>
<%= f.submit "Add Project", class: "" %>
Controller:
If i understood the first line in the create action i think you try to re-build the project assigned_projects in-order to stamp the creator attribute !!
Instead you could remove this line and put a hidden field in the nested for, something like:
<%= ff.hidden_field :creator, current_user %>
So your controller looks pretty basic now:
def create
#project = Project.new(params[:prject])
if #project.save #nested objects will be saved automatically
redirect_to current_user
else
render 'new'
end
end
What does the build_project method do?
I think in your controller you should just have build, not build.build_project, so like this:
#project = current_user.assigned_projects.build(params[:project])
of if build_project is a method used to create the params then
#project = current_user.assigned_projects.build(project_params)
in the case of rails 4 you would need something like this:
def project_params
params.require(:project).permit(:your_params)
end
In the case of rails 3 I think you need to add
attr_accessible :param1, :param2
in the project model for the parameters you want to set.
Problem is solved by removing the validations for project_id and user_id in the join table "AssignedProject"
So the join Model looks like that:
# Join Model AssignedProject
class AssignedProject < ActiveRecord::Base
belongs_to :user#, class_name: "User"
belongs_to :project#, class_name: "Project"
attr_accessible :project_id, :user_id, :position, :project, :project_attributes
accepts_nested_attributes_for :project
validates :position, presence: { message: " can't be blank." }
end
The New and Create methods look like that:
# Projects Controller
class ProjectsController < ApplicationController
def new
#project = Project.new
#project.assigned_projects.build(user_id: current_user)
end
def create
#project = Project.new(params[:project])
if #project.save
#project.assigned_projects.create(user_id: current_user)
redirect_to current_user
else
render 'new'
end
end
end
And the form in the view for the new method looks like that:
<%= form_for( #project ) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.hidden_field :creator_id, value: current_user.id %>
<%= f.fields_for :assigned_projects, #project.assigned_projects do |ff| %>
<%= ff.hidden_field :project_id, value: #project %>
<%= ff.hidden_field :user_id, value: current_user.id %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.label :currency %>
<%= f.text_field :currency %>
<%= f.submit "Add Project", class: "" %>
<% end %>

Nested form in many to many relationship in rails 4

I have a model Contact which has a many-to-many relationship with Company:
class Contact < ActiveRecord::Base has_many :contactcompanies
has_many :companies, through: :contactcompanies
Company model:
class Company < ActiveRecord::Base
has_many :contactcompanies
has_many :contacts, through: :contactcompanies
ContactCompany:
class ContactCompany < ActiveRecord::Base
belongs_to :company
belongs_to :contact
contacts_controller.rb:
def new
#contact = Contact.new
#all_companies = Company.all
#contact_company = #contact.contactcompanies.build
end
contact create form where I want to have a multiple select for companies:
<%= form_for #contact do |f| %>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
<%= f.label :image_url %>
<%= f.text_field :image_url %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= fields_for(#contact_company) do |cc| %>
<%= cc.label "All Companies" %>
<%= collection_select(:companies, :id, #all_companies, :id, :name, {}, { :multiple => true }) %>
<% end %>
<div class="form-action">
<%= f.submit nil, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
contacts_path, :class => 'btn' %>
</div>
<% end %>
My issue is when I go to /contacts/new I get this error:
Circular dependency detected while autoloading constant Contactcompany
Any ideas? I'm searching for hours without success. Thanks
You have declared your class as "ContactCompany"
This implies:
has_many :contact_companies
has_many :contacts, through: :contact_companies
Without the underscore, it is looking for a class named Contactcompany, which does not exist.

Nested form not rendering Rails 3.2

The nested form in the view just won't render, unless I remove the f attribute, in which case the submit button will not work. I have two models, job and employer. I've been following the railscast here
job.rb
attr_accessible :title, :location, :employers_attributes,
belongs_to :employers
accepts_nested_attributes_for :employers
employer.rb
attr_accessible :companyname, :url
has_many :jobs
jobs_controller.rb
def new
#job = Job.new
#employer = Employer.new
end
_form.html
<%= form_for(#job) do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :location %>
<%= f.text_field :location %>
<%= f.fields_for :employers do |builder| %>
<%= builder.label :companyname, "Company Name" %>
<%= builder.text_field :companyname %>
<%= builder.label :url, "Web Address" %>
<%= builder.text_field :url %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Any input would be brilliant - thanks
This happens because your job has no employers.
Change your code to this:
def new
#job = Job.new
#job.employer = #job.build_employer
end
In your job.rb change:
attr_accessible :title, :location, :employer_attributes,
belongs_to :employer
accepts_nested_attributes_for :employer
This line:
belongs_to :employers
Should be singulars:
belongs_to :employer
With this association you not need nested form you can use select for pick employer for each job.
But if you need many employers for each job and each job can have many employers see this screencast

Resources