2021/5/9 Rails 6.1 の変更点で気になったところ
ActiveModel
*_previously_changed? accepts :from and :to keyword arguments like *_changed?.
code:ruby
topic.update!(status: :archived)
topic.status_previously_changed?(from: "active", to: "archived")
# => true
変更を明示的に確認出来るようになった
Add *_previously_was attribute methods when dirty tracking. Example:
code:ruby
pirate.update(catchphrase: "Ahoy!")
pirate.catchphrase_previously_was # => "Thar She Blows!"
似たような感じで元の値が取れるようになった
The ActiveModel’s errors collection is now an array of these Error objects, instead of messages/details hash.
HashじゃなくなったらしいHashを期待していたらハマりそう
ActiveRecord
Add support for rails console --sandbox for multiple database applications.
sandboxで複数DBへのコネクションがサポートされた
--sandbox トランザクション張るので本番で使うの怖い気がするのだけれどみんなどうしてるのかな
Build predicate conditions with objects that delegate #id and primary key: code:ruby
class AdminAuthor
delegate_missing_to :@author
def initialize(author)
@author = author
end
end
Post.where(author: AdminAuthor.new(author))
delegate_missing_to で primary key が電波するようになったので上のようなコードが書けるようになった
delegate_missing_to 知らなかった...めちゃべんり
MySQL: Uniqueness validator now respects default database collation, no longer enforce case sensitive comparison by default.
validates :hoge, uniquness: true が独自判じゃなくなり、MySQLの設定に従うように
ケースセンシティブが強制されていたのがなくなる
Remove deprecated ActiveRecord::Base#update_attributes and ActiveRecord::Base#update_attributes!.
なくなっちゃった
relation.create does no longer leak scope to class level querying methods in initialization block and callbacks.
code:ruby
User.where(name: "John").create do |john|
User.find_by(name: "David") # => #<User name: "David", ...> end
Named scope chain does no longer leak scope to class level querying methods.
code:ruby
class User < ActiveRecord::Base
scope :david, -> { User.where(name: "David") }
end
こういうのがあって
code:ruby
User.where(name: "John").david
こうしたときに条件に John を含まなくなる
これはハマる人はハマりそう
where.not now generates NAND predicates instead of NOR.
code:ruby
User.where.not(name: "Jon", role: "admin")
# Before: SELECT * FROM users WHERE name != 'Jon' AND role != 'admin'
# After: SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
Remove deprecated support for using unsafe raw SQL in ActiveRecord::Relation methods.
これはやばい。使うなって話だけれどレガシーなシステムだと存在し得る
Add values_at method.
code:ruby
topic = Topic.first
topic.values_at(:title, :author_name)
Allow associations supporting the dependent: key to take dependent: :destroy_async.
:destroy_async will enqueue a job to destroy associated records in the background.
おー、これはべんりそう
Associationの削除を非同期で出来るようになった
大量の記事があるブログを消すなどが気軽に出来るようになる
Allow where references association names as joined table name aliases.
code:ruby
class Comment < ActiveRecord::Base
has_many :children, class_name: "Comment", foreign_key: :parent_id
end
# ... FROM comments LEFT OUTER JOIN comments children ON ... WHERE children.label = 1
Comment.includes(:children).where("children.label": "child")
テーブル名じゃなくて関係の名前で条件を書けるようになって地味に便利
Allow default to be configured for Enum.
code:ruby
class Book < ActiveRecord::Base
end
Book.new.status # => "published"
デフォルト値が指定出来るようになった
Added the setting ActiveRecord::Base.immutable_strings_by_default, which allows you to specify that all string columns should be frozen unless otherwise specified. This will reduce memory pressure for applications which do not generally mutate string properties of Active Record objects.
よき
Support relation.and for intersection as Set theory.
code:ruby
david_and_mary.merge(mary_and_bob) # => mary, bob david_and_mary.and(mary_and_bob) # => mary Add support for finding records based on signed ids, which are tamper-proof, verified ids that can be set to expire and scoped with a purpose. This is particularly useful for things like password reset or email verification, where you want the bearer of the signed id to be able to interact with the underlying record, but usually only within a certain time period.
code:ruby
signed_id = User.first.signed_id expires_in: 15.minutes, purpose: :password_reset
User.find_signed signed_id # => nil, since the purpose does not match
travel 16.minutes
User.find_signed signed_id, purpose: :password_reset # => nil, since the signed id has expired
travel_back
User.find_signed signed_id, purpose: :password_reset # => User.first
User.find_signed! "bad data" # => ActiveSupport::MessageVerifier::InvalidSignature
これはべんりそう。
Add support for if_not_exists option for adding index.
The add_index method respects if_not_exists option. If it is set to true index won't be added.
code:ruby
add_index :users, :account_id, if_not_exists: true
インデックスがなければ作るということが出来るようになった