Reputation: 5931
So I'm new to scopes, and don't really understand them well.Let's say I have 2 models, Project
and Ticket
:
class Project < ActiveRecord::Base
has_many :tickets
end
class Ticket < ActiveRecord::Base
belongs_to :project
end
I'm used to code like this to access associated data from tickets:
Project.find(1).tickets.each do |ticket|
puts ticket.name
end
I created new scope:
scope :default, -> { where(default: true) }
And now when I use Project.default
I get back ActiveRecord::Relation
and don't have a clue how to access associated tickets
?
Upvotes: 1
Views: 39
Reputation: 115511
Project.default will indeed return an ActiveRecord::Relation
, which is a 'to be triggered' query. The query will be triggered once you start looping etc, this is sort of transparent to you.
If you want to get tickets from the projects, first I recommend you include them in your query to avoid N+1. Do it this way:
projects = Project.default.includes(:tickets)
Then to access tickets of a particular project:
project = projects.first
project.tickets
If you want a method to always return a single object:
class Project < ActiveRecord::Base
has_many :tickets
def self.get_default_with_tickets
Project.where(default: true).includes(:tickets).first
end
end
then:
Project.get_default_with_tickets #=> your_project
Be sure to handle the cases:
Upvotes: 2
Reputation: 32933
Use all
or first
to complete the query.
#get all default projects
Project.default.all
#get the first default project
Project.default.first
Upvotes: 0
Reputation: 76774
A scope is basically just a class method (one which fires on a non-intialized model):
class Project < ActiveRecord::Base
has_many :tickets
scope :defaults, -> { where(default: true) }
end
This means if you do this:
@defaults = Project.defaults
... you get all the project
objects back which have the attribute default
as true
This is the same as this:
class Project < ActiveRecord::Base
has_many :tickets
def self.defaults
where(default: true)
end
end
Error
The reason you're getting a relation is because when you use where
, you're basically getting back an "array" of data (as opposed to just a single record). If you .each
through the data or just return .first
, you'll get an actual object which you can output:
@defaults = Project.defaults
@defaults.each do |project|
project.tickets #-> associated tickets
end
Upvotes: 0