Reputation: 349
I have a Track table and a Section table. A track has many sections. Sections are connected to their respective task by the Section's :track_id, which corresponds to the Track's :id attribute.
<% @track = Track.find(params[:id]) %>
<% @sections = Section.find_by_track_id(@track.id) %>
In the code above I'm trying to find multiple sections that share the same :track_id attribute, but find_by_track_id() only returns the first. What's the best way to get all of them?
Thanks!
Upvotes: 1
Views: 3237
Reputation: 76784
Association
To extend Taryn East
's answer, you need to look into ActiveRecord Associations.
In your model, if you have the following has_many
relationship:
#app/models/track.rb
Class Track < ActiveRecord::Base
has_many :sections
end
#app/models/section.rb
Class Section < ActiveRecord::Base
belongs_to :track
end
This will set up a relational database association between your tracks
and sections
datatables.
--
Associative Data
The magic of Rails comes into play here
When you call the "parent" object, you'll be able to locate it using its primary key
(typically the ID
). The magic happens when Rails automatically uses this primary_key
as a foreign_key
of the child model - allowing you to call all its data as an append to the parent object:
@track = Track.find params[:id] #-> find single Track by primary key
@sections = @track.sections #-> automagically finds sections using the track primary key
This means if you call the following, it will work exactly how you want:
@sections.each do |section|
section.name
end
Where
Finally, if you wanted to look up more than one record at a time, you should identify which ActiveRecord
method you should use:
find
is to locate a single record by id
finy_by key: "value"
is to locate a single record by your defined key/columnwhere
is to return multiple items using your own conditionsSo to answer your base line question, you'll want to use where
:
@sections = Section.where track_id: params[:id]
This is not the right answer, but it should help you
Upvotes: 3
Reputation: 41
Use find when you are looking for one specific element identified by it's id.
Model.find
is using the primary key column. Therefore there is always exactly one or no result.
Upvotes: -1
Reputation: 9443
You're looking for where
, which finds all records where a specific set of conditions are met.
@sections = Section.where(track_id: @track.id)
This is unrelated to your question, but you should set @sections
and @track
in your controller. As it seems like you're new to Rails, I'd highly recommend reading through the Rails Guides. They will help you immensely on your journey.
EDIT: I was solving for the general question of "Find multiple database objects by attribute in Rails?", which is how to find multiple database objects in the general case. @TarynEast's method is the way to go to find all of the sections
for a track
, or more generally, all of the objects that belong to the desired object. For the specific case you're asking for above, go with @TarynEast's solution.
Upvotes: 5
Reputation: 27747
If your tracks and sections are related in this way, then the best way to relate them is by using the methods that come automatically from Rails' associations.
in this case, I expect in your model files, you have the following:
class Track < ActiveRecord::Base
has_many :sections
end
class Section < ActiveRecord::Base
belongs_to :track
end
Then you can get the sections for a track like this:
@track = Track.find(params[:id])
@sections = @track.sections
Upvotes: 6