How to load parent-child-parent associations in Rails 4? - activerecord

this is my first question on StackOverflow :)
I'm building a Rails 4 app, having trouble to figure out a good way to load records from mutilple data models. I could hard code SQL statements like an inner join, but wondering if there's any better way. Searched in existing questions on SO, but didn't find a match.
Here are my models:
class Person < ActiveRecord::Base
has_many :addresses
end
class Address < ActiveRecord::Base
belongs_to :person
belongs_to :city
end
class City < ActiveRecord::Base
has_many :addresses
end
Question: given a person Id, how should I load its associated addresses with the city information?

Address.includes(:persons,:cities).where(person_id: person.id)
this is one of many ways.

Related

Rails association, I want something but the other model shouldn't care

So I think I need help with what I am doing with my asscoiations. I have two models (well many but for the purposes here). One is a Provider. Each provider can have a designation. Though the Designations is just a list it can appear in many different providers so it is not one to one. My models are as follows:
Provider.rb
class Provider < ActiveRecord::Base
has_and_belongs_to_many :groups
has_one :designation
has_one :specialty
end
Designation.rb
class Designation < ActiveRecord::Base
end
The error I get is this:
SQLite3::SQLException: no such column: designations.provider_id: SELECT "designations".* FROM "designations" WHERE "designations"."provider_id" = ? LIMIT 1
Which tells me my associations are off cause the designations should not have the provider_id, if anything the provider should have the designation_id.
Do I ditch the has_one and just put has_many in the Designation?
If I do that, I am new to rails, do I have to create a migration so the database is correctly updated?
Try using
models/provider.rb
belongs_to :designation
Then in
models/designation.rb
has_many :providers
It may feel a little strange but the belongs_to just lets you know which model the id column needs to go in. In this case the provider model, so you'll need:
rails g migration add_designation_id_to_provider designation_id:integer

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 records with x number of classifications

I'm trying to figure out how to write an ActiveRecord method that will return all Boats with more than three classifications.
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 BoatClassifications < ActiveRecord::Base
belongs_to :boat
belongs_to :classification
end
In general, I'm having trouble finding resources for writing queries on join models in AR. If anyone knows any good resources to help learn complex AR queries, that would be really helpful.
Fist JOIN the boats with the classifications. Then you need to GROUP BY boats.id so then you can COUNT how many rows you have grouped for every different boat. Using the HAVING allows you to apply that condition over the grouped records. At the end, selects the boats as you want.
Boat.joins(:classifications).group("boats.id").having("COUNT(*) > 3").select("boats.*")

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

Ruby on Rails: Associations when a user likes a song

I'm trying to figure out the best way to setup my database and models for the following scenario.
A user can like an infinite number of songs.
A song can be liked once by an infinite number of users.
I have these tables:
songs, users, likes etc... Following RoR conventions.
The table named likes has these foreign keys: user_id, song_id. And also a field named 'time' to save a timestamp when the song was liked.
I'm not sure of how to do this, I would like to be able to use code like this in my controllers:
User.find(1).likes.all
This should not return from the likes table, but join the songs table and output all the songs that the user likes.
What are the best practises to achieve this in Ruby on Rails following their conventions?
Unless you need to act specifically on the likes table data, the model itself is probably not necessary. The relationship is easy:
class User < ActiveRecord::Base
has_and_belongs_to_many :songs
end
class Song < ActiveRecord::Base
has_and_belongs_to_many :users
end
This will join through the currently non-existent song_users table. But since you want it to join through likes you can change each one to this:
has_and_belongs_to_many :songs, :join_table => 'likes'
If you want to be able to call User.find(1).likes and get songs, then change the user's version to this:
class User < ActiveRecord::Base
has_and_belongs_to_many :likes, :join_table => 'likes', :class_name => 'Song'
end
And you could change the songs version to something like this:
class Song < ActiveRecord::Base
has_and_belongs_to_many :liked_by, :join_table => 'likes', :class_name => 'User'
end
This will give you Song.find(1).liked_by.all and give you the users (You could keep it to users if you wanted using the first version)
More details on habtm relationships can be found here: http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many
Edit to add
If you want to act on the join table for whatever reason (you find yourself needing methods specifically on the join), you can include the model by doing it this way:
class User < ActiveRecord::Base
has_many :songs, :through => :likes
has_many :likes
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :song
end
class Song < ActiveRecord::Base
has_many :users, :through => :likes
has_many :likes
end
This will let you do User.find(1).songs.all, but User.find(1).likes.all will give you the join data

Resources