0

我試圖從「has_one:through」關聯中檢索一個字段。假設我有以下型號:Rails 4:ActiveRecord =>不能從數據庫中「選擇」has_one:through字段

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 

...及以下型號:

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 

..我想用ActiveRecord的是翻出只是基於的人的名字查詢,以預測(我知道它很愚蠢,但這只是一個練習);所以是這樣的:

# 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) 

或SQL方面

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 

這就是我一直是這樣的:

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 

這種返回預測對象的我空的情況下

所以然後我試過這個:

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 

然而,這也導致空預測的colleciton對象

然而,這樣做的結果正是我想要的,但這已經是該數據庫查詢了後:

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

result.each do |forecast| 

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

end 

爲什麼我不能使用select從數據庫中獲取first_name,並且只將first_name從數據庫中取出?我明顯錯過了一些東西。

+0

另外,據我所知,我可能會添加一個範圍,但是從我的理解範圍只是要給我的能力運行手動查詢併爲我提供語法糖,例如select(「person.first_name」),如下所示:file:/// Users/tomek/Library/Application%20Support/Dash/DocSets/Ruby_on_Rails_4/Ruby%20on%20Rails。文檔集/內容/資源/文件/ api.rubyonrails.org /班/ ActiveRecord的/作用域/命名/ ClassMethods.html#方法-I-範圍。 但我想弄清楚爲什麼我不能通過選擇項目,但我可以在每個方法。 – 2014-10-11 15:17:53

回答

1

我不知道爲什麼你的解決方案可以工作。

這樣來做:

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

它會返回名字的數組。

如果你真的需要使用select(以獲得範圍):

Forecast.where("precipitation > ?", 1.5).joins(:person).select("person.first_name") 
+0

你爲什麼這樣說:「我不知道你的解決方案爲什麼能起作用。」 ?? – 2014-10-11 22:14:27

+1

因爲你應該指定你想要加入的表。您正試圖從Forecast中選擇person first_name,但您不在join子句中指定person表。 ActiveRecord應該引發異常,因爲它會嘗試在預測表中找到first_name列。 – chumakoff 2014-10-12 12:06:16

+0

好吧,但我有一個關於Forecast to Person的has_one子句,是不是有助於自動創建連接? – 2014-10-12 13:06:27