user1870954
user1870954

Reputation: 207

Model Associations in Rails has_one with class_name

I'm trying to find an optimal way to model my database.
Background:

Basic index layout
-- Environment1 --Status_Field_1--Status_Field_2--Status_Field_3--Status_Field_4--
-- Environment2 --Status_Field_1--Status_Field_2--Status_Field_3--Status_Field_4--
-- Environment3 --Status_Field_1--Status_Field_2--Status_Field_3--Status_Field_4--
-- Environment4 --Status_Field_1--Status_Field_2--Status_Field_3--Status_Field_4--

Current Schema

Environment(name):has_many StatusUpdates
StatusUpdate(field1, field2, field3, field4): belongs_to Environment    

Environments Controller

def index
    @environments = Environment.paginate(page: params[:page])
end

I then render @environments using a partial.

The Question
The current schema seems appropriate, but I suspect I would have to make an extra call to the database in the EnvironmentsController during the index function. Do I change the Environment schema to include fields 1 - 4? Or is there a way to execute Environment.paginate while retrieving the most recent StatusUpdate from the database for each Environment?

H-man's recommendation sounds perfect, but I can't figure out why I am receiving an unexpected tLabel error in my model with the has_one association he recommended. For reference:

class Environment < ActiveRecord::Base
    has_many: status_updates
    has_one: current_status, -> { order: 'created_at DESC' }, class_name: 'StatusUpdate'
end

Rails 4.0.2

Upvotes: 0

Views: 451

Answers (1)

Hesham
Hesham

Reputation: 2347

class Environment < ActiveRecord::Base
  has_many :status_updates
  has_one :current_status, -> {order 'created_at DESC'}, class_name: 'StatusUpdate'
end

Then you can do this:

def index
  @environments = Environment.includes(:current_status).paginate(page: params[:page])
end

This will eager-load the current status update for all environments in one go. I assume you're using Rails 4 since you didn't mention the version #. If you're using an older version of rails, use this instead:

  has_one :current_status, class_name: 'StatusUpdate', order: 'created_at DESC'

Upvotes: 1

Related Questions