Polymorphic Relationships - Retrieving the owner - ruby-on-rails

I have a polymorphic relationship setup as follows:
class Industry < ActiveRecord::Base
attr_accessible :name
has_many :user_industries
end
class UserIndustry < ActiveRecord::Base
attr_accessible :industry_id, :industriable_id, :industriable_type
belongs_to :industry
belongs_to :industriable, polymorphic: true
end
class Applicant < ActiveRecord::Base
has_many :user_industries, as: :industriable
end
class Employer < ActiveRecord::Base
has_many :user_industries, as: :industriable
end
I have a search feature and I'd like to fetch, for example, all Applicants that have a certain Industry. Does Rails provide a convenient way to do this, or do I have to write some methods myself?

from the comment that you wrote i assume, that you want to write a join query like this (untested):
Applicant.joins(:user_industries).where('user_industries.industry_id' => self.id).pluck('applicants.id')

Related

how to connect two table that has no relation in rails

I have a table called foods and categories, but this table has no relation, I want to connect them through another table called food_category. And I want to make one-to-one relation between food and category maybe the diagram looks like this
class Food < ApplicationRecord
has_one :category
end
class Category < ApplicationRecord
has_one :food
end
class FoodCategory < ApplicationRecord
belongs_to :category
belongs_to :food
end
Is it possible to do this?
Yes, this is possible. You just need to do
has_one :category, through: :food_categories
as discussed in the Rails docs here.
However, this is a long-winded way to go about this kind of association. If it's going to be one-to-one, why not just add a foreign key to Category from Food? And presumably, you would actually want Category to contain many Food records? Seems like the below would make more sense:
class Food < ApplicationRecord
belongs_to :category
end
class Category < ApplicationRecord
has_many :food
end
class Food < ApplicationRecord
has_one :food_category
has_one :category, through: :food_categories
end
In rails console, you can access like this
Food.find(:id).categories

Rails 4, Active Record, create order scope on belongs_to for has_many_through

I have the following models set up:
class Location < ActiveRecord::Base
has_many :location_parking_locations
has_many :parking_locations, through: :location_parking_locations
end
class LocationParkingLocation < ActiveRecord::Base
belongs_to :location
belongs_to :parking_location
end
class ParkingLocation < ActiveRecord::Base
has_many :location_parking_locations
has_many :locations, through: :location_parking_locations
end
The LocationParkingLocation has an integer field called upvotes. I would like to create a 'by_votes' scope that I can add to a query to order the results by this upvotes field. Where and how do I define this scope, so that I can call it like this:
location.parking_locations.by_votes
I can't define it like this, because then it's not a valid method on parking_locations:
class LocationParkingLocation < ActiveRecord::Base
belongs_to :location
belongs_to :parking_location
scope :by_votes, -> { order("upvotes DESC") }
end
Should it be defined in the 'ParkingLocation' class? If so, how do I tell it that I want to order by a field on the location_parking_locations table?
I think you might be able to use merge here.
You can leave your scope in the LocationParkingLocation class, and the result would look like:
location.parking_locations.merge(LocationParkingLocation.by_votes)
I just read a little about it in this blog post.

Associations two-many-to-many

I don't fully understand how associations work.
I have 3 models:
Movie (:about, :title, :url, :actors, :uploader)
Actor (:birth, :name)
Relationships (:actor_id, :film_id)
Relationships is the association between Movies and Actors, so "which actor play in which movie". My teacher told me I can make it easier with http://railscasts.com/episodes/47-two-many-to-many but I don't know how to use that, any idea?
I would imagine you want something like:
class Movie < ActiveRecord::Base
has_many :actors, :through => :relationships
end
class Relationship < ActiveRecord::Base
belongs_to :movie
belongs_to :actor
end
class Actor < ActiveRecord::Base
has_many :movies, :through => :relationships
end
http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association
Or alternatively, if you don't feel you have to define the relationship class explicitly, you can simply use has_and_belongs_to_many:
class Movie < ActiveRecord::Base
has_and_belongs_to_many :actors
end
class Actor < ActiveRecord::Base
has_and_belongs_to_many :movies
end

has_many relationship rails 3

Hi I have three tables like the following:
class Workitem < ActiveRecord::Base
has_many :effort
attr_protected
end
class Effort < ActiveRecord::Base
attr_protected
belongs_to :workitem
belongs_to :person
end
class Person < ActiveRecord::Base
attr_accessible :given_name, :mgrid, :surname, :id
has_many :effort
end
The idea is to keep track of how many days a person has spent on a particular work item through efforts table. Could somebody verify if my relationships are correct? But this doesn't seem to work. Am I missing something here?
Also, I can't understand the has_many :through kind of associations. Can somebody please give me an idea if that is what I'm supposed to use in this case?
You would usually have the child as a plural object:
class Workitem < ActiveRecord::Base
has_many :efforts
attr_protected
end
class Person < ActiveRecord::Base
attr_accessible :given_name, :mgrid, :surname, :id
has_many :efforts
end
And I'd recommend using attr_accessible instead of attr_protected
If a Foo had many Bars and the Bars belonged to many Foos, it might look like this:
class Foo < ActiveRecord::Base
has_many :foo_bar
has_many :bars, through => :foo_bar
end
class Bar < ActiveRecord::Base
has_many :foo_bar
has_many :foos, through => :foo_bar
end
class FooBar
belongs_to :foo
belongs_to :bar
end
Something like that anyway. There's a load of help on Railcasts here
Also, there's a trillion examples on SO.
Hope that helps

Can a 3-way relationship be modeled this way in Rails?

A User can have many roles, but only one role per Brand.
Class User < AR::Base
has_and_belongs_to_many :roles, :join_table => "user_brand_roles"
has_and_belongs_to_many :brands, :join_table => "user_brand_roles"
end
The problem with this setup is, how do I check the brand and the role at the same time?
Or would I better off with a BrandRole model where different roles can be set up for each Brand, and then be able to assign a user to a BrandRole?
Class User < AR::Base
has_many :user_brand_roles
has_many :brand_roles, :through => :user_brand_roles
end
Class BrandRole < AR::Base
belongs_to :brand
belongs_to :role
end
Class UserBrandRole < AR::Base
belongs_to :brand_role
belongs_to :user
end
This way I could do a find on the brand for the user:
br = current_user.brand_roles.where(:brand_id => #brand.id).includes(:brand_role)
if br.blank? or br.role != ADMIN
# reject access, redirect
end
This is a new application and I'm trying to learn from past mistakes and stick to the Rails Way. Am I making any bad assumptions or design decisions here?
Assuming Roles,Brands are reference tables. You can have a single association table Responsibilities with columns user_id, role_id, brand_id.
Then you can define
Class User < AR::Base
has_many : responsibilities
has_many :roles, :through => responsibilities
has_many :brands,:through => responsibilities
end
Class Responsibility < AR::Base
belongs_to :user
has_one :role
has_one :brand
end
The you can define
Class User < AR::Base
def has_access?(brand)
responsibility = responsibilities.where(:brand => brand)
responsibility and responsibility.role == ADMIN
end
end
[Not sure if Responsibility is the term used in your domain, but use a domain term instead of calling it as user_brand_role]
This is a conceptual thing. If BrandRole is an entity for your application, then your approach should work. If BrandRole is not an entity by itself in your app, then maybe you can create a UserBrandRole model:
class User < AR::Base
has_many :user_brand_roles
end
class Brand < AR::Base
has_many :user_brand_roles
end
class Role < AR::Base
has_many :user_brand_roles
end
class UserBrandRole < AR::Base
belongs_to :user
belongs_to :brand
belongs_to :role
validates_uniqueness_of :role_id, :scope => [:user_id, :brand_id]
end

Resources