Query an ActiveRecord on several tables? - ruby

Sorry to ask this question but I'm really newbie with Ruby and I need help to update several records on my database.
I'm using ActiveRecord to query the database. Let say I have a table Product that contains SubProduct that also contains SubSubProduct. Now I would like to write a simple query to get all SubSubProduct of Product.
To get a list of SubSubProduct I usually do this
ssp = SubSubProduct.where(sub_sub_type: "example")
Now to use a where clause on relational element how can I do
ssp = SubSubProduct.where(sub_sub_type: "example", SubProduct.Product.type: "sample")

Set up ActiveRecord associations in your models:
#app/models/product.rb:
class Product < ActiveRecord::Base
has_many :sub_products
end
#app/models/sub_product.rb:
class SubProduct < ActiveRecord::Base
belongs_to :product
end
#app/models/sub_sub_product.rb:
class SubSubProduct < ActiveRecord::Base
belongs_to :sub_product
end
What you wanted:
ssp = SubSubProduct.where(sub_sub_type: "example", SubProduct.Product.my_type: "sample")
The correct syntax:
ssp = SubSubProduct.includes(sub_product: :product).where(sub_sub_type:"example", products: {my_type: "toto"})

This is performed via associations.
class SubSubProduct
has_many :products
end
Then you can do things like
sub_product.products
and it will product all the products associated with them.

Try a nested includes:
`Product.includes(subproducts: :subsubproducts)'

For this, you'll want to set up ActiveRecord associations in your models:
In product.rb:
class Product < ActiveRecord::Base
has_many :sub_products
has_many :sub_sub_products, through: :sub_products
end
In sub_product.rb:
class SubProduct < ActiveRecord::Base
belongs_to :product
has_many :sub_sub_products
end
In sub_sub_product.rb:
class SubSubProduct < ActiveRecord::Base
belongs_to :sub_product
end
Then, if you have a Product and want its SubSubProducts, you can use:
# p is a Product object
p.sub_sub_products

Related

Mix Polymorphic associations with STI or MTI in Ruby on Rails

I have a problem or dilemma after implementing polymorphic association following this: All the code is located here,
I have implemented this model:
Let's suppose that I also need the subscription to magazines. It will also be something similar to the other two
class Magazines < ApplicationRecord
has_many :subscriptions, as: :subscribable
end
class User < ApplicationRecord
has_many :subscriptions
has_many :podcasts, through: :subscriptions, source: :subscribable, source_type: 'Podcast'
has_many :newspapers, through: :subscriptions, source: :subscribable, source_type: 'Newspaper'
has_many :magazines, through: :subscriptions, source: :subscribable, source_type: 'Newspaper'
end
class Subscription < ApplicationRecord
belongs_to :subscribable, polymorphic: true
belongs_to :user
end
It works well, the problem now is ok I can handle like three types of subscription
MagazineSubscription, PodcastSubscription and NewspaperSubscription. The three have the same attributes and same behaviour, but belongs to different model. What happens If after doing that I need some kind of MTI or STI with the subscription classes. i.e. the MagazineSubscription have different behaviour and maybe other attributes. There is an easy way on this to accomplish this new requirement like creating a Subscription class that handles all that the polymorphic association and the other models:
class Subscription < ActiveRecord::Base
self.inheritance_column = :sti_subscription
belongs_to :subscribable, polymorphic: true
belongs_to :user
def _type=(sType)
sti_subscrition = sType.to_s.classify.constantize.base_class.to_s + "Subscription"
super(sType.to_s.classify.constantize.base_class.to_s)
end
end
class MagazineSubscription < Subscription
# new behaviour here
end
or I must follow something similar to this with the Subscription class handling two polymorphic relations, with the subscribable and his descendants
So my question is when I have used polymorphic association is an easy way to use that to set STI or MTI, or I need to make a new approach

Rails polymorphic aliased associations

I would like to try set up this association:
# app/models/course.rb
class Course < ActiveRecord::Base
belongs_to :subjectable, polymorphic: true
end
# app/models/student.rb
class Student < ActiveRecord::Base
has_many :courses, as: :subjectable
end
# app/models/campus.rb
class Campus < ActiveRecord::Base
has_many :courses, as: :subjectable
end
But this did not read very well in the code.
#this seems fine
campus = Campus.last
campus.courses
#this dosent make much sense gramatically
student = Student.last
student.courses
Campuses offer Courses, but Students don't have courses they have subjects. Now they are the same thing under the covers they just don't read well.
How could I get it so that student.subejects would yield the same result as student.courses?
You can name the association as you want, you don't have to mach the associated class.
In this case, you have to tell ActiveRecord what the pointed class is :
# app/models/student.rb
class Student < ActiveRecord::Base
has_many :subjects, as: :subjectable, class_name: 'Course'
end

Activerecord checking if association exist

I have two ActiveRecord models:
class Class < ActiveRecord::Base
(...)
has_many :class_to_teacher, dependent: :destroy
end
class Teacher < ActiveRecord::Base
has_many :classes,
through: :class_to_teacher
end
class ClassToTeacher < ActiveRecord::Base
belongs_to :klass
belongs_to :teacher
end
When I remove Class I don't remove it completly only I remove record from ClassToTeacher record. I need to keep this data:
def leave(class, teacher)
teacher.klasses.delete(class)
end
Now I have to get all associated classes (classes which contains record in ClassToTeacher). How to do this the best? Thanks for all answers.
You should try something like that:
Class.includes(:class_to_teacher).where('class_to_teacher.id is not null').references(:class_to_teacher).all
Assuming that you have an 'id' field in your database for the ClassToTeacher
I guess there's a lot of ways to get there but the simplest one is probably this:
Klass.where(id: KlassToTeacher.select(:klass_id))
This will result in a single query with a sub-query. Note that I changed the names of the models because Class is already defined in Ruby and you're just asking for trouble.

ActiveRecord - Finding all objects with shared attributes in a join model

I have three models
class Boat < ActiveRecord::Base
belongs_to :captain
has_many :boat_classifications
has_many :classifications, through: :boat_classifications
end
class Classification < ActiveRecord::Base
has_many :boat_classifications
has_many :boats, through: :boat_classifications
end
class BoatClassification < ActiveRecord::Base
belongs_to :boat
belongs_to :classification
end
I'm trying to write a simple ActiveRecord query to find all the boats of type sailboat. Something like Boat.where(classifications: "Sailboat")
I think this could work:
Boat.joins(:classifications).where(classifications: { name: 'Sailboat' }) # name or whatever field contains Sailboat
Generates this query:
SELECT `boats`.* FROM `boats` INNER JOIN `boat_classifications` ON `boat_classifications`.`boat_id` = `boats`.`id` INNER JOIN `classifications` ON `classifications`.`id` = `boat_classifications`.`classification_id` WHERE `classification`.`name` = 'Sailboat'
I think you want something like this:
Boat.includes(:classifications).where(classifications: {id: Classification.sailboats})
For this to work, you also need a scope on Classification like this:
def self.sailboats
where(name: "Sailboat")
end

Ruby on Rails 3: How can I sort ActiveRecords by an attribute of another table?

I need to query a database table and get the rows ordered by a count of an association. Is there a Rails (like Active Record Query) way to do this?
My models and their associations are as follows:
class User < ActiveRecord::Base
has_one :business
end
class Business < ActiveRecord::Base
has_many :postulations
end
class Postulation < ActiveRecord::Base
belongs_to :business
end
I need to get a number of Users ordered by the amount of Postulations that their Business has. Is there a clean way to do this or do I just have to query with find_by_sql?
Thank you.
User.includes(:business => :postulations).group("users.id").order("count(postulations.id) desc").limit(20)
This will probably work

Resources