Movatterモバイル変換


[0]ホーム

URL:


酒と泪とRubyとRailsと

Active RecordのCHANGELOG(Rails 5.0.0.beta2)を読んでみた! 


2/22(月)に開催されたSendagaya.rb #138 に参加して、
ActiveRecod CHANGELOG
を読んだのでその斜め読みのメモです!


🐝foreign_key_exists?

migrationファイルで使えるメソッド。テーブルに外部キー制約が付いているかを確認するforeign_key_exists? が追加。

# Check a foreign key exists
foreign_key_exists?(:accounts,:branches)

# Check a foreign key on a specified column exists
foreign_key_exists?(:accounts,column::owner_id)

# Check a foreign key with a custom name exists
foreign_key_exists?(:accounts,name:"special_fk_name")

アンチパターンにあるらしいから外部キー制約はちゃんと付け足ほうがいい。

🐞Active Record::Base.suppress

classComment< ActiveRecord::Base
belongs_to:commentable,polymorphic:true
after_create -> { Notification.create!comment:self,
recipients: commentable.recipients }
end

こんな風にComment を作成したら必ずNotification を作るようなパターンはあるけど、
特定のパターンの場合は、Notification を作成しないためには次のように記述する。

moduleCopyable
defcopy_to(destination)
Notification.suppressdo
# この中では Comment を作成しても Notification は作らない。
end
end
end

とするとNotification.suppress のブロックの中では、Notification が作られなくなる。

🗻Active Record::Base#accessed_fields

こんな感じのリファクタリングができるようになる。

classPostsController< ActionController::Base
after_action:print_accessed_fields,only::index

defindex
@posts = Post.all
end

private

defprint_accessed_fields
p @posts.first.accessed_fields#=> :id, :title, :author_id, :updated_at
end
end

とすると:id, :title, :author_id, :updated_at しか使わないので、
次のように書いて必要なカラムだけを取得するようにリファクタリングできる。

classPostsController< ActionController::Base
defindex
@posts = Post.select(:id,:title,:author_id,:updated_at)
end
end

😼Active Record::Base.ignored_columns

ActiveRecord::Base.ignored_columns でカラムを定義すると、Active Recordでは閲覧できないカラムを定義することができる。
おそらく、DBにあるけどもActiveRecodなどで参照してほしくないようなカラムを定義する。

🏈Active Record::Relation#update

ActiveRecord::Relation#updateの動作が次のように変わったとのこと。

# Before: idとattriubutesを渡す形式だった。1SQLで実行できるけどcallbackが呼ばれない
Person.update(15,:user_name =>'Samuel',:group =>'expert')

# After: こういった形で呼べる。1件1件更新するのでちょっと遅いけど、callbackが呼ばれる
Comment.where(group:'expert').update(body:"Group of Rails Experts")

🐯drop_テーブルのオプション :if_exists

migrationファイル内のオプションで:if_exists を設定できるようになった。

drop_table(:posts,if_exists:true)

🎂Active Record::Relation#or

Post.where(‘id = 1’).or(Post.where(‘id = 2’)) を正確に解釈するようになりました

Post.where('id = 1').or(Post.where('id = 2'))
#=> SELECT * FROM posts WHERE (id = 1) OR (id = 2)

Added #or to ActiveRecord::Relation by matthewd · Pull Request #16052 · rails/rails

🤔Active Record::Relation#left_outer_joins(#left_joins)

外部結合のための#left_outer_joins(#left_joins) が追加。

User.left_outer_joins(:posts)
#=> SELECT "users".* FROM "users" LEFT OUTER JOIN "posts" ON
#=> "posts"."user_id" = "users"."id"

added ActiveRecord::Relation#outer_joins by Crunch09 · Pull Request #12071 · rails/rails

😎findで与えたidsと同じ順序でActive Recordを返す

records = Topic.find([4,2,5])
assert_equal'The Fourth Topic of the day', records[0].title
assert_equal'The Second Topic of the day', records[1].title
assert_equal'The Fifth Topic of the day', records[2].title

🚜after_commitのcallback名が変わった

#### Before ####
after_commit:add_to_index_later,on::create
after_commit:update_in_index_later,on::update
after_commit:remove_from_index_later,on::destroy

#### After ####
after_create_commit:add_to_index_later
after_update_commit:update_in_index_later
after_destroy_commit:remove_from_index_later

🎉Active Record::Relation#in_batches

 People.in_batches(of:100)do|people|
people.where('id % 2 = 0').update_all(sleep:true)
people.where('id % 2 = 1').each(&:party_all_night!)
end

ちなみにちょっとおもしろかったのはパフォーマンスです。 idを指定しつつ検索をしていく場合のほうが、OFFSETを使うよりも早いという結果になりました。

SELECT"posts"."id"FROM"posts"ORDERBY"posts"."id"ASCLIMIT2
SELECT"posts"."id"FROM"posts"WHERE ("posts"."id" >2)ORDERBY"posts"."id"ASCLIMIT2
SELECT"posts"."id"FROM"posts"WHERE ("posts"."id" >4)ORDERBY"posts"."id"ASCLIMIT2

# ↑ のパフォーマンス
Benchmark times (50Mrows,noindex, batchsize1000):
batchtime
1194.7s
20.016s
30.006s
40.008s
50.007s
...
SELECTCOUNT(count_column)FROM (SELECT1AS count_columnFROM"posts"LIMIT2OFFSET0) subquery_for_count
SELECTCOUNT(count_column)FROM (SELECT1AS count_columnFROM"posts"LIMIT2OFFSET2) subquery_for_count
SELECTCOUNT(count_column)FROM (SELECT1AS count_columnFROM"posts"LIMIT2OFFSET4) subquery_for_count

# ↑ のパフォーマンス
Benchmark times (50Mrows,noindex, batchsize1000):
batchtime
1192.5s
2242.0s
3257.5s
4256.8s
5258.7s
... (average times increaseoneach iteration, becauseof higheroffset)

🍮none? / one? の実装の変更

none? や、one? の実装が改善。

# Before:

users.none?
# SELECT "users".* FROM "users"

users.one?
# SELECT "users".* FROM "users"

# After:

users.none?
# SELECT 1 AS one FROM "users" LIMIT 1

users.one?
# SELECT COUNT(*) FROM "users"

🏀belongs_toでアソシエーションがなければバリデーションエラー

belongs_to でアソシエーションがなければ、バリデーションエラーになるようになった。
optional: trueをつけるとエラーが出ないようになる。

🎃Tips

以下は今回のCHANGE LOGとは直接は関係ない部分

(Tips) revertを使うとrollbackできる

migrationファイルの中で以下のようなことができるrevert というのがあるそう。何がうれしいかというとロールバックができるそう。

classFixupExampleMigration< ActiveRecord::Migration[5.0]
defchange
revertdo
create_table(:apples)do|t|
t.string:variety
end
end
end
end

Reverting Previous Migrations - Rails Guide

(Tips) RubyのEnumerable#any?

%w{ant bear cat}.any? {|word| word.length >=3}#=> true
%w{ant bear cat}.any? {|word| word.length >=4}#=> true
[nil,true,99 ].any?#=> true

(Tips) Active Record::Relation#any?

person.pets# => [#]

person.pets.any?do|pet|
pet.group =='cats'
end# => false

person.pets.any?do|pet|
pet.group =='dogs'
end# => true

(Tips) define_attribute_methods

define_attribute_methods を使うと次のようなことができる。

classPerson
include ActiveModel::AttributeMethods

attr_accessor:name,:age,:address
attribute_method_prefix'clear_'

private

defclear_attribute(attr)
send("#{attr}=",nil)
end
end

person = Person.new
person.name ='John Due'
person.clear_name
puts person.name#=> nil

DRYを実現するのに便利そう

ActiveModel::AttributeMethods で重複をなくす - Qiita

🗽あとがき

CHANGELOGを集中して読んだり、いろんな人の意見を聞く機会っていなかなかなかので、本当にいい勉強になりました!
Sendagaya.rb #138 楽しかったです^^

🐹参考リンク

🖥 VULTRおすすめ

VULTR」はVPSサーバのサービスです。日本にリージョンがあり、最安は512MBで2.5ドル/月($0.004/時間)で借りることができます。4GBメモリでも月20ドルです。 最近はVULTRのヘビーユーザーになので、「ここ」から会員登録してもらえるとサービス開発が捗ります!

📚 おすすめの書籍


[8]ページ先頭

©2009-2025 Movatter.jp