How do I include has_many relationships in a Rails form? - ruby-on-rails

I have two models, Artist and User that are connected through a third model, ArtistMembership.
From the edit/new Artist form, I want to be able to edit the role of any User in an existing ArtistMembership relationship for that Artist, delete ArtistMemberships, and add new AtistMembership relationships, which would include a User and :role.
Here's my Artist model:
class Artist < ActiveRecord::Base
has_many :artist_memberships, foreign_key: "artist_id", dependent: :destroy
attr_accessible :bio, :created_at, :email, :location, :name, :updated_at, :website, :pic
accepts_nested_attributes_for :artist_memberships, :allow_destroy => :true
...
end
Here's my User model:
class User < ActiveRecord::Base
...
has_many :artist_memberships, foreign_key: "user_id"
...
end
Here's my ArtistMembership model:
class ArtistMembership < ActiveRecord::Base
belongs_to :artist, class_name: "Artist"
belongs_to :user, class_name: "User"
attr_accessible :artist_id, :created_at, :role, :user_id
end
If I have a _form.hml.erb too, for editing Artists that starts:
<%= form_for #artist do |artist_form| %>
<div class="field">
<%= artist_form.label :name %>
<%= artist_form.text_field :name %>
</div>
..
<div class="actions">
<%= artist_form.submit %>
</div>
<% end %>
how can I create the related ArtistMembership forms for the aforementioned functionality?

May be this is helpful for you, see this field_for
you can use accepts_nested_attributes_for(*attr_names)

Maybe you are looking for this method.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
Refer to the "One-to-many" section.
But if I were you, I would rather use the "Nested Resource" technic.
http://guides.rubyonrails.org/routing.html#nested-resources

Related

Nested checkboxes in Rails

I'm trying to create an event app where each event has multiple tables and each table has multiple people sitting at a table the event has multiple tickets which map the people to the tables that they are sitting at -> in order to achieve this I have created a checkbox nested in the fields_for :tables (which is in turn in the event form) I presume something is wrong with either the strong parameters or the form itself but I have not been able to find any information that provides a solution to the problem.After checking the checkboxes in the form indicating which people are going to be sitting at this table and submitting the form and returning to the form I find that the checkboxes are no longer checked???
here are the contents of my model files
# models
class Event < ActiveRecord::Base
has_many :tables, dependent: :destroy
has_many :people , through: :tickets
has_many :tickets
accepts_nested_attributes_for :tickets, allow_destroy: true
accepts_nested_attributes_for :tables, allow_destroy: true
end
class Table < ActiveRecord::Base
belongs_to :event
has_many :tickets
has_many :people, through: :tickets
end
class Ticket < ActiveRecord::Base
belongs_to :table
belongs_to :person
end
class Person < ActiveRecord::Base
has_many :tickets
has_many :tables, through: :tickets
end
Here is the form with parts omitted for brevity.
<%= form_for(#event) do |f| %>
...
<%= f.fields_for :tables do |builder| %>
<%= render 'table_field', f: builder %>
<% end %>
<%= link_to_add_fields "Add Table", f, :tables %>
...
<% end %>
And here is the checkbox list I have implemented within the table_field.
<% Person.all.each do |person| %>
<div class="field">
<%= check_box_tag "table[people_ids][]", person.id, f.object.people.include?(person) %> <%= f.label [person.first_name, person.last_name].join(" ") %>
</div>
<% end %>
this is the event_params
def event_params
params.require(:event).permit(:name, :description, :start, :end, :latitude, :longitude, :address, :data, :people_ids => [], tables_attributes: [:id, :number, :size, :people_ids => []]).tap do |whitelisted|
whitelisted[:data] = params[:event][:data]
end
How do I get the checkboxes to be persistently checked in this form?
You can use http://apidock.com/rails/v4.0.2/ActionView/Helpers/FormOptionsHelper/collection_check_boxes
<%= f.collection_check_boxes(:people_ids, Person.all, :id, :name) do |person| %>
<%= person.label { person.check_box } %>
<% end %>
It will persist data as well.

Nested Attributes for a Rich Join Table, using simple_form Rails

I want to create a form that has nested attributes, which populates a record within a rich join table. (That created record within the rich join table of course should have the appropriate foreign keys.)
I have yet to find a thorough answer on creating nested form fields on a has_many :through relationship. Please help!
For this example, I have a user form. Within that form, I am also trying to populate a record within the users_pets table (rich join table).
Additional question: are rich join models supposed to be singular or plural? Example: app/models/owners_pets.rb or app/models/owners_pet.rb.
app/models/owner.rb
class Owner < ActiveRecord::Base
has_many :owners_pets, allow_destroy: true
has_many :pets, through: :owners_pets
end
app/models/pet.rb
class Pet < ActiveRecord::Base
has_many :owners_pets, allow_destroy: true
has_many :owners, through: :owners_pets
end
app/models/owners_pets.rb
class OwnersPet < ActiveRecord::Base
belongs_to :owners
belongs_to :pets
end
app/controller/owners.rb
def owner_params
params.require(:owner).permit(:first_name, owners_pets_attributes: [:id, :pet_name, :pet_id])
end
app/views/owners/_form.html.erb
<%= simple_form_for(#owner) do |f| %>
<%= f.input :first_name %>
<%= f.simple_fields_for :owners_pets do |ff|
<%= ff.input :pet_name %>
<% end %>
<div>
<%= f.button :submit %>
</div>
<% end %>
Here is the answer, thanks to a bunch of help from a mentor. It helps me to keep in mind that rich join naming conventions should NOT be pluralized at the very end, just like other non-rich-join models. Ex: book_page.rb NOT books_pages.rb. Even books_page.rb would work (just update your strong params and database table accordingly). The important part is that the entire model must follow the rails convention of the model being singular (no 's' on the end).
Below in the rich join model, I made the decision to name it the completely singular version: owner_pet.rb as opposed to the other version: owners_pet.rb. (Therefore of course, my database table is named: owner_pets)
app/models/owner.rb
class Owner < ActiveRecord::Base
has_many :owner_pets
has_many :pets, through: :owner_pets
accepts_nested_attributes_for :owner_pets, allow_destroy: true
end
app/models/pet.rb
class Pet < ActiveRecord::Base
has_many :owner_pets
has_many :owners, through: :owner_pets
end
app/models/owner_pet.rb
class OwnerPet < ActiveRecord::Base
belongs_to :owner
belongs_to :pet
end
app/controller/owners.rb
def new
#owner = Owner.new
#owner.owner_pets.build
end
private
def owner_params
params.require(:owner).permit(:first_name, owner_pets_attributes: [:_destroy, :id, :pet_name, :pet_id, :owner_id])
end
app/views/owners/_form.html.erb
<%= simple_form_for(#owner) do |f| %>
<%= f.input :first_name %>
<%= f.simple_fields_for :owner_pets do |ff| %>
<%= ff.input :pet_name %>
<%= ff.input :pet_id, collection: Pet.all, label_method: "pet_type" %>
<% end %>
<div>
<%= f.button :submit %>
</div>
<% end %>
Your join table is the problem:
It should be belongs_to :owners belongs_to :pets for the join table to work
Plus the rich join model should be pluralised, as in: owners_pets

Is it ok to use User.find in a view partial?

I have 3 models
User
Business (acts_as_commentable using acts_as_commentable gem)
Comment (belongs to user)
On the Business show page I display all the comments associated with that business:
Name:<%= #business.name %>
<%= render #business.comments %>
comments partial
Comment: <%= comment.comment %><br >
By: <%= User.find(comment.user_id).name %>
Is there a better way to display the name of the user instead of using User.find?
Here are my models
User
class User < ActiveRecord::Base
attr_accessible :email, :name
end
Business
class Business < ActiveRecord::Base
attr_accessible :name, :category
has_reputation :votes, source: :user, aggregated_by: :sum
acts_as_commentable
end
Comment
class Comment < ActiveRecord::Base
include ActsAsCommentable::Comment
attr_accessible :comment, :user_id
belongs_to :commentable, :polymorphic => true
default_scope :order => 'created_at ASC'
belongs_to :user
validates :user_id, presence: true
end
I believe you can just use this:
<%= comment.user.name %>
Rails will handle loading for you.
Each comment belongs to a user. So, you just have to get the user this way
comment.user.name
I think the best way is:
<%= comment.user.try(:name) %>
I see you have validates :user_id, presence: true to have user. But if the use has deleted, comment.user.name will put the error.
Or you can use:
<%= comment.user.blank? ? "Visitor" : comment.user.name %>

rails list all items for a many to many including design

So I have the following models:
Image:
class Image < ActiveRecord::Base
has_many :product_images
has_many :products, :through => :product_images
attr_accessible :asset, :name, :description, :product_ids, :file_content_type, :is_boolean
accepts_nested_attributes_for :product_images
has_attached_file :asset
end
ProductImage:
class ProductImage < ActiveRecord::Base
belongs_to :product
belongs_to :image
attr_accessible :is_thumbnail
end
and Product:
class Product < ActiveRecord::Base
has_many :images, :through => :product_images
has_many :product_images
attr_accessible :name, :description, :thumbnail, :searchTerms, :group_ids, :upload_file_ids
end
Now what I would like to do on the images form is display a checkbox for all the products and then another checkbox for the is_thumbnail attribute
I have had a look into using simple_fields_for but this will only display if the product has already been added. Is there a way to do this?
<%= f.simple_fields_for(:product_images) do |builder| %>
<%= builder.input :is_thumbnail %>
<%= builder.association :products, include_blank: false %>
<% end %>
I'm not very familiar with simple_fields however building form inputs base on an instance will only allow you to "represent" that instance.
This means that you could print all already associated products using
builder.association :products
but if you want to print all products in your database you will need to fetch them, loop and display them in your form.

Has_many accepts_nested_attributes Can't mass assign attribute

I'm having issues with a form in a custom registration for Devise. This form needs to have both User and Business model information in there that I'll be creating both at once on the form. It's important that this can't be a multi-step registration form - I need to have both the User and Business models filled out simultaneously, as part of the requirements.
I have the following models:
user.rb
class User < ActiveRecord::Base
has_many :businessusers, :include => :business
has_many :businesses, :through => :businessusers
accepts_nested_attributes_for :businessusers
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :role, :businessusers
business.rb
class Business < ActiveRecord::Base
has_many :businessusers
has_many :users, :through => :businessusers
businessuser.rb
class Businessuser < ActiveRecord::Base
belongs_to :business
belongs_to :user
end
businessusers migration
create_table :businessusers do |t|
t.integer :user_id
t.integer :business_id
end
In my registration form, I have the following code:
Business Information
<br>
<%= f.fields_for :businessusers do |business_form| %>
<%= business_form.input :name %>
<%= business_form.input :address_line1 %>
<%= business_form.input :address_line2 %>
<%= business_form.input :city %>
Finally, here is my controller:
custom_registration_controller.rb
def create
#user=User.new(params[:user])
#business = #user.businesses.build(params[:business]) unless params[:business] [:name].blank?
end
EDIT: I've gotten past the mass assign attribute problem, but now I have another one.
Does anyone know where I'm going wrong? Before, I was disabling id on businessusers table. But this gave me an error saying I needed a primary ID on the table. So when I allow the field :id, it makes it so that the form no longer has the business fields on it.
Thanks!

Resources