June 10, 2019
This blog is part of our Rails 6 series.
Rails 6 adds :private
option to
delegate
method. After this addition, we can delegate methods in the private scope.
Let's checkout how it works.
Let's create two models named as Address
and Order
. Let's also delegate
validate_state
method in Order
to Address
.
class Address < ApplicationRecord
validates :first_name, :last_name, :state, presence: true
DELIVERABLE_STATES = ['New York']
def validate_state
unless DELIVERABLE_STATES.include?(state)
errors.add(:state, :invalid)
end
end
end
class Order < ApplicationRecord
belongs_to :address
delegate :validate_state, to: :address
end
>> Order.first
SELECT "orders".* FROM "orders"
ORDER BY "orders"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> #<Order id: 1, amount: 0.1e2, address_id: 1, created_at: "2019-03-21 10:02:58", updated_at: "2019-03-21 10:17:44">
>> Address.first
SELECT "addresses".* FROM "addresses"
ORDER BY "addresses"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> #<Address id: 1, first_name: "Amit", last_name: "Choudhary", state: "California", created_at: "2019-03-21 10:02:47", updated_at: "2019-03-21 10:02:47">
>> Order.first.validate_state
SELECT "orders".* FROM "orders"
ORDER BY "orders"."id" ASC LIMIT $1 [["LIMIT", 1]]
SELECT "addresses".* FROM "addresses"
WHERE "addresses"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
=> ["is invalid"]
Now, let's add private: true
to the delegation.
class Order < ApplicationRecord
belongs_to :address
delegate :validate_state, to: :address, private: true
end
>> Order.first.validate_state
SELECT "orders".* FROM "orders"
ORDER BY "orders"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> Traceback (most recent call last):
1: from (irb):7
NoMethodError (private method 'validate_state' called for #<Order:0x00007fb9d72fc1f8>
Did you mean? validate)
As we can see, Rails now raises an exception of private method called if
private
option is set with delegate
method.
Here is the relevant pull request.
If this blog was helpful, check out our full blog archive.