Permalink
Browse files

We tenderized the wrong method! Object#try already had the yield opti…

…on, just needed some tenderloving instance_eval to fit the bill
  • Loading branch information...
dhh committed Aug 29, 2014
1 parent 39691ba commit 5e51bdda59c9ba8e5faf86294e3e431bd45f1830
View
@@ -1,15 +1,10 @@
* Added yield to Object#presence, so you can do this:
* Added instance_eval version to Object#try, so you can do this:
project.account.owner.presence { name.first } || 'Nobody'
person.try { name.first }
instead of calling twice (which may incur double SQL calls):
instead of:
project.account.owner ? project.account.owner.name.first || 'Nobody'
or assigning to local variable:
owner = project.account.owner
owner ? owner.name.first || 'Nobody'
person.try { |person| person.name.first }
*DHH*
@@ -39,21 +39,9 @@ def present?
#
# region = params[:state].presence || params[:country].presence || 'US'
#
# You can also use this with a block that will be yielded if the object is present
# and the result of that block will then be returned. The block itself is run against
# the instance you're running #presence on (using instance_eval)
#
# project.account.owner.presence { name.first } || 'Nobody'
#
# @return [Object]
def presence(&block)
if present?
if block_given?
instance_eval(&block)
else
self
end
end
def presence
self if present?
end
end
@@ -33,14 +33,23 @@ class Object
# ...
# end
#
# You can also call try with a block without accepting an argument, and the block
# will be instance_eval'ed instead:
#
# @person.try { upcase.truncate(50) }
#
# Please also note that +try+ is defined on +Object+, therefore it won't work
# with instances of classes that do not have +Object+ among their ancestors,
# like direct subclasses of +BasicObject+. For example, using +try+ with
# +SimpleDelegator+ will delegate +try+ to the target instead of calling it on
# delegator itself.
def try(*a, &b)
if a.empty? && block_given?
yield self
if b.arity.zero?

This comment has been minimized.

Show comment
Hide comment
@aripollak

aripollak Oct 22, 2014

Contributor

@dhh should this also be added to #try! since the doc for that says it is mostly the same as #try?

@aripollak

aripollak Oct 22, 2014

Contributor

@dhh should this also be added to #try! since the doc for that says it is mostly the same as #try?

This comment has been minimized.

Show comment
Hide comment
@dhh

dhh Oct 22, 2014

Member

Yes, please do with PR 👍

@dhh

dhh Oct 22, 2014

Member

Yes, please do with PR 👍

instance_eval(&b)
else
yield self
end
else
public_send(*a, &b) if respond_to?(a.first)
end
@@ -28,14 +28,4 @@ def test_present
BLANK.each { |v| assert_equal false, v.present?, "#{v.inspect} should not be present" }
NOT.each { |v| assert_equal true, v.present?, "#{v.inspect} should be present" }
end
def test_presence
BLANK.each { |v| assert_equal nil, v.presence, "#{v.inspect}.presence should return nil" }
NOT.each { |v| assert_equal v, v.presence, "#{v.inspect}.presence should return self" }
end

This comment has been minimized.

Show comment
Hide comment
@chancancode

chancancode Aug 30, 2014

Member

@dhh Don't think you intend to rm these, so I brought it back c67c5e6

If that's incorrect please revert

@chancancode

chancancode Aug 30, 2014

Member

@dhh Don't think you intend to rm these, so I brought it back c67c5e6

If that's incorrect please revert

This comment has been minimized.

Show comment
Hide comment
@dhh

dhh Aug 30, 2014

Member
@dhh

dhh via email Aug 30, 2014

Member
def test_presence_with_a_block
assert_equal "THIS WAS TENDERLOVE'S IDEA", "this was tenderlove's idea".presence { upcase } || "Nobody"
assert_equal "Nobody", nil.presence { upcase } || "Nobody"
end
end
@@ -65,6 +65,10 @@ def test_try_only_block_nil
assert_equal false, ran
end
def test_try_with_instance_eval_block
assert_equal @string.reverse, @string.try { reverse }
end
def test_try_with_private_method_bang
klass = Class.new do
private

0 comments on commit 5e51bdd

Please sign in to comment.