0

I am trying to retrieve one field from a "has_one :through" association. Assuming I have the following model:

class CreatePersons < ActiveRecord::Migration
  def change
    create_table :person do |t|
      t.string :first_name
      t.string :last_name
      t.date   :age
    end
  end

  def change
    create_table :location do |t|
      t.decimal     :longitude
      t.decimal     :latitude
      t.string      :city
      t.string      :state

      t.references  :person
    end
  end

  def change
    create_table :forecasts do |t|
      t.timestamp   :time
      t.text        :summary
      t.decimal     : precipitation

      t.references    :location

      t.timestamps
    end
  end
end

... and the following model:

class Location < ActiveRecord::Base
  belongs_to  :person
  belongs_to  :forecast
end

class Forecast < ActiveRecord::Base
  belongs_to :locaiton
  has_one    :person,    :through => :location
end

class Person < ActiveRecord::Base
end

.. and I want to make query using ActiveRecord that pulls out ONLY the persons first name based on the forecast (i know its stupid, but this is just an excercise); so something like this:

# i realize this is a bad query, i'm putting this here to make my question stronger
Forecast.where("percipitation > ?", 1.5).select(:first_name)

or in SQL terms

select first_name from forecast fc
inner join locaiton loc on loc.id = fc.location_id
inner join person on person.id = loc.person_id
where precipitation > 1.5

SO I have tried something like this:

Forecast.joins(:person).where("percipitation > ?", 1.5).select(:person)

# Forecast.joins(:person).where("percipitation > ?", 1.5).select(:person).to_sql

#  select 'person' from forecast fc
#  inner join locaiton loc on loc.id = fc.location_id
#  inner join person on person.id = loc.person_id
#  where fc.percipitation > 1.5

this returns me empty instances of the Forecast object

so then I tried this:

Forecast.joins(:person).where("percipitation > ?", 1.5).select("person.first_name")

# Forecast.joins(:person).where("percipitation > ?", 1.5).select("person.first_name").to_sql

#  select 'person.first_name' from forecast fc
#  inner join locaiton loc on loc.id = fc.location_id
#  inner join person on person.id = loc.person_id
#  where fc.percipitation > 1.5

however, this also results in a colleciton of empty Forecast objects

HOWEVER, doing this results in exactly what i want, but this is already after the db has been queried:

result = Forecast.joins(:person).where("precipitation > ?", 1.5)

result.each do |forecast|

  puts forecast.person.first_name # => "John", "Bob", "Jim"

end

Why can't I get just the first_name out of the DB using select and pull only first_name out of the database? I'm obviously missing something.

4

1 回答 1

1

我不知道为什么您的解决方案完全有效。

这样做:

Forecast.where("precipitation > ?", 1.5).joins(:person).pluck("person.first_name")

它将返回名字数组。

如果您确实需要使用select(获取范围):

Forecast.where("precipitation > ?", 1.5).joins(:person).select("person.first_name")
于 2014-10-11T16:16:23.047 回答