-
-
Save stevenharman/1440721 to your computer and use it in GitHub Desktop.
| # This is a record, as in a vinyl. | |
| class Record < ActiveRecord::Base | |
| belongs_to :user | |
| belongs_to :album | |
| end | |
| class Album < ActiveRecord::Base | |
| has_many :records | |
| belongs_to :artist | |
| end | |
| class User < ActiveRecord::Base | |
| has_many :records | |
| end | |
| class Artist < ActiveRecord::Base | |
| has_many :albums | |
| end | |
| # I want to query for a certain Album and also pull back any specific instances of | |
| # that album owned by a given User. However, if the user doesn't own any instances | |
| # of the Album, I still want the Album. Is that doable? | |
| # Example, find Album #42 and include any records owned by user #99. | |
| Album.include(:records).where('records.user_id' => 99).find(42) | |
| # this causes RecordNotFound if user 99 does NOT have any records for Album 42. |
@subdigital Actually, I believe you have that backwards. see: http://guides.rubyonrails.org/active_record_querying.html#specifying-conditions-on-eager-loaded-associations
Perhaps I should just bite the bullet and do it in two calls?
a = Album.find(42)
a_records = a.records.where('user_id' => 99)Yeah you're right. I had it backwards :).
I see what you're trying to do now. I think 2 queries is ok in this case. It's probably possible to do it in 1 though.
I believe find is not supposed to be mixed with the other query methods. It's single purpose, for getting 1 record.
What about this:
Album.include(:records).where('records.user_id = ? or records.user_id is null", 99).where(:id => 42).first definitely a shot in the dark.
I was thinking the same thing, but it also results in an empty array. Also, I think I prefer using two queries, and sticking with the AR ARI, as it is more expressive and intention revealing.
Also, all of this is wrapped inside other objects - I treat the AR API as a private to the AR Models. For example
class Library
def initialize(user, fetch_albums=Album)
@owner = user
@fetch_albums = fetch_albums
end
def albums
fetch_albums.for_owner(owner)
end
def fetch_records_for_album(album)
owner.fetch_records_for_album(album)
end
private
attr_reader :owner, :fetch_albums
end
class Album < ActiveRecord::Base
has_many :records
belongs_to :artist
#...
def self.for_owner(owner)
includes(:records).where(user_id: owner)
end
end
class User < ActiveRecord::Base
has_many :records
#...
def fetch_records_for_album(album)
records.where(album_id: album)
end
end
I believe what you want is this:
includedoes an INNER JOIN, whereas you want a LEFT JOIN.