Display different field from model based on ID - ruby-on-rails

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

Related

Ruby on Rails, User Models and Active Admin query

I am using Active Admin in my application.
The application has a Users model (Devise) but I have 3 user groups - parents, teachers and students. Each has their own model.
e.g
student.rb
belongs_to :user
user.rb
has_one :student
parent.rb
belongs_to :user
user.rb
has_one :parent
What I am trying to do here is store the attributes that would be the same across the user groups in the Users model so "first_name, last_name, email" etc and then using the individual user models to store attributes that are unique to each user group. I am using a one to one relationship between the main users table and the three user group tables.
Here (note I have not displayed all attributes in the user group tables):
The problem is this is not working out so well with Active Admin. In the view I have to create a user and then assign a parent and a student in different views. I would like to have a single form where, for example, a student's user record can be put in with the attributes from the main Users table as well as their unique attributes in the students table without having to go to multiple model views to complete records. It's too convoluted.
Is there a way to render the inputs from different models in the one view? i.e in students have "first name", "last name"...from the Users table along with the inputs unique to a student?
If you were taking the approach I am taking here what method would you follow? I'm not even sure I am doing the associations right. In fact i'm not even sure this is the most efficient way to do this.
I am using enums to assign the roles.
Would appreciate any guidance here. Thanks.
Students, Guardians, and Teachers are all a type of User. Why not consolidate them into a single type and use inheritance to represent them as a common type?
class User < ActiveRecord::Base
# ...
end
class Teacher < User
# ...
end
class Guardian < User
# ...
end
class Student < User
# ...
end
You'll need to add a type column via a migration, and also write a task to merge them into a common table, but it will likely be worth the effort.
See STI in Rails: http://api.rubyonrails.org/classes/ActiveRecord/Inheritance.html.
EDIT:
If you don't want to go the STI route, you'll have to use nested attributes
class User < ActiveRecord::Base
accepts_nested_attributes_for :teacher
accepts_nested_attributes_for :guardian
accepts_nested_attributes_for :student
end
Then add a custom form in admin/user.rb ():
ActiveAdmin.register User do
form do |f|
f.inputs "User Inputs" do
# ...
f.input :email
# ...
end
f.inputs "Guardian Attributes", for: [:guardian, f.object.guardian || Guardian.new] do |g|
g.input :mobile_no
end
# Repeat for teacher, Student, etc...
end
end
If you're using strong parameters, make sure you whitelist the appropriate params for User, guardian_attributes, etc.
In my opinion, the nesting here is pretty ugly and having this normalized schema is going to be difficult to maintain and query.

Setting a relationship between Users to access a resource

I'm teaching myself Rails and I'm trying to setup a collaboration relationship kind of like Github adds collaborators to projects. My models look like this:
class Restaurant < ActiveRecord::Base
has_many :employees
has_many :users, through: :employees
end
class User < ActiveRecord::Base
has_many :employees
has_many :restaurants, through: :employees
end
class Employee < ActiveRecord::Base
belongs_to :restaurant
belongs_to :user
end
The employee table also has a user_type column to handle permissions within the project (restaurant). I can't figure out how to make my employee_controller set this relationship. Users primary key is :email so I'm guessing a form should be able to receive the :email parameter, check if such a user with the inputed email exists, and add the relationship to the employees table.
I'm looking to be able to do something like this:
Restaurant_A = Restaurant.create(restaurant_params)
User_A.restaurants = Restaurant_A
Restaurant_A.employees = User_B
I think my models might be wrong but essentially I'd like to be able to have users with the ability to create a restaurant as well as be added as employees of another restaurant/their own restaurants.
Your model is all right - no problem with that.
What you are trying to accomplish, you can accomplish that by following:
restaurant_a = Restaurant.create(restaurant_params)
# Remember to name it 'restaurant_a', it is convention in Ruby
user_a.restaurants << restaurant_a
<< is an operator that inserts left hand side thing into its right hand thing. So in our case, it will insert restaurant_a into the list of restaurants that are associated with user_a, and then you call save operation on your user_a like user_a.save.
Same case is on the other side:
restaurant_a.employees << user_b
# According to Ruby convention, you shouldn't start your variable
# name with an upper case letter, and you should user a convention
# called 'snake_type' naming convention. So instead of naming
# your variable like 'firstDifferentUser', name it 'first_different_user'
# instead.
restaurant_a.save # To successfully save the record in db
Edit:
For creating a form:
<%= form_for(#restaurant, #employee) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<% end %>
And you need to define #restaurant and #employee in your employee's controller new action, because you are gonna create a new employee for a particular restaurant.

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.

Get value from other model without any association

I have 3 models and tables Products, Customers, Buyers and there are has_and_belongs_to_many relationship among them. And I have another model and table sells. I need to get value from all of the above 3 tables in sells/new page. Do I have to use any association among them? How can I get the values?
I want product_id, product_name, customer_id, customer_name in views/sells/new.html.erb file I don't understand how can I get that
First of all it should be sales table and the Sale model. But anyway, from the view (or helper), you can do:
Product.all # gives you all products
# or fetch just the columns you want:
Product.select( [:id, :name] )
Same goes for customers (i.e. Customer.all etc.).
It's not an orthodox way to do it but it will work. With Erb you'll need <% ... %> or <%= ... %> of course.
Add user_id and product_id to sells table
Class User
has_many :sells
end
Class Product
has_many :sells
end
Class Sells
belongs_to :user
belongs_to :user
end
Then do on sell show page
sell.user_id
sell.user.name
sell.product_id
sell.product.name
Hope this is what you need or least give an idea :)

Selecting belongs_to parents in a form?

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 %>

Resources