SQL - Rails Deep nested joins - sql

First of all, I'm French, so sorry for my ugly english.
I have following models :
Shop
has_and_belongs_to_many :products
Product
has_and_belongs_to_many :shops
has_many :taggings
has_many :tags, through: :taggings
Tagging
belongs_to :tag
belongs_to :product
Tag
has_many :taggings
has_many :products, through: :taggings
I want to be able to do Shop.first.tags, so I want to get all shop's products' tags, in a single request if it's possible. If I could have explanations with, it will be fine :)

You have not specified a relationship for tags on your Shop model. You'll need to add that relationship in order to call #tags on a single object.
class Shop
# ...
has_many :tags, :through => :products
# ...
end

Related

Rails - Using multple has_many through: associations joining same two models. Redundant has_many through:

Would association person and company through employment AND through interviewing be bad practice?
Why, specifically?
And does that answer apply to databases in general, not just rails?
Example:
employment.rb
class Employment < ActiveRecord::Base
belongs_to :people
belongs_to :companies
end
interview.rb
class Interview < ActiveRecord::Base
belongs_to :people
belongs_to :companies
end
person.rb
class Person < ActiveRecord::Base
has_many :employments
has_many :interviews
has_many :companies, through: :employments
has_many :companies, through: :interviews
end
company.rb
class Company < ActiveRecord::Base
has_many :employments
has_many :interviews
has_many :companies, through: :employments
has_many :companies, through: :interviews
end
Person and Company are associated through Employment, but also redundantly through Interview.
There's nothing wrong with having two models having multiple associations, including multiple associations of the same type. You will want to give the associations unique names, though - otherwise when you called (for instance) #person.companies, you wouldn't know what you were going to get - companies through employments, or companies through interviews.
I believe this question has a decent example: ruby on rails has_many :through association which has two columns with same model

Rails: NameError: uninitialized constant on join table

I can't seem to work around the name convention or if I'm joining them incorrectly.
This is the error I'm getting from the user model:
> user.companies
NameError: uninitialized constant User::CompaniesUser
And from the company model:
> company.users
NameError: uninitialized constant Company::CompaniesUser
user.rb
has_many :companies_users
has_many :companies, :through => :companies_users
company.rb
has_many :companies_users
has_many :users, :through => :companies_users
company_user.rb
class CompanyUser < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
I've been looking up through examples but I honestly don't understand why it keeps exploding. If there's any additional information needed, I'll provide it, I appreciate any help given.
Your association companies_users will be mapped to class named CompaniesUser by Rails because "companies_users".classify will give you CompaniesUser. But the class you want to associate is CompanyUser, so the solution in this case would be to modify your associations to include class_name option as follows:
# user.rb
has_many :companies_users, class_name: CompanyUser
has_many :companies, :through => :companies_users
# company.rb
has_many :companies_users, class_name: CompanyUser
has_many :users, :through => :companies_users
Update: This is of course if you want to stick with the association name companies_users, otherwise #Babur has a solution for you.
It should be:
has_many :company_users
has_many :companies, :through => :company_users
Only last word should be pluralized
Because of your has_many :companies_users in your Company model, Rails tried to load a model class for that table, that be convention would be called CompaniesUser. To make your code work, you could either change your has_many declaration to
has_many :company_users
or even get rid of the CompanyUser model completely and use has_and_belongs_to_many instead.
class User
has_and_belongs_to_many :companies
end
class Company
has_and_belongs_to_many :users
end

Extra fields for join tables

I am building an Web app using Rails 3.2.
I have three tables. Item, Task and Articles.
TASK
has_many :articles
has_many :items, :through => :articles
ITEM
has_many :articles
has_many :tasks, :through => :articles
ARTICLE
belongs_to :task
belongs_to :item
In the join table (Article) I got an extra field called amount.
How can I set this field when creating the relationship?
Right now I do it like this but it does not feel "right".
Article.create(item_id: self.item_id, task_id: self.id, amount: self.item_amount)

Is a has_many :through relationship the right way to model this data?

I have a Client model that needs each client instance to own and create multiple addresses, email_ids, phone_numbers. A simple has_many relationship would not allow me to scale I presume so I thought I should go for a has_many :through relationship
I want to use a has_many :through relationship
class Client < ActiveRecord::Base
has_one :profile
has_many :addresses, :through => :profile
has_many :emails, :through => :profile
has_many :phonenumbers, :through => :profile
end
class Profile < ActiveRecord::Base
belongs_to :client
has_many :addresses
has_many :emailids
has_many :phonenumbers
end
class Address < ActiveRecord::Base
belongs_to :profile
end
class EmailId < ActiveRecord::Base
belongs_to :profile
end
class PhoneNumber < ActiveRecord::Base
belongs_to :profile
end
Will I then be able to execute queries like:
client.phonenumbers client.create_phonenumbers etc?
Or should I just stick to has_many belongs_to and put address, email_id and phone_number in the profile relationship and then say client has_many profiles? That doesn't sound right to me. Are there any benefits to the rich association that I have outlined above?
I think it seems to be fine stick with the has_many :through. Because we don't need to put an extra relationship between client and other tables i.e addresses etc and also an extra column client_id in those tables. only putting profile id will do the same.

rails - what is the best/most efficient way to associate these models

In my application I have the following situation:
User belongs_to Group
Group has_many Users
Project belongs_to User
User has_many projects
The following is also true:
- Each Group will have one BaseCase
- Each Project will have multiple Scenarios and one BaseCase(depending on the Group the Project User belongs to)
- Scenario and BaseCase is the same type of object (let's call this Data)
- The default values for each Scenario are the BaseCase values for the Group, but the User can change these default values to create the specific Scenario
I am not sure how to capture all these relationships through associations efficiently, does anyone have any ideas? thanks
If I understand correctly, then something like that
class User
belongs_to :group
has_many :projects
end
class Group
has_many :users
has_many :projects, :through => :users
has_one :base_case
end
class Project
has_many :scenarios
has_one :base_case
belongs_to :user
has_one :group, :through => user
has_one :base_case, :through => :group
end
class Scenario
belongs_to :project
has_one :base_case, :through => :project
before_create do
self.attributes = self.base_case.attributes.except(:group_id, ...)
end
end
class BaseCase
belongs_to :group
end