Reputation: 24895
Model A has_many model_bs.
Model B belongs_to model_a and model_c.
Model C has_many model_bs and can by of type black
or white
.
I want to pull all records of model A, which have model Bs, that belong to model C of type black
. So far I could pull all records of model B, which belong to model C of type black
, like so:
ModelB.joins(:model_c).where("model_c.type = 'black'")
This returns an ActiveRecord::Relation::ActiveRecord_Relation_ModelB
, but now I need something like:
records = ModelB.joins(:model_c).where("model_c.type = 'black'")
Model_A.where model_b: records
which doesn't work for obvious reasons.
Another thing I tried was:
Model_A.includes(:model_bs).includes(model_c).where("model_c.type = 'black'")
but this produces the error:
ActiveRecord::ConfigurationError:
Association named 'model_c' was not found on ModelA; perhaps you misspelled it?
So how do I do this? I would also like to understand the principle of querying, when you have a lot of chained models and want to retrieve records of model X, based on attribute of model Y, with model Y being n levels away from model X.
Upvotes: 1
Views: 1070
Reputation: 24895
Just for the record - since I constantly got the error that no model_c attribute is defined on ModelA I figured that in ModelA.includes(:model_bs).includes(:model_c)
it searches for a direct relation between ModelA and ModelC. So I did this - the common entity between ModelA and ModelC is ModelB, thus:
ModelB.includes(:model_a).included(:model_c).where("my_string_criteria")
Although this returns instances of ModelB and not of ModelA, as I originally wanted, this was not a problem, as I only needed the values from one field of ModelA and was going to use pluck
anyway. So I used pluck
on the above mentioned relation instead and still got what I was looking for. But xlembouras was more precise and more efficient so I went with his suggestion.
Upvotes: 0
Reputation: 8295
I think you need joins
and not includes
since you only want one model as a result.
Model_A.joins(model_bs: :model_c).where("model_cs.type = 'black'").references(:model_cs)
because modelA has many modelbs and modelC has many modelbs
Upvotes: 3
Reputation: 112
You made a typo: includes(model_c)
should be includes(:model_c)
and this is where the error Association named 'model_c' was not found on ModelA
came from.
One way to get your query could be:
Model_A.includes(:model_bs, :model_cs).where("model_cs.type = 'black'").references(:model_cs)
Also in your models you could link Model_A and Model_C directly by:
In Model_A
has_many :model_cs, :through => :model_bs
In Model_C
has_many :model_as, : through => :model_bs
Upvotes: 1