ActiveRecord
1. create_with
create
するときの条件を追加できます。
例えば、"ユーザーから「男」を探して、いなかったら「男」、「山田太郎」を追加したい" とき
User.create_with(name: 'Yamada Taro').find_or_create_by(sex: 'man')
こんな感じで find_or_create
を使う際に便利です。
2. update(attributes)
内部的には、attribute
をオブジェクトにセットして、save
メソッドを呼んでいるだけ。
なので、これを利用すると update_or_create_by
が作れます。
User.find_or_initialize_by(name: 'Yamada Taro').update(sex: 'man')
initialize
しないで
User.find_or_create_by(name: 'Yamada Taro').update(sex: 'man')
とすると、INSERT した後に UPDATE するので、find_or_initialize_by
した方がちょっとお得。
3. extending(*modules, &block)
ActiveRecord_Relation に対して、exetend することが出来ます。
例えば
Partner.identifiers
#=> NoMethodError: undefined method `identifiers'
module Identifiers
def identifiers
pluck(:identifier)
end
end
partner = Partner.all.extending(Identifiers)
partner.identifiers
#=> ["partner1", "partner2", "partner3", "partner4"]
user = User.all.extending(Identifiers)
user.identifiers
#=> ["user1", "user2", "user3"... ]
このように、再利用することができます。
引数には、ブロックを渡すことも出来ます。
partner = Partner.all.extending do
def identifiers
pluck(:identifier)
end
end
ブロックによる更なる拡張も可能です。
partner = Partner.all.extending(Identifiers) do
def names
pluck(:name)
end
end
4. destroy_all
と delete_all
destroy_all
は条件にあったものを関連テーブルも含めて削除する。DELETE
は主キーによって行うので、DELETE
の手前で SELECT
が発行されます。そのため、対象の DELETE
は一つずつ行われます。
delete_all
は関連テーブルは削除しないが、条件にあったものを bulk でまるっと消します。関連データを削除しない場合は、こっちの方が効率がいい。
5. except
, only
, unscope
指定した条件を外す系のメソッド達
except(*skips)
User.select(:id).except(:select)
#=> SELECT `users`.* FROM `users`
only
partner.select(:id).where(id: 1).only(:where)
#=> SELECT `partners`.* FROM `partners` WHERE `partners`.`id` = 1
unscope(*args)
# 例えば
1. User.order('email DESC').unscope(:order)
#== User.all
2. User.order('email DESC').select('id').where(name: "John")
.unscope(:order, :select, :where)
#== User.all
3. User.where(name: "John", active: true)
.unscope(where: :name)
#== User.where(active: true)
# こんな感じでも使える
has_many :comments, -> { unscope where: :trashed }
except
も似たメソッドだが、merge
で使えません。
User.order('email').merge(User.except(:order))
== User.order('email')
User.order('email').merge(User.unscope(:order))
== User.all
こういう感じで、chain を外す事も出来るんですね。
ActiveSupport
6. squish
String
クラス
両端の空白文字を取り除き、文字列内の連続する空白文字をスペース一つに置き換える。
" foo bar boo ".squish #=> "foo bar boo"
" foo bar\n\n\n\tboo\t\n".squish #=> "foo bar boo"
squish!
破壊的変更も!ちなみに中身は
def squish!
gsub!(/\A[[:space:]]+/, '')
gsub!(/[[:space:]]+\z/, '')
gsub!(/[[:space:]]+/, ' ')
self
end
こんなの用意されてるの知らなくて、自分で正規表現作って gsub
してました。
7. remove(*patterns), remove!(*patterns)
String
クラス
こちらは pattern にマッチしたものを削除する!
"foo bar test".remove(" test") #=> "foo bar"
8. all_week, all_month, all_quarter, all_year
Date
, DateAndTime
, Time
で使える。
週、月、四半期、年の Range を返す。
中見るとこんな感じ
beginning_of_week(start_day)..end_of_week(start_day)
業務のコードでわざわざ、beginning_of_month
と end_of_month
計算して、範囲指定しているところがあったので、all_month
一発でいけたんだなあと。
9. advance(options)
Date
, DateAndTime
, Time
で使える。
key を指定して、まるっと足し算を行う
key は keys: :years, :months, :weeks, :days
today = Date.today #=> Sat, 09 May 2015
today.advance({years: 1, months: 1, weeks: 1, days: 1}) #=> Fri, 17 Jun 2016
なんかちょろっと手元で試したいときとかに使えそうだなあと。
10. with_options
Object
クラス
重複しているオプションがあったら、まとめることが出来ます。
例えば
class Account < ActiveRecord::Base
has_many :customers, dependent: :destroy
has_many :products, dependent: :destroy
has_many :invoices, dependent: :destroy
has_many :expenses, dependent: :destroy
end
こんな感じで、同じような条件が続く事ってよくあると思うのですが、
class Account < ActiveRecord::Base
with_options dependent: :destroy do |assoc|
assoc.has_many :customers
assoc.has_many :products
assoc.has_many :invoices
assoc.has_many :expenses
end
end
と書けます。
特に、レシーバーが必要ない場合は
with_options dependent: :destroy do
has_many :customers
has_many :products
has_many :invoices
has_many :expenses
end
省略可能です。
ちなみに
with_options if: :persisted?, length: {minimum: 50} do
validates :content, if: -> { content.present? }
end
と同じオプションをブロック内でも定義した場合は
validates :content, length: {minimum: 50}, if: -> { content.present? }
とブロック内で定義した方が優先されます。
以上、なんのつながりも無くランダムに選んだ、メソッド 10 でした。