[英]How do I get back an ActiveRecord instead of an ActiveRecord relation?
使用 Rails 5. 如何獲得 ActiveRecord 而不是 ActiveRecord 關系? 我有以下型號
class State < ActiveRecord::Base
belongs_to :country
...
def self.cached_find_us_state_by_name(name)
Rails.cache.fetch("#{name.upcase} US") do
find_us_state_by_name(name)
end
end
# Look up a US state by its full name
def self.find_us_state_by_name(name)
search_criteria = ["upper(states.name) = ? "]
search_criteria.push( "states.country_id = countries.id " )
search_criteria.push( "countries.iso = 'US' " )
results = State.joins(:country).where( search_criteria.join(' and '),
name.upcase)
end
但是當我使用這些方法查找項目時,我得到的是一個 ActiveReocrd 關系......
2.4.0 :004 > State.cached_find_us_state_by_name('Ohio')
=> #<ActiveRecord::Relation [#<State id: 3538, name: "Ohio", country_id: 233, iso: "OH">]>
這是以后的問題,特別是......
ActiveRecord::AssociationTypeMismatch: State(#70288305660760) expected, got State::ActiveRecord_Relation(#70288290686360)
from /Users/davea/.rvm/gems/ruby-2.4.0@global/gems/activerecord-5.0.1/lib/active_record/associations/association.rb:221:in `raise_on_type_mismatch!'
from /Users/davea/.rvm/gems/ruby-2.4.0@global/gems/activerecord-5.0.1/lib/active_record/associations/belongs_to_association.rb:12:in `replace'
編輯:根據給出的建議,我將方法更改為
def self.cached_find_us_state_by_name(name)
Rails.cache.fetch("#{name.upcase} US") do
find_us_state_by_name(name)
end
end
# Look up a US state by its full name
def self.find_us_state_by_name(name)
search_criteria = ["upper(states.name) = ? "]
search_criteria.push( "states.country_id = countries.id " )
search_criteria.push( "countries.iso = 'US' " )
results = State.joins(:country).where( search_criteria.join(' and '),
name.upcase).take
end
但唉,我仍然得到一個 ActiveRecord::Relation
2.4.0 :011 > State.cached_find_us_state_by_name('Ohio')
=> #<ActiveRecord::Relation [#<State id: 3538, name: "Ohio", country_id: 233, iso: "OH">]>
您可以使用find_by
而不是where
- 源代碼很簡單:
def find_by(*args)
where(*args).take
end
另一種方法是調用.first
或[0]
,但如果你的where
有很多記錄,這會很慢,因為它會在選擇第一個之前將它們全部加載到內存中。 如果使用limit(1)
,那么這些方法的速度將是可以接受的。
有多種方法可以從ActiveRecord::Relation
獲取ActiveRecord
對象。調用的結果
results = State.joins(:country).where( search_criteria.join(' and '),
name.upcase)
返回一個ActiveRecord::Relation
。 當您在ActiveRecord
中使用where
子句時,情況總是如此。 為了獲得特定的ActiveRecord
對象,您可以:
find_by
方法返回它在數據庫中找到的第一個實例。 請注意,這不會返回所有符合條件的記錄。 * 例如, User.find_by(first_name: "Mark")
將返回一個ActiveRecord
對象,其中包含第一個名字為“Mark”的記錄ActiveRecord::Relation
集合上使用first
一種方法。 例如, User.where(first_name: "Mark").first
與前面的示例執行相同的操作。最后,你可以這樣寫:
User.where(first_name: "Mark") do |u| puts u.last_name end
這允許您一次遍歷ActiveRecord::Relation
集合一條記錄。 因此,對於您的示例,它看起來像這樣:
results.each do |res| # do stuff end
大多數 ActiveRecord 方法返回 ActiveRecord::Relations 以提供流暢的 API(如果您願意的話,語法上令人愉悅的方法鏈接)。 我認為這是一個設計決定。 有一些方法可以打破這種情況,例如first
(實際上是對find_nth!(0)
的調用)、 last
to_a
、 to_sql
和其他一些方法。
因此,我發現“周圍”的方法是使用.first
,我真正打算得到一個且只有一個結果,正如 Mark 和 maxple 所建議的那樣。 我還認為這可能是唯一的方法之一。
這個: https ://github.com/rails/rails/blob/603ebae2687a0b50fcf003cb830c57f82fb795b9/activerecord/lib/active_record/querying.rb
而這個(查詢委托了它的大部分方法): https ://github.com/rails/rails/blob/603ebae2687a0b50fcf003cb830c57f82fb795b9/activerecord/lib/active_record/querying.rb
可能值得瀏覽。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.