ActiveRecord::Relation issue

Hi, everyone.

Yesterday found an interesting issue in scope method.
Let`s say, you have next model structure:

Model A --has_many-> Model B --has_many-> Model C --has_many-> Model_D

Model D has some attribute, let`s say, ‘status’ ENUM(‘opened’,
‘closed’).

In Model A I would like to take all records, where Model D`s status is
opened.
This is a little bit confusing.

Here is an example.
We have a project. A project has many tasklists. Tasklist has many
tasks.
I would like take all projects, which have one or more tasks opened.
I hope, there should be any possibility to call in controller just
active_projects = Project.all.active.

I would appreciate any help.

Max R.

I guess I have to chalk to up to another “I didn’t know you could do
that”. I’ll also admit I have no idea how efficient this is.

I’ve used a technique where I query a belongs_to table with the ids of
a has_many related table. In my test I have
Assessments has_many -> Questions has_many -> Answers

I’d do something like
answer_ids = Answer.where(:requires_other =>
true).select(:question_id).map(&:question_id)

@foo.map(&:id) is shorthand for @foo.map{|i| i.id}, which gets

array of ids
question_ids = Question.where(:id =>
answer_ids).select(:assessment_id).map(&:assessment_id)
@assessments = Assessment.where(:id => question_ids)

Or, if you want one big hard to read statement!

@assessments = Assessment.where(:id => Question.where(:id =>
Answer.where(:requires_other =>
true).select(:question_id).map(&:question_id)).select(:assessment_id).map(&:assessment_id))

Someone else will have to chime in on how efficient or inefficient
this is. My last project was on a database that was very reliant on
“sets” and this is the closest thing I’ve found in rails to that
concept.

Steve

On 15 October 2010 13:00, Max R. [email protected] wrote:

Hi, everyone.

Yesterday found an interesting issue in scope method.
Let`s say, you have next model structure:

Model A --has_many-> Model B --has_many-> Model C --has_many-> Model_D

Are the reverse relationships has_many or belongs_to?

Colin

Colin L. wrote in post #954645:

Are the reverse relationships has_many or belongs_to?

Colin

Yes, sure.
A <–belongs_to- B <–belongs_to- C <–belongs_to- D

2Steve.

Here you have a right solution, but this code should be written in
controller. In this case, I could easily run through all records and
calculate the Model A`s state.

Anyway, for 3 model structure there is actually a solution. Here it is:
#Model C definition
belongs_to :model_b

#Model B definition
has_many :model_c
belongs_to :model_a

#Model A definition
has_many :model_b
–>has_many :model_c, :through => :model_b

Max R.

On 16 October 2010 13:47, Max R. [email protected] wrote:

belongs_to :model_a

#Model A definition
has_many :model_b
–>has_many :model_c, :through => :model_b

I have not tried it but can you then say
has_many :model_d, :through → :model_c

If you can then I think you can just find A where a.d.state is whatever.

Colin

Someone else will have to chime in on how efficient or inefficient
this is. My last project was on a database that was very reliant on
“sets” and this is the closest thing I’ve found in rails to that
concept.

Just To clarify the last statement, the Database environment was 4D
and in 4D you’d do

QUERY([Answers];[Answers]requires_other = true)
RELATE ONE SELECTION([Answers];[Questions])
RELATE ONE SELECTION([Questions];[Assessments])

Don’t know if there is an equivalent approach in Rails.

Steve

At the end of the day, the most important thing is that it works.
However, I think we should try to get the database do the work. I’ll
apologize in advance that this example is rails2.

Project -> TaskList -> Task

Project.all(:group => “projects.id”, :joins => {:task_lists => :task},
:conditions => “tasks.status = ‘open’”)

This results is a list of projects that have open tasks.

Luke

Luke C. wrote in post #954803:

At the end of the day, the most important thing is that it works.
However, I think we should try to get the database do the work. I’ll
apologize in advance that this example is rails2.

Project -> TaskList -> Task

Project.all(:group => “projects.id”, :joins => {:task_lists => :task},
:conditions => “tasks.status = ‘open’”)

This results is a list of projects that have open tasks.

Luke

Thanks a lot, Luke.
This is exactly, what I meant.

Actually, there is next structure:

User -> Project -> Tasklist -> Task

Thanks to Luke, I wrote next scope in the model:

class Project < ActiveRecord::Base
has_and_belongs_to_many :users
has_many :tasklists
belongs_to :user

def self.active
all(:group => ‘projects.id’, :joins => {:tasklists => :tasks},
:conditions => “tasks.status = ‘open’”)
end
end

And now the call User.first.projects.active returns all the projects
with active tasks.

Max R.

At the end of the day, the most important thing is that it works. However, I
think we should try to get the database do the work. I’ll apologize in advance
that this example is rails2.

Project -> TaskList -> Task

Project.all(:group => “projects.id”, :joins => {:task_lists => :task},
:conditions => “tasks.status = ‘open’”)

This results is a list of projects that have open tasks.

Luke

Still not a lot out there on rails3 finders/arel examples. Is this the
rails3 version of the above?

Project.group(:id).joins(:task_lists => :tasks).where(:tasks =>
{:status => ‘open’})

Seemed to work in my assessments example

Assessment.group(:id).joins(:questions => :answers).where(:answers =>
{:requires_other => true})

Colin L. wrote in post #954800:

On 16 October 2010 13:47, Max R. [email protected] wrote:

belongs_to :model_a

#Model A definition
has_many :model_b
–>has_many :model_c, :through => :model_b

I have not tried it but can you then say
has_many :model_d, :through → :model_c

If you can then I think you can just find A where a.d.state is whatever.

Why not use the nested_has_many_through plugin?

Colin

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]