Selecting belongs_to parents in a form? - ruby-on-rails

Imagine I have something like this:
class Employer < ActiveRecord::Base
has_many :employees
end
class Employee < ActiveRecord::Base
belongs_to :employer
end
And I want to create a new Employee, and give a form with with a drop down box, where I can select which Employer I wish to associate it with. The dropdown should list every employer in the system. How can I do this?
Thanks.

I think you haven't understood what this association does. Or I haven't understood what you really want.
If you want to display ALL employers in a view, you simply have to fetch them in the corresponding controller action and save it in an instance variable. Then you can access its contents inside the view.
controller action:
#employers = Employer.all
...
corresponding view:
<%= collection_select #employers %>

Related

Rails: Polymorphic Associations - Create Child In Form And Choose Parent

To illustrate my question, i'll use the following association as listed on ruby guides for polymorphic associations:
class Picture < ApplicationRecord
belongs_to :imageable, polymorphic: true
end
class Employee < ApplicationRecord
has_many :pictures, as: :imageable
end
class Product < ApplicationRecord
has_many :pictures, as: :imageable
end
Now in our :pictures table, we will have 2 different columns, namely imageable_id and imageable_type.
The first thing that I am unclear of is, what exactly goes into imageable_type ? Is that something that the "rails magic" would automatically fill up when imageable_id is declared?
Moving on to my next point (which will probably indirectly answer my uncertainty above), how do I assign either a Product or Employee to my Picture.new form?
#create new picture form
#assume pre_created_array holds the :id for both Employee & Product
<%= form_for #picture do |f| %>
#relevant fields ontop
#choosing parent field is the one im unsure of
#this is what i assumed might be correct(?)
<%= f.select :imageable_id, options_for_select(pre_created_array) %>
<% end %>
Now does this form actually work? Is the building of the association something that has to be handled in the controller action instead? I am actually not very sure because usually in a regular association the parent can be declared before .save, such as doing #post.employee = #find an employee. So are we suppose to read the :imageable_id?
#pictures controller
def create
#picture = Picture.new(picture_params)
#manipulate :imageable_id here???
if #picture.save
#blahblah other code
end
So i am actually quite unsure about this, whether it is supposed to be the form or controller handling the building of association. Which is why i'm bringing up this 2 "uncertainties".
A polymorphic association is cool because it allows a single table to belong_to multiple, as you know. So given a picture, we don't have to know whether it belongs to an employee or a product, we can just call picture.imageable and get the parent.
So if we don't have to know where the parent is, that must means Rails has to know. How does it know? imageable_type! imageable_type is the name of the class which it belongs to. In this case, either 'Employee' or 'Product'. That way, given the imageable_id, it knows what table in which to search.
image.imageable actually calls image.imageable_type.constantize.find(image.imageable_id)
Rails will do this "magic" for you if you simply assign objects instead of IDs. image.update(imageable: Product.first) will assign both for you.
So in your form, you should be able work with a collection of objects and let Rails do the rest for you.

Syntax for getting attributes of entries created via accepts_nested_attributes_for

I have a User model that looks something like this:
class User < ActiveRecord::Base
has_many :events
has_many :event_sessions, through: :events
accepts_nested_attributes_for :events
end
I have a form that submits a User, Event, and EventSession to my UserController and everything works as expected.
Once my controller performs a #user.save. I want pull out the id of the Event it created.
What's the correct syntax there? It's not as if #user.event.id works.
#user.events.last.id
When you have a has_manyor has_and_belongs_to_many you are always dealing with a collection of associated models.
The controller would need to explicitly call event's user and be placed in the views that you want it displayed...as an example...i want to place it in show page for Events.
def show
#event = Event.find(params[:id])
end
View would be to get the id
<%= #event.user.id %>
Hope this helps...I believe this will help your problem. If not please advise

Many to Many relation issue in Rails 4

I am a rails beginner and encountered the following issue
Models are setup as follows (many to many relation):
class Activity < ActiveRecord::Base
belongs_to :user
has_many :joinings
has_many :attendees, through: :joinings
end
class Joining < ActiveRecord::Base
belongs_to :activity
belongs_to :attendee
end
class Attendee < ActiveRecord::Base
has_many :joinings
has_many :activities, through: :joinings
end
This is one page test application for some users posting some activities, and other users to join the activities.
It is organized as single page format (activities index), and after each activity, there is a "Join" button users can click.
I am stuck at the point when a user needs to join a specific activity.
in the index.html.erb (of the activities), with the Join button code.
This will point to the attendee controller, to Create method, but I got no information regarding the Activity that I want to follow (eg. activity_id, or id)
Without this I cannot use the many to many relation to create the attendee.
What would be the correct button code, or any other suggestion to to get the corresponding activity ID in the attendees controller?
I tried a lot of alternatives, including even session[current_activity] , but is pointing (of course) always to the last activity.
Thanks so much !
If you have existing activities, and existing attendees, and you want to change the relationship between them, then you are editing the join table records. Therefore, you should have a controller for these. Like i said in my comment i'd strongly recomnmend renaming "joining" to "AttendeeActivity" so your schema looks like this:
class Activity < ActiveRecord::Base
belongs_to :user
has_many :attendee_activities
has_many :attendees, through: :attendee_activities
end
class AttendeeActivity < ActiveRecord::Base
belongs_to :activity
belongs_to :attendee
end
class Attendee < ActiveRecord::Base
has_many :attendee_activities
has_many :activities, through: :attendee_activities
end
Now, make an AttendeeActivitiesController, with the standard scaffoldy create/update/destroy methods.
Now, when you want to add an attendee to an activity, you're just creating an AttendeeActivity record. if you want to remove an attendee from an activity, you're destroying an AttendeeActivity record. Super simple.
EDIT
If you want to create an Attendee, and add them to an activity at the same time, then add a hidden field to the form triggered by the button:
<%= hidden_field_tag "attendee[activity_ids][]", activity.id %>
This will effectively call, when creating the attendee,
#attendee.activity_ids = [123]
thus adding them to activity 123 for example.
You have several options here. I'm assuming that the Join button will simply submit a hidden form to the attendees controller's create action. So the simplest solution would be to include the activity_id as a hidden form tag that gets submitted along with the rest of the form. This activity_id will be available in the params hash in the controller.
The other option is to setup Nested routing so that the activity_id is exposed via the path.
Thanks for all the details. I will change the naming of the join table for the future.
My problem was that I could not find the specific activity for attendee create method. Finally I found something like this for the JOIN button:
<%= button_to 'Join', attendees_path(:id => activity) %>
This will store the Activity ID, so I am able to find it in the Attendees controller:
def create
activity = Activity.find(params[:id])
#attendee = activity.attendees.create user_id: current_user.id
redirect_to activities_path
end
this updates also the Joinings (AttendeeActivity) table.
I will study about the hidden_field_tag solution, as is not clear to me yet.

Display different field from model based on ID

I know this is trivial stuff, but I am banging my head a bit here. You guys are always much more helpful.
I have two models: Contact and Group. Group has_many contacts and Contact belongs_to group.
Therefore Contact has a group_id field.
In my "show" view for a Contact, I have: <%= #contact.group_id %>
This shows "1". Let's say "Sales" = group_id 1.
Now, the Group model has the default id field, and a group field, which contains the word "Sales", associated with id 1.
All I want to do is on my "show" page, display "Sales" instead of 1.
I'd imagine I need to create a variable within my "show" action in the ContactsController. I am just not sure what to put there?
Thanks.
Create association between contact and sales
class Contact < ActiveRecord::Base
belongs_to :group
end
class Group < ActiveRecord::Base
has_many :contacts
end
And in your view
<%= #contact.group.name %>
You can also get all the contacts of a particular group like
group.contacts
<%= #contact.group.name %>
you can access related models from each other just like this:
<model>.<related_model>
and then go on to ask for any attributes from the related model

Add variable number of items of one type when creating item of another type

I want to create a form that lets you create an item of type A. In that form, you can add multiple items of type B to be associated to the item of type A that you are creating.
I think I understand how to do this in the models- just have a has_many and belongs to relationship.
I'm not really sure how to do this in the UI. Right, now I have the scaffolding and it only has fields for attributes of the item I'm creating. Is there a way to have it show fields for adding items of types defined in has_many that we see in the model file?
EDIT
ClassA
has_many :ClassB
ClassB
belongs_to :ClassA
Let's assume your Item A is a Person and Item B is a Project. So, for what you said, a Person has_many Projects. (I decided to use "real world" resources, instead of Item A and Item B for the clarify of the example).
Here is how you would define your models associations:
class Person < ActiveRecord::Base
has_many :projects
accepts_nested_attributes_for :projects
end
class Project < ActiveRecord::Base
belongs_to :person
end
Then, the form of your Person would look like this:
<%= form_for #person do |person_form| %>
...
<%= person_form.fields_for :projects do |project_builder| %>
# Here goes the fields of the projects
<%= project_builder.text_field :name %>
<% end %>
...
<% end %>
The key here is fields_for method, which will let you put into your Person form, form builders for the Projects associated with that Person.
It is important to know that if you are creating a new Person, there are obviously no Projects associated, and therefore the fields_for part would be empty. You might want to start by just basically doing this in the #new action:
def new
#person = Person.new
5.times { #person.projects.build }
end
Later, and once you get the feeling you know what's going on, you might want to add some buttons in the front end side that would let you "dynamically" add new Projects.

Resources