ActiveRecord Query Interface 3.0

この翻訳では、Ruby on Rails 3のActiveRecrodの次のバージョンでの革新について説明し、新しいインターフェイスのサポートを優先して除外されるモジュールの部分についても説明します。

Rails 3.1でサポートが失われるものは何ですか?


次のメソッドはRails 3.1のリリースで非推奨と見なされ(Rails 3.0ではありません)、Rails 3.2から完全に除外されます(ただし、特別なプラグインをインストールして使用することもできます)。 この警告に留意してください。 コードの大幅な変更が必要です。

要するに、 :conditions :include :joins :limit :offset :order :select :readonly :group having :from :lock ActiveRecordによって提供される任意のクラスメソッド:lock含むoptionsハッシュを渡すomは廃止されたと見なされます。

これをより詳細に検討してください。 ActiveRecordは現在、次の検索方法を提供しています。計算方法と同様に:Rails 3.0以降、これらのメソッドにオプションを渡すことは推奨されておらず、Rails 3.2では完全に削除されます。 さらに、メソッドfind(:first)およびfind(:all) (追加オプションなし)も除外され、 firstおよびallが優先されall 。 ルールの例外として、 count()は引き続き:distinctオプションを受け入れます。

次のコードは、サポートされていないオプションの使用を示しています。
User.find(:all, :limit => 1)
User.find(:all)
User.find(:first)
User.first(:conditions => {:name => 'lifo'})
User.all(:joins => :items)

ただし、このコードは引き続き機能します。
User.find(1)
User.find(1,2,3)
User.find_by_name('lifo')

さらに、オプションハッシュをnamed_scopeメソッドに渡すと、サポートも失われます。
named_scope :red, :conditions => { :colour => 'red' }
named_scope :red, lambda {|colour| {:conditions => { :colour => colour }} }

オプションの転送は、メソッドwith_scopewith_exclusive_scopeおよびdefault_scopeサポートも失います:
with_scope(:find => {:conditions => {:name => 'lifo'}) { ... }
with_exclusive_scope(:find => {:limit =>1}) { ... }
default_scope :order => "id DESC"

動的scoped_by_も同様に履歴に記録されます。
red_items = Item.scoped_by_colour('red')
red_old_items = Item.scoped_by_colour_and_age('red', 2)

新しいAPI


Rails 3のActiveRecordは、以下の検索メソッドを受け取ります( optionsハッシュの既存の同等物は括弧内に示されています)。
チェーン

上記の各メソッドは、 Relationクラスのオブジェクトを返します。 基本的に、 Relation匿名のnamed_scopeに非常に似ています。 これらのメソッドはすべて自分で定義されているため、呼び出しのチェーンを作成できます。
lifo = User.where(:name => 'lifo')
new_users = User.order('users.id DESC').limit(20).includes(:items)

既存のリレーションに複数のファインダーを適用することもできます。
cars = Car.where(:colour => 'black')
rich_ppls_cars = cars.order('cars.price DESC').limit(10)

ほぼモデル

プライマリCRUDメソッドの使用に関しては、リレーションはモデルとまったく同じように動作します。 次のメソッドは、Relationクラスのオブジェクトで呼び出すことができます。次のコードは期待どおりに機能します。
red_items = Item.where(:colour => 'red')
red_items.find(1)
item = red_items.new
item.colour #=> 'red'

red_items.exists? #=> true
red_items.update_all :colour => 'black'
red_items.exists? #=> false

updateまたはdelete / destroyメソッドを呼び出すと、 Relationが「リセット」されることを知っておくことが重要です。 メソッドを最適化するために使用されるキャッシュエントリ( relation.sizeなど)を削除します。

遅延読み込み

おそらく前の例から、 Relations 「怠lazに」ロードされることがすでに明らかになっています-つまり それらについては、コレクションを操作するメソッドを呼び出す必要があります。 これは、 associationsnamed_scopeすでに機能している方法に非常に似ています。
cars = Car.where(:colour => 'black') # Relations ,
cars.each {|c| puts c.name } # "select * cars ..."

これは、フラグメントキャッシングと共に非常に便利です。 そのため、コントローラーでは次を呼び出すだけで十分です。
def index
@recent_items = Item.limit(10).order('created_at DESC')
end
そしてビューで:
<% cache('recent_items') do %>
<% @recent_items.each do |item| %>
...
<% end %>
<% end %>

前の例で@recent_items@recent_items.each viewから@recent_items.eachれた場合にのみ、データベースから@recent_items生成されview 。 コントローラーはデータベースからのクエリを実行しないため、追加の作業を必要とせずに断片化されたキャッシングがはるかに効率的になります。

強制ダウンロード- allfirstlast

遅延読み込みが不要な場合は、たとえば、 all Relation型のオブジェクトで呼び出す必要があります。
cars = Car.where(:colour => 'black').all

ここではallRelationではなくArray返すことを覚えておくことが重要です。 これは、Rails 2.3でnamed_scopeassociationsがどのようにnamed_scopeするかに似ています。
同様に、 firstlastメソッドはタイプActiveRecord (またはnil )のオブジェクトを返します:
cars = Car.order('created_at ASC')
oldest_car = cars.first
newest_car = cars.last

named_scope scope

named_scopeメソッドの使用は、 named_scopeを支持して、Rails 3.0では推奨されません。 しかし、実際に変更されたのは、 named_プレフィックスを記述する必要がなくなったことnamed_です。 渡す検索オプションは、Rails 3.1から完全に除外されます。
named_scopeメソッドは、単にscopeという名前に変更されました。 つまり 次の定義:
class Item
named_scope :red, :conditions => { :colour => 'red' }
named_scope :since, lambda {|time| {:conditions => ["created_at > ?", time] }}
end

次のようになります。
 クラスItem
    スコープ:赤、:条件=> {:色=> '赤'}
    スコープ:以来、ラムダ{|時間|  {:条件=> ["created_at>?"、時間]}}
終わり 

ただし、オプションハッシュが除外されるという事実を考慮すると、実際には新しい検索方法を使用して記述する必要があります。 このように:
 クラスItem
    スコープ:赤、ここで(:色=> '赤')
    スコープ:以来、ラムダ{|時間|  where( "created_at>?"、time)}
終わり 

内部的には、 named scopeRelationアドオンであり、 finderメソッドと組み合わせて使用​​するための非常に単純なバリエーションを作成します。
red_items = Item.red
available_red_items = red_items.where("quantity > ?", 0)
old_red_items = Item.red.since(10.days.ago)

Model.scoped

「クリーンな」リレーションから始まる複雑なクエリを作成する必要がある場合は、 Model.scoped使用する必要があります。
cars = Car.scoped
rich_ppls_cars = cars.order('cars.price DESC').limit(10)
white_cars = cars.where(:colour => 'red')

内部といえば、 ActiveRecord::Baseには次のデリゲートが含まれています。
delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
delegate :select, :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :to => :scoped
delegate :count, :average, :minimum, :maximum, :sum, :calculate, :to => :scoped

上記のコードは、 ActiveRecord内で行われていることのより透明なビューを提供できます。 これに加えて、動的メソッド(別名find_by_namefind_all_by_name_and_colour )もRelationによって委任されます。

with_scopeおよびwith_exclusive_scope

with_scopewith_exclusive_scopeRelation 'aの上に構築され、それらとの関係を使用できるようになりました。
  with_scope(where(:name => 'lifo'))do
    ...
終わり 

または名前付きスコープ:
  with_exclusive_scope(Item.red)do
    ...
終わり 

Source: https://habr.com/ru/post/J82767/


All Articles