Forum: Ruby passing a method as a paramter

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Sarah A. (Guest)
on 2009-03-02 11:50
I'm probably missing some basic Ruby syntax, but I'm relatively new to
Ruby and can't figure this out from the various references I've looked
at

I'd like to use this nifty test helper:

  # Calls creation_method with nil values for field_names and asserts
that
  # the resulting object was not saved and that errors were added for
that field.
  #
  #  assert_required_fields :create_article, :subject, :body, :author
  def assert_required_fields(creation_method, *field_names)
    field_names.each do |field|
      record = send(creation_method, field => nil)
      assert_equal false, record.valid?
      assert_not_nil record.errors.on(field)
    end
  end

However, I don't know how to pass the creation method. My basic test
would be:

  def test_should_create_user
    user = User.create(:email => "removed_email_address@domain.invalid", 
:lastname => "jones",
:password => "secret");
    assert user.valid?, "User was invalid:\n#{user.to_yaml}"
  end

I tried this for the failure case...
  def test_should_not_create_user_unless_default_fields
    assert_required_fields User::create, :email, :lastname, :password
  end

But that reports an error:
 1) Error:
test_should_not_create_user_unless_default_fields(UserTest):
TypeError: #<User uuid: nil, firstname: nil, lastname: nil, login: nil,
email: nil, ...> is not a symbol

Can someone advise me of the correct syntax?

Thanks,
Sarah
Leo (Guest)
on 2009-03-02 12:27
(Received via mailing list)
>     assert_required_fields User::create, :email, :lastname, :password

Instead of User::create, which doesn't return the method as it would
in some other languages but calls it right away, you could use either
one of:

User.method(:create)
lambda {|*args| User.create(*args)}

HTH
Sarah A. (Guest)
on 2009-03-02 12:32
Hi Leo,

This gave me the same error:
 assert_required_fields User.method(:create), :email, :lastname,
:password

I got a different error with this:
 assert_required_fields {|*args| User.create(*args)}, :email, :lastname,
:password

test/unit/user_test.rb:15: syntax error, unexpected ',', expecting kEND
    assert_required_fields {|*args| User.create(*args)}, :email,
:lastname, :password

Am I missing something?

Thanks,
Sarah
Michael F. (Guest)
on 2009-03-02 12:36
(Received via mailing list)
On Mon, Mar 2, 2009 at 6:49 PM, Sarah A. <removed_email_address@domain.invalid>
wrote:
>  #
>  #  assert_required_fields :create_article, :subject, :body, :author
>  def assert_required_fields(creation_method, *field_names)
>    field_names.each do |field|
>      record = send(creation_method, field => nil)
>      assert_equal false, record.valid?
>      assert_not_nil record.errors.on(field)
>    end
>  end

## Using blocks:

def assert_required_fields(*field_names, &block)
  field_names.each do |field_name|
    record = yield(field_name => nil)
    assert_equal(false, record.valid?)
    assert_not_nil(record.errors.on(field)
  end
end

# Usage:
assert_required_fields(:email, :lastname, :password){|field|
User::create(field) }


## Using the method itself

def assert_required_fields(method, *field_names)
  field_names.each do |field_name|
    record = method.call(field_name => nil)
    assert_equal(false, record.valid?)
    assert_not_nil(record.errors.on(field)
  end
end

# Usage
assert_required_fields(User.method(:create), :email, :lastname,
:password)


## Using send
def assert_required_fields(obj, method, *field_names)
  field_names.each do |field_name|
    record = obj.send(method, field_name => nil)
    assert_equal(false, record.valid?)
    assert_not_nil(record.errors.on(field)
  end
end

# Usage
assert_required_fields(User, :create, :email, :lastname, :password)


^ manveru
Sarah A. (Guest)
on 2009-03-02 12:45
Wow.  Awesome run through of various Ruby syntax options -- I think I'll
print that out and hang it on my wall.  Oddly none of those match the
original definition which uses send but has just a single
"creation_method" parameter...

>>  #  assert_required_fields :create_article, :subject, :body, :author
>>  def assert_required_fields(creation_method, *field_names)
>>    field_names.each do |field|
>>      record = send(creation_method, field => nil)
>>      assert_equal false, record.valid?
>>      assert_not_nil record.errors.on(field)
>>    end
>>  end

Any thoughts on how that could be called?

Thanks,
Sarah
Michael F. (Guest)
on 2009-03-02 12:56
(Received via mailing list)
On Mon, Mar 2, 2009 at 7:44 PM, Sarah A. <removed_email_address@domain.invalid>
wrote:
>>>      assert_not_nil record.errors.on(field)
>>>    end
>>>  end
>
> Any thoughts on how that could be called?

It's the second example, you cannot obtain an instance of Method like
you would do in Python or JavaScript by simply omitting the
parenthesis, you have to use the Object#method method.

All of these are equivalent:

User.create
User.create()
User.method(:create).call
User.send(:create)

^ manveru
Sarah A. (Guest)
on 2009-03-02 17:17
Michael F. wrote:
> On Mon, Mar 2, 2009 at 7:44 PM, Sarah A. <removed_email_address@domain.invalid>
> wrote:
>>>>      assert_not_nil record.errors.on(field)
>>>>    end
>>>>  end
>>
>> Any thoughts on how that could be called?
>
> It's the second example, you cannot obtain an instance of Method like
> you would do in Python or JavaScript by simply omitting the
> parenthesis, you have to use the Object#method method.
>
> All of these are equivalent:
>
> User.create
> User.create()
> User.method(:create).call
> User.send(:create)
>
> ^ manveru

I get the error: (ActiveRecord::Base).create> is not a symbol
calling:
  assert_required_fields User.method(:create), :create, :email,
:lastname, :password

the code in my library uses send, not call

Of course, I could just change the definition of assert_required_fields,
but since it is part of a plugin
(http://topfunky.net/svn/plugins/topfunky_power_too...
), I figure there must be some standard way to call it

Thanks for your help,
Sarah
Michael F. (Guest)
on 2009-03-02 18:30
(Received via mailing list)
On Tue, Mar 3, 2009 at 12:16 AM, Sarah A. <removed_email_address@domain.invalid>
wrote:
>> you would do in Python or JavaScript by simply omitting the
>
> I get the error: (ActiveRecord::Base).create> is not a symbol
> calling:
>  assert_required_fields User.method(:create), :create, :email,
> :lastname, :password

Sorry, with rails all bets on normally behaving ruby code are off.

^ manveru
Rick D. (Guest)
on 2009-03-02 20:07
(Received via mailing list)
On Mon, Mar 2, 2009 at 10:16 AM, Sarah A. <removed_email_address@domain.invalid>
wrote:

> > you would do in Python or JavaScript by simply omitting the
>
> http://topfunky.net/svn/plugins/topfunky_power_too...
> ), I figure there must be some standard way to call it


Yes, you need to pass a symbol, just as the error is trying to tell you:

 def test_should_not_create_user_unless_default_fields
   assert_required_fields :create, :email, :lastname, :password
 end

I'm assuming that this is in the unit test for the User model.


--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
Sarah A. (Guest)
on 2009-03-02 20:42
Rick Denatale wrote:
> Yes, you need to pass a symbol, just as the error is trying to tell you:
>
>  def test_should_not_create_user_unless_default_fields
>    assert_required_fields :create, :email, :lastname, :password
>  end
>
> I'm assuming that this is in the unit test for the User model.

So, how would it magically know to call create on User and not some
other class? as I might expect, I get this error:

  1) Error:
test_should_not_create_user_unless_default_fields(UserTest):
NoMethodError: undefined method `create' for #<UserTest:0x1e93a58>


Thanks,
Sarah:w
Rick D. (Guest)
on 2009-03-02 22:18
(Received via mailing list)
On Mon, Mar 2, 2009 at 1:41 PM, Sarah A. <removed_email_address@domain.invalid>
wrote:

> other class? as I might expect, I get this error:
>
>  1) Error:
> test_should_not_create_user_unless_default_fields(UserTest):
> NoMethodError: undefined method `create' for #<UserTest:0x1e93a58>
>

Okay, I'm curious where you found the topfunky power tools plugin.
There's
not much that google reveals about the usage.

However, it appears to come from a very early Peepcode screen cast on
Test
First Design (Peepcode #4 to be exact).  I did a quick look at the
screencast and it depends on having helper method called ceate in the
test
case.  So you should have something like:

 class UserTest < Test::Unit::TestCase
    #...
   def test_should_not_create_user_unless_default_fields
      assert_required_fields :create, :email, :lastname, :password
   end

   private
   def create(options={})
      User.create({
         :email => "removed_email_address@domain.invalid",
         :last_name => "jones",
         :password => "secret"
       }.merge(options)
     )
    end
 end

The create method creates a valid record, and the assert_required_fields
nils out each field asserted to be required, calls the create method
with
that field set to nil and ensures that the resulting record has an error
on
that field.

And given that helper method, the other test can be re-written as:

def test_should_create_user
   user = create
   assert user.valid?, "User was invalid:\n#{user.to_yaml}"
 end

Now, as I say, this plugin doesn't seem to be very popular based on a
google
search, and it's rather old.  There are probably more 'modern'
approaches to
testing required field validations these days using Test::Unit tests in
Rails, I'm not as up on that as I tend to use RSpec rather than
Test::Unit.

And since this really IS a Rails question, it probably would have gotten
a
better response, quicker if it had been submitted ot the ruby on rails
mailing list.
--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
Gary W. (Guest)
on 2009-03-02 22:23
(Received via mailing list)
On Mar 2, 2009, at 3:16 PM, Rick DeNatale wrote:
> Okay, I'm curious where you found the topfunky power tools plugin.
> There's
> not much that google reveals about the usage.
>
> However, it appears to come from a very early Peepcode screen cast
> on Test
> First Design (Peepcode #4 to be exact).  I did a quick look at the
> screencast and it depends on having helper method called ceate in
> the test
> case.  So you should have something like:

Wow. +10 to Rick for his google-ruby-rails-test-unit-mentoring-fu

Gary W.
Sarah A. (Guest)
on 2009-03-02 23:20
Rick Denatale wrote:
> Okay, I'm curious where you found the topfunky power tools plugin.
> There's not much that google reveals about the usage.

I'm just getting into TDD. I experimented with cucumber a bit and really
liked it, but I'm diving into an old codebase with lots of pre-existing
unit tests. I wanted to understand the basics, so (as you guessed) I
bought the peepcode tutorial.

> Now, as I say, this plugin doesn't seem to be very popular based on a
> google search, and it's rather old.  There are probably more 'modern'
> approaches to
> testing required field validations these days using Test::Unit tests in
> Rails, I'm not as up on that as I tend to use RSpec rather than
> Test::Unit.

If its wisdom is out of date, is there another resource you recommend?
Or is everyone just skipping unit tests these days in favor of the BDD
tools?

> And since this really IS a Rails question, it probably would have gotten
> a better response, quicker if it had been submitted ot the ruby on rails
> mailing list.

Yeah, I see that in retrospect -- seemed like a basic language question
at the time.  Thanks so much for digging in and letting me know the
scoop, which I clearly didn't fully understand from the screencast.   Of
course, now I know four ways to pass a method as a parameter, which is
fabulous.

Cheers,
Sarah
This topic is locked and can not be replied to.