I have a form that creates a signed_user. This is the first line of the form:
<%= form_for(setup_user(#signed_user)) do |f| %>
The setup_user is in my application helper:
def setup_user(user)
user.tap do |u|
u.build_invitation
end
end
These are the model associations:
signed_user model:
has_one :invitation, :foreign_key => "sender_id"
invitation model:
belongs_to :sender, :class_name => 'SignedUser'
So why is a user being created without an invitation? I checked my console and the user's invitation is nil...
What you want is a nested form. All the details are available in the article but basically make sure you use accepts_nested_attributes_for in your SignedUser model.
class SignedUser < ActiveRecord::Base
...
has_one :invitation, :foreign_key => "sender_id"
accepts_nested_attributes_for :invitation, :allow_destroy => true
...
end
If you want your form to modify attributes from the Invitation model (in addition to attributes from the SignedUser), you'll also need to use fields_for in your form. For example:
<%= form_for setup_user(#signed_user) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
// More user form fields
<%= f.fields_for :invitation do |cf| %>
<%= cf.label :event_name %>
<%= cf.text_field :event_name %>
// More invitation form fields
<% end %>
<%= submit_tag %>
<% end %>
Related
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.
I GOT TWO PROBLEMS:
-I'm stuck with creating a project which includes nested attributes for :position
-I got it nearly working for editing the project details plus the :position attribute, but the fields_for :assigned_projects ads all the fields for all users who are assigned to the project.
I have 3 Models:
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 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, :controlled, :currency, :creator_id, :assigned_projects
accepts_nested_attributes_for :assigned_projects#, :allow_destroy => true
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, :user, :user_attributes
accepts_nested_attributes_for :user
end
Each User can create a Project and is the Projects.creator
Each Project has_many Users through the join model Assigned_Project
Each User can have a different position in the project, so I want to save the :position in the join model AssignedProject.
if a user creates a Project, he should be able to edit the project attributes PLUS the :position attribute of the new join model.
Now the Form field for New.Project and Edit.Project
/project/new.htm.erb
<%= form_for( setup_new_project(#project) ) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.fields_for :assigned_projects do |ff| %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.submit "Add Project", class: "" %>
<% end %>
/project/edit.htm.erb
<%= form_for( setup_project(current_project) ) do |f| %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.fields_for :assigned_projects do |ff| %>
<%= ff.label :position %>
<%= ff.text_field :position%>
<% end %>
<%= f.submit "Update Project", class: "" %>
<% end %>
And I have the following setup methods as described in this article:
http://www.sitepoint.com/complex-rails-forms-with-nested-attributes/
module FormHelper
def setup_project(project)
project.assigned_projects ||= AssignedProject.new
project
end
def setup_new_project(project)
project.assigned_project = AssignedProject.new
project
end
end
I hope the problem is clear enough.
for creating a new project the current error message is:
undefined method `assigned_project='
15: <%= render 'shared/user_sidebar_menu' %>
16:
17: <div class="span4 offset1">
18: <%= form_for( setup_new_project(#project) ) do |f| %>
19:
20: <%= render 'shared/error_messages', object: f.object %>
21:
UPDATE: added projects_controller.rb
projects_controller.rb
class ProjectsController < ApplicationController
def new
#project = Project.new
end
def create
#project = Project.new(params[:project])
#project.creator = current_user
if #project.save
current_user.assigned_projects.create(project: #project)
redirect_to current_user
else
render 'new'
end
end
end
Update setup_new_project method as below:
def setup_new_project(project)
project.assigned_projects.build ## Updated this line
project
end
Use project.assigned_projects(Notice plural) instead of project.assigned_project(Notice singular WRONG).
User and AssignedProject model are in a 1-M relationship. So, you get dynamic method assigned_projects=(Notice plural), you are getting error as you called assigned_project=(Notice singular) which does not exist.
UPDATE
undefined method each for <AssignedProject:0x007ff7aa55b528>
Use project.assigned_projects.build instead of project.assigned_project = AssignedProject.new.
UPDATE 2
You are approaching this incorrectly. The form helpers are totally not required. All you need to do is update the new and create actions as below:
def new
#project = Project.new
#project.assigned_projects.build
end
and update the form_for in both new and edit view's as below:
<%= form_for(#project) do |f| %>
I'm new to rails and just cant get that problem solved.
i have 3 models. Orders, Products and LineItems.
I want to have a order form with checkboxes for each product. User selects appropriate products and submits the order.
I cannot get the form to create the correct hash.
class Order < ActiveRecord::Base
attr_accessible :account_id, :user_id
has_many :line_items, :dependent => :destroy
end
class LineItem < ActiveRecord::Base
attr_accessible :account_id, :product_id, :order_id
belongs_to :orders
belongs_to :product
end
Here the view:
<%= form_for 'line_items[]' do |f| %>
<%= f.select :account_id, options_from_collection_for_select( Account.all,
:id, :name ), :prompt => 'Select Account' %>
<% Product.all.each do |product| %>
<div>
<%= check_box_tag 'line_items[product_ids][]', product.id %>
</div>
<% end -%>
<div>
<%= f.submit 'save' %>
</div>
thanks!
You would need to use accepts_nested_attributes_for in your model to enable nested atributes from associated models. You may also want to check out this railscast and adapt to your needs.
For example in the orders model:
class Order < ActiveRecord::Base
attr_accessible :account_id, :user_id
has_many :products #This makes the association to products
has_many :line_items, :dependent => :destroy
accepts_nested_attributes_for :products #This allows the attributes from products accessible
end
Then the form could be:
<%= form_for #order do |f| %>
<%= f.select :account_id, options_from_collection_for_select( Account.all,
:id, :name ), :prompt => 'Select Account' %>
<%= f.fields_for :product do |product_form| %>
<%= product_form.check_box :id %>
<% end %>
<%= f.submit %>
<% end %>
class User < ActiveRecord::Base
belongs_to :person, :dependent => :destroy
accepts_nested_attributes_for :person, :allow_destroy => true
attr_accessible :person_attributes
end
class Person < ActiveRecord::Base
has_many :phone_numbers, :as => :phoneable, :dependent => :destroy
has_one :user
accepts_nested_attributes_for :phone_numbers
end
class PhoneNumber < ActiveRecord::Base
belongs_to :phoneable, :polymorphic => true
end
<%= form_for #user do |user_form| %>
<%= user_form.fields_for :person do |person_form| %>
<%= person_form.fields_for :phone_numbers do |phone_number_form| %>
<%= phone_number_form.text_field :number %>
<% end %>
<% end %>
<% end %>
This works. It does what I expect, but I want more than one phone number in my form. How can I accomplish that?
user[person_attributes][phone_numbers_attributes][0][number]
Why does fields_for add [0] ?
If I want multiple phone numbers, would the second look like this?
user[person_attributes][phone_numbers_attributes][1][number]
If so, how?
If I can get multiple phone numbers in the database, my next question will be how to include other phone number attributes along with each number? e.g.: description
user[person_attributes][phone_numbers_attributes][0][number]
user[person_attributes][phone_numbers_attributes][0][description]
fields_for adds "[0]" because its a many relationship and it needs to make an array, with an index for each relation member [0], [1] ...
So yes, the second would have [1], rails adds that by itself via the helpers.
To include other phone number attributes:
<%= form_for #user do |user_form| %>
<%= user_form.fields_for :person do |person_form| %>
<%= person_form.fields_for :phone_numbers do |phone_number_form| %>
<%= phone_number_form.text_field :number %>
<%= phone_number_form.text_field :description %>
<% end %>
<% end %>
<% end %>
I am having some issues with nested models in a form, using Rails 3.1rc4.
I presently have models that look like this:
class Sale < ActiveRecord::Base
attr_accessible :customer_id, :vehicle_id, :sale_date
belongs_to :customer
accepts_nested_attributes_for :customer
end
and
class Customer < ActiveRecord::Base
attr_accessible :dealership_id, :first_name, :last_name, :address1, :email
belongs_to :dealership
has_many :sales
has_many :vehicles, :through => :sales
end
I've obviously truncated these slightly, but all the important info is there.
I am attempting to set up a sale form that will also allow me to create a new customer, hence the accepts_nested_attributes_for :customer line in the sale model.
My form view looks like (again truncated, only the important part):
<%= form_for #sale, :html => {:class => 'fullform'} do |f| %>
<%= f.error_messages %>
<%= field_set_tag 'Customer Details' do %>
<% f.fields_for :customer do |builder| %>
<%= builder.label :first_name %><br>
<%= builder.text_field :first_name %>
<% end %>
<% end %>
<% end %>
The problem I am having is that neither the text field nor the label for :first_name are showing up when the form is rendered - there is no error message, it just doesn't appear.
I should mention that I have tried both with and without #sale.customer.build in the new method of my controller, but it seems to have had no effect.
Thanks!
Can anyone suggest what I am doing wrong?
EDIT: For the avoidance of doubt, my sales controller's new method looks like:
def new
#sale = Sale.new
#sale.customer.build
end
Add customer_attributes to your attr_accessible in the Sale model.
Another mistake; Replace:
<% f.fields_for :customer do |builder| %>
With:
<%= f.fields_for :customer do |builder| %>