サーチ…


前書き

ActiveRecordは、ビジネスデータとロジックを表すシステムのレイヤーであるMVCのMです。リレーショナルデータベース管理システム内のテーブルへのアプリケーションの豊富なオブジェクトを接続する技術がO bject R elational Mの apper(ORM)です。

ActiveRecordは、データベースのクエリを実行し、ほとんどのデータベースシステムと互換性があります。どのデータベースシステムを使用していても、ActiveRecordメソッド形式は常に同じです。

.where

whereメソッドは任意のActiveRecordモデルで使用でき、指定された条件に一致するレコードのセットをデータベースに問い合わせることができます。

whereメソッドは、キーがモデルが表すテーブルの列名に対応するハッシュを受け入れます。

簡単な例として、次のモデルを使用します。

class Person < ActiveRecord::Base
  #attribute :first_name, :string
  #attribute :last_name, :string
end

最初の名前のSvenすべての人を見つけるには:

people = Person.where(first_name: 'Sven')
people.to_sql # "SELECT * FROM people WHERE first_name='Sven'"

SvenSchrodinger名字を持つすべての人を見つけるには:

people = Person.where(first_name: 'Sven', last_name: 'Schrodinger')
people.to_sql # "SELECT * FROM people WHERE first_name='Sven' AND last_name='Schrodinger'"

上記の例では、sql出力は、 first_namelast_name両方が一致した場合にのみレコードが返されることを示しています。

OR条件付きクエリ

first_name == 'Bruce' OR last_name == 'Wayne'レコードを検索するには

User.where('first_name = ? or last_name = ?', 'Bruce', 'Wayne')
# SELECT "users".* FROM "users" WHERE (first_name = 'Bruce' or last_name = 'Wayne')

。配列あり

任意のActiveRecordモデルのwhereメソッドを使用して、 WHERE column_name IN (a, b, c, ...)という形式のSQLを生成できます。これは、引数として配列を渡すことによって実現されます。

簡単な例として、次のモデルを使用します。

class Person < ActiveRecord::Base
  #attribute :first_name, :string
  #attribute :last_name, :string
end

people = Person.where(first_name: ['Mark', 'Mary'])
people.to_sql # "SELECT * FROM people WHERE first_name IN ('Mark', 'Mary')"

配列にnilが含まれている場合、その列がnullかどうかを確認するためにSQLが変更されnull

people = Person.where(first_name: ['Mark', 'Mary', nil])
people.to_sql # "SELECT * FROM people WHERE first_name IN ('Mark', 'Mary') OR first_name IS NULL"

スコープ

スコープは、 ActiveRecordモデルで定義済みのフィルタとして機能します。

スコープはscopeクラスメソッドを使用して定義されます。

簡単な例として、次のモデルを使用します。

class Person < ActiveRecord::Base
  #attribute :first_name, :string
  #attribute :last_name, :string
  #attribute :age, :integer

  # define a scope to get all people under 17
  scope :minors, -> { where(age: 0..17) }

  # define a scope to search a person by last name
  scope :with_last_name, ->(name) { where(last_name: name) }

end

スコープはモデルクラスから直接呼び出すことができます:

minors = Person.minors

スコープは連鎖できます。

peters_children = Person.minors.with_last_name('Peters')

whereメソッドや他のクエリー型メソッドも連鎖することができます:

mary_smith = Person.with_last_name('Smith').where(first_name: 'Mary')

背後では、スコープは単純な標準クラスのメソッドの構文的な砂糖です。たとえば、これらのメソッドは機能的に同じです。

scope :with_last_name, ->(name) { where(name: name) }

# This ^ is the same as this:

def self.with_last_name(name)
  where(name: name)
end

デフォルトスコープ

モデルのすべての操作のデフォルトスコープを設定します。

scopeメソッドとクラスメソッドの間には顕著な違いがありscopescope定義スコープは、そのロジックがnilを返す場合でも常に ActiveRecord::Relation返します。しかし、クラスメソッドはそのようなセーフティネットを持たず、何かを返すと連鎖性を破る可能性があります。

どこにもない

where句は使用して否定することができwhere.not構文:

class Person < ApplicationRecord
  #attribute :first_name, :string
end

people = Person.where.not(first_name: ['Mark', 'Mary'])
# => SELECT "people".* FROM "people" WHERE "people"."first_name" NOT IN ('Mark', 'Mary')

ActiveRecord 4.0以降でサポートされています。

注文

.orderを使用してActiveRecordクエリ結果を注文することができます:

User.order(:created_at)
#=> => [#<User id: 2, created_at: "2015-08-12 21:36:23">, #<User id: 11, created_at: "2015-08-15 10:21:48">]

指定されていない場合は、昇順に並べ替えられます。以下のようにして指定することができます:

User.order(created_at: :asc)
#=> => [#<User id: 2, created_at: "2015-08-12 21:36:23">, #<User id: 11, created_at: "2015-08-15 10:21:48">]

User.order(created_at: :desc)
#=> [#<User id: 7585, created_at: "2016-07-13 17:15:27">, #<User id: 7583, created_at: "2016-07-13 16:51:18">]

.orderは文字列も受け入れます

User.order("created_at DESC")
#=> [#<User id: 7585, created_at: "2016-07-13 17:15:27">, #<User id: 7583, created_at: "2016-07-13 16:51:18">]

文字列は生のSQLであるため、属性だけでなくテーブルも指定できます。自分のrole名に従ってusersを注文する場合は、次のusersにします。

Class User < ActiveRecord::Base
    belongs_to :role
end

Class Role < ActiveRecord::Base
  has_many :users
end

User.includes(:role).order("roles.name ASC")

orderスコープは、Arelノードを受け入れることもできます。

User.includes(:role).order(User.arel_table[:name].asc)

ActiveRecord Bang(!)メソッド

失敗した場合にfalse値ではなく例外を発生させるためにActiveRecordメソッドが必要な場合は、追加することができ!彼らへ。これはとても重要です。あなたが使用しない場合、いくつかの例外/失敗は捕まえにくいので!それらの上に。開発サイクルでこれを実行して、ActiveRecordコードをこのように書くことで、時間と手間を省くことをお勧めします。

Class User < ActiveRecord::Base
  validates :last_name, presence: true
end

User.create!(first_name: "John")
#=> ActiveRecord::RecordInvalid: Validation failed: Last name can't be blank

bang! )を受け入れるActiveRecordメソッドは次のとおりです。

  • .create!
  • .take!
  • .first!
  • .last!
  • .find_by!
  • .find_or_create_by!
  • #save!
  • #update!
  • すべてのARダイナミックファインダ

.find_by

find_byを使用して、テーブル内の任意のフィールドでレコードを見つけることができます。

したがって、 first_name属性を持つUserモデルを使用すると、次のことができます。

User.find_by(first_name: "John")
#=> #<User id: 2005, first_name: "John", last_name: "Smith">

find_byがデフォルトで例外をスローしないことをfind_byfind_byてください。結果が空集合であれば、 find代わりにnilを返しfind

例外が必要な場合は、 find_by!使用することができますfind_by!それは、 findようなActiveRecord::RecordNotFoundエラーを発生させfind

。すべて削除

多くのレコードをすばやく削除する必要がある場合、 ActiveRecord.delete_allメソッドを提供します。モデル上で直接呼び出す、そのテーブル内のすべてのレコードを削除する、またはコレクションを削除する。ただし、 .delete_allはオブジェクトをインスタンス化しないため、コールバックは提供されません( before_*およびafter_destroyafter_destroyません)。

User.delete_all
#=> 39  <-- .delete_all return the number of rows deleted

User.where(name: "John").delete_all 

ActiveRecordの大文字と小文字を区別しない検索

ActiveRecordモデルで類似の値を検索する必要がある場合は、 LIKEまたはILIKEを使用するように誘惑されるかもしれませんが、データベースエンジン間では移植できません。同様に、常にダウンケーシングまたはアップケーシングに頼ることは、パフォーマンス上の問題を引き起こす可能性があります。

ActiveRecordの基礎となるArel matchesメソッドを使用すると、安全な方法でこれを行うことができます:

addresses = Address.arel_table
Address.where(addresses[:address].matches("%street%"))

Arelは、構成されたデータベースエンジンに適切なLIKEまたはILIKE構造を適用します。

最初と最後のレコードを取得する

Railsは、データベースからfirstlastレコードを取得する非常に簡単な方法を持っています。

usersテーブルからfirstレコードを取得するには、次のコマンドを入力する必要があります。

User.first

それは次のsqlクエリを生成します:

SELECT  `users`.* FROM `users`  ORDER BY `users`.`id` ASC LIMIT 1

そして、次の記録を返すでしょう:

#<User:0x007f8a6db09920 id: 1, first_name: foo, created_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00, updated_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00 >

usersテーブルからlastレコードを取得するには、次のコマンドを入力する必要があります。

User.last

それは次のsqlクエリを生成します:

SELECT  `users`.* FROM `users`  ORDER BY `users`.`id` DESC LIMIT 1

そして、次の記録を返すでしょう:

#<User:0x007f8a6db09920 id: 10, first_name: bar, created_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00, updated_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00 >

最初最後のメソッドに整数を渡すと、 LIMITクエリが作成され、オブジェクトの配列が返されます。

User.first(5)

これは、次のsqlクエリを生成します。

SELECT  "users".* FROM "users"  ORDER BY "users"."id" ASC LIMIT 5

そして

User.last(5)

これは、次のsqlクエリを生成します。

SELECT  "users".* FROM "users"  ORDER BY "users"."id" DESC LIMIT 5

.groupと.count

私たちはProductモデルを持っており、それらのcategoryグループ化したいと考えていcategory

Product.select(:category).group(:category)

これにより、次のようにデータベースが照会されます。

SELECT "product"."category" FROM "product" GROUP BY "product"."category"

グループ化されたフィールドも選択されていることを確認します。グループ化は、 categories発生(この場合)を数えるのに特に便利です。

Product.select(:category).group(:category).count

クエリが示すように、すべてのレコードを最初に取得し、コード内でカウントするよりもはるかに効率的な、カウントにデータベースを使用します:

SELECT COUNT("products"."category") AS count_categories, "products"."category" AS products_category FROM "products" GROUP BY "products"."category"

.distinct(または.uniq)

結果から重複を削除する場合は、 .distinct()使用できます。

Customers.select(:country).distinct

これは、次のようにデータベースに照会します。

SELECT DISTINCT "customers"."country" FROM "customers"

.uniq()は同じ効果を持ちます。 Rails 5.0では廃止され、バージョン5.1のRailsから削除されます。その理由は、 uniqueという単語は異なるものと同じ意味を持たず、誤解を招く可能性があるからです。さらに、 distinctはSQL構文に近い。

結合

joins()使用すると、テーブルを現在のモデルに結合できます。例えば、

User.joins(:posts)

次のSQLクエリを生成します。

"SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id""

テーブルに参加すると、そのテーブルにアクセスできます。

User.joins(:posts).where(posts: { title: "Hello world" })

複数形に注意してください。あなたの関係が:has_many場合、 joins()引数は複数形にする必要があります。それ以外の場合は、単数形を使用します。

ネストされたjoins

User.joins(posts: :images).where(images: { caption: 'First post' })

それは次を生成する:

"SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" INNER JOIN "images" ON "images"."post_id" = "images"."id""

含まれるもの

ActiveRecord with includesは、指定されたすべてのアソシエーションが最小数のクエリを使用してロードさincludesようにします。したがって、関連付けられたテーブルを持つデータのテーブルをクエリすると、両方のテーブルがメモリにロードされます。

@authors = Author.includes(:books).where(books: { bestseller: true } )

# this will print  results without additional db hitting
@authors.each do |author| 
  author.books.each do |book|
    puts book.title
  end
end

Author.joins(:books).where(books: { bestseller: true } )は、 書籍を読み込まずに条件付きの著者だけをメモリに読み込みます 。ネストされた関連付けに関する追加情報が必要ない場合は、 joins使用しjoins

@authors = Author.joins(:books).where(books: { bestseller: true } )

# this will print results without additional queries
@authors.each { |author| puts author.name }

# this will print results with additional db queries
@authors.each do |author| 
  author.books.each do |book|
    puts book.title
  end
end

リミットとオフセット

limitを使用してフェッチするレコードの数を指定し、 offsetを使用してレコードの数を通知してスキップしてレコードを返すことができます。

例えば

User.limit(3) #returns first three records

これは、次のSQLクエリを生成します。

"SELECT  `users`.* FROM `users` LIMIT 3"

上記のクエリではオフセットが記述されていないので、最初の3つのレコードが返されます。

User.limit(5).offset(30) #returns 5 records starting from 31th i.e from 31 to 35

これは、次のSQLクエリを生成します。

"SELECT  `users`.* FROM `users` LIMIT 5 OFFSET 30"


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow