jlhonora
jlhonora

Reputation: 10699

ActiveRecord: select for has_one

I have the following active record model:

class Dispatch < ActiveRecord::Base
  has_one :waypoint
end

When accessing the waypoint object, the generated query retrieves all columns from the model:

pry(main)> d.waypoint
Waypoint Load (0.5ms) SELECT `waypoints`.* FROM `waypoints`
WHERE `waypoints`.`waypointable_id` = <dispatch_id>
LIMIT 1

If I want to retrieve specific columns from the dispatch's waypoint then I should use the select scope for has_one ApiDock reference, section 4.2.3. Unfortunately, that approach throws a NoMethodError:

pry(main)> d = Dispatch.last
pry(main)> d.waypoint.select('latitude, longitude')
Waypoint Load (19.4ms)  SELECT `waypoints`.* FROM `waypoints`
WHERE `waypoints`.`waypointable_id` = <some_id> LIMIT 1
NoMethodError: private method `select' called for #<Waypoint:0x007fe77ed79c28>

What am I missing? I tried with ActiveRecord 4.0.11 and 4.2.0.

Edit

The underlying query should be something like this:

SELECT latitude, longitude FROM `waypoints`
WHERE `waypoints`.`waypointable_id` = <some_id>
LIMIT 1

I know I could just do

Waypoint.where(waypointable_id: <some_id>).select('latitude, longitude').last

but that misses the whole point of the has_one association. And since it is a feature specified in the docs then it should work properly, right?

Upvotes: 1

Views: 1432

Answers (3)

Prakash Murthy
Prakash Murthy

Reputation: 13067

Try:

Waypoint.select('latitude, longitude').where(...)

Activerecord select is a class method : http://guides.rubyonrails.org/active_record_querying.html#selecting-specific-fields

Upvotes: 1

Ahmad Elassuty
Ahmad Elassuty

Reputation: 4744

By default has_one retrieves the whole object but if you need to override this you cannot call select on the retrieved object because select is a class method.

try ::

has_one :waypoint, -> { select "latitude, longitude"}

this will return by default only the latitude and longitude.

Upvotes: 0

pkrawat1
pkrawat1

Reputation: 681

Try this

d.waypoint.as_json(only: [:latitude, :longitude])

Upvotes: 0

Related Questions