提交 3fe83d1d 编写于 作者: A Abhay Nikam 提交者: Ryuta Kamizono

Adds touch option to has_one association

上级 aa5e6b59
* Add `touch` option to `has_one` association.
*Abhay Nikam*
* Deprecate `where.not` working as NOR and will be changed to NAND in Rails 6.1.
```ruby
......
......@@ -7,7 +7,7 @@ def self.macro
end
def self.valid_options(options)
valid = super + [:as]
valid = super + [:as, :touch]
valid += [:through, :source, :source_type] if options[:through]
valid
end
......@@ -16,6 +16,11 @@ def self.valid_dependent_options
[:destroy, :delete, :nullify, :restrict_with_error, :restrict_with_exception]
end
def self.define_callbacks(model, reflection)
super
add_touch_callbacks(model, reflection) if reflection.options[:touch]
end
def self.add_destroy_callbacks(model, reflection)
super unless reflection.options[:through]
end
......@@ -27,6 +32,33 @@ def self.define_validations(model, reflection)
end
end
private_class_method :macro, :valid_options, :valid_dependent_options, :add_destroy_callbacks, :define_validations
def self.touch_record(o, name, touch)
record = o.send name
return unless record && record.persisted?
if touch != true
record.touch(touch)
else
record.touch
end
end
def self.add_touch_callbacks(model, reflection)
name = reflection.name
touch = reflection.options[:touch]
callback = lambda { |record|
HasOne.touch_record(record, name, touch)
}
model.after_create callback, if: :saved_changes?
model.after_update callback, if: :saved_changes?
model.after_destroy callback
model.after_touch callback
end
private_class_method :macro, :valid_options, :valid_dependent_options, :add_destroy_callbacks,
:define_callbacks, :define_validations, :add_touch_callbacks
end
end
......@@ -15,10 +15,13 @@
require "models/drink_designer"
require "models/chef"
require "models/department"
require "models/club"
require "models/membership"
class HasOneAssociationsTest < ActiveRecord::TestCase
self.use_transactional_tests = false unless supports_savepoints?
fixtures :accounts, :companies, :developers, :projects, :developers_projects, :ships, :pirates, :authors, :author_addresses
fixtures :accounts, :companies, :developers, :projects, :developers_projects,
:ships, :pirates, :authors, :author_addresses, :memberships, :clubs
def setup
Account.destroyed_account_ids.clear
......@@ -706,6 +709,40 @@ def test_with_polymorphic_has_one_with_custom_columns_name
end
end
def test_has_one_with_touch_option_on_create
assert_queries(3) {
Club.create(name: "1000 Oaks", membership_attributes: { favourite: true })
}
end
def test_has_one_with_touch_option_on_update
new_club = Club.create(name: "1000 Oaks")
new_club.create_membership
assert_queries(2) { new_club.update(name: "Effingut") }
end
def test_has_one_with_touch_option_on_touch
new_club = Club.create(name: "1000 Oaks")
new_club.create_membership
assert_queries(1) { new_club.touch }
end
def test_has_one_with_touch_option_on_destroy
new_club = Club.create(name: "1000 Oaks")
new_club.create_membership
assert_queries(2) { new_club.destroy }
end
def test_has_one_with_touch_option_on_empty_update
new_club = Club.create(name: "1000 Oaks")
new_club.create_membership
assert_no_queries { new_club.save }
end
class SpecialBook < ActiveRecord::Base
self.table_name = "books"
belongs_to :author, class_name: "SpecialAuthor"
......
# frozen_string_literal: true
class Club < ActiveRecord::Base
has_one :membership
has_one :membership, touch: true
has_many :memberships, inverse_of: false
has_many :members, through: :memberships
has_one :sponsor
......@@ -12,6 +12,8 @@ class Club < ActiveRecord::Base
scope :general, -> { left_joins(:category).where(categories: { name: "General" }).unscope(:limit) }
accepts_nested_attributes_for :membership
private
def private_method
......
......@@ -524,6 +524,8 @@
t.integer :club_id, :member_id
t.boolean :favourite, default: false
t.integer :type
t.datetime :created_at
t.datetime :updated_at
end
create_table :member_types, force: true do |t|
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册