Reputation: 1714
So I have the following simplified models and associations:
class Barber < User
has_many :barber_styles, inverse_of: :barber
end
class Style < ActiveRecord::Base
end
class BarberStyle < ActiveRecord::Base
belongs_to :barber, inverse_of: :barber_styles
belongs_to :style
delegate :name, to: :style
end
If I wanted to make a query based on all BarberStyle
's that belong to a specific Barber
, is there a way I can include the name of the associated Style
?
I want to use a line something like:
BarberStyle.joins(:barber).where(barber: 109).include(:style)
So I'd be able to access an associated style.name
. But I don't think a line like this exists.
I know I could just use map
to build an array of my own objects, but I have to use a similar query with many different models, and don't want to do a bunch of extra work if it's not necessary.
In one of my previous projects, I was able to render json with the following lines:
@colleges = College.includes(:sports).where(sports: { gender: "male" })
render json: @colleges, include: :sports
But I don't want to render json in this case.
Edit:
I don't really have any unincluded associations to show, but I'll try to elaborate further.
All I'm trying to do is have extra associated models/fields aggregated to each BarberStyle
result within my ActiveRecord Relation query.
In an attempt to make this less confusing, here is an example of the type of data I want to pass into my JS view:
[
#<BarberStyle
id: 1,
barber_id: 116,
style_id: 91,
style: { name: "Cool Hairstyle" }
>,
#<BarberStyle
id: 2,
barber_id: 97,
style_id: 92,
style: { name: "Cooler Hairstyle" }
>,
etc...
]
The reason I want the data formatted this way is because I can't make any queries on associated models in my JS view (without an AJAX call to the server).
I had very similarly formatted data when I did render json: @colleges, include: :sports
in the past. This gave me a collection of Colleges
with associated Sport
models aggregated to each College
result. I don't want to build json in this fashion for my current situation, as it will complicate a few things. But I suppose that's a last resort.
I'm not sure if there's a way to structure an ActiveRecord query where it adds additional fields to the results, but I feel like it should, so here I am looking for it. Haven't found anything in the docs, but then again there is sooooo much left out of those.
Upvotes: 0
Views: 123
Reputation: 529
Doug as far as I understand your code, BarberStyle
must be a joining model between Barber
and Style
. You mentioned in your comment that you removed the has_many :styles, through: :barber_styles
from your Barber
model because you thought that it wasn't relevant. That's not true, it's exactly the point that would help you to achieve your goal. Add this relation again then you can do something like this:
barber = Barber.includes(:styles).where(barber: {id: 109})
barber.styles.each { |style| puts style.name }
Since barber.styles
is a collection, I added a loop between all the possible styles you can have. But, from that, you can use your data as you feel like, looping through it or any other way you want.
Hope to have helped!
Upvotes: 1
Reputation: 8331
First off, in your case inverse_of
does not accomplish anything, since you are setting the default values. Remove that.
Secondly, it seems you need to better understand the concept of HABTM relationships.
Using has many through
is generally a good idea since you can add data and logic to the model in the middle.
It ideally suits your case, so you should set it up like this:
class Barber < User
has_many :barber_styles
has_many :styles, through: :barber_styles
end
class Style < ActiveRecord::Base
has_many :barber_styles
has_many :barbers, through: :barber_styles
end
class BarberStyle < ActiveRecord::Base
belongs_to :barber
belongs_to :style
end
Now it is an easy task to get the styles of a given barber. Just do this:
barber = Barber.find(1)
barber.styles
# => AR::Collection[<#Style name:'Cool Hairstyle'>,<#Style name:'Cooler Hairstyle'>]
Rails automatically uses the BarberStyle model in between to find the styles of a certain barber. I assume this covers your need, if you have extra information stored only in BarberStyle, let me know.
Upvotes: 0