Sciguy77
Sciguy77

Reputation: 349

Find multiple database objects by attribute in Rails?

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

Answers (5)

Richard Peck
Richard Peck

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

enter image description here

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/column
  • where is to return multiple items using your own conditions

So 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

Rahu1
Rahu1

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

Joe Kennedy
Joe Kennedy

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

Rahu1
Rahu1

Reputation: 41

    <% @[email protected]%>

Upvotes: -1

Taryn East
Taryn East

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

Related Questions