[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

passing a method as a paramter

Sarah Allen

3/2/2009 9:50:00 AM

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 => "fred@foo.com", :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
--
Posted via http://www.ruby-....

12 Answers

-lim-

3/2/2009 10:25:00 AM

0

> =A0 =A0 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 Allen

3/2/2009 10:34:00 AM

0

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
--
Posted via http://www.ruby-....

Michael Fellinger

3/2/2009 10:34:00 AM

0

On Mon, Mar 2, 2009 at 6:49 PM, Sarah Allen <sarah@ultrasaurus.com> wrote:
> 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:
>
> =C2=A0# Calls creation_method with nil values for field_names and asserts
> that
> =C2=A0# the resulting object was not saved and that errors were added for
> that field.
> =C2=A0#
> =C2=A0# =C2=A0assert_required_fields :create_article, :subject, :body, :a=
uthor
> =C2=A0def assert_required_fields(creation_method, *field_names)
> =C2=A0 =C2=A0field_names.each do |field|
> =C2=A0 =C2=A0 =C2=A0record =3D send(creation_method, field =3D> nil)
> =C2=A0 =C2=A0 =C2=A0assert_equal false, record.valid?
> =C2=A0 =C2=A0 =C2=A0assert_not_nil record.errors.on(field)
> =C2=A0 =C2=A0end
> =C2=A0end

## Using blocks:

def assert_required_fields(*field_names, &block)
field_names.each do |field_name|
record =3D yield(field_name =3D> 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 =3D method.call(field_name =3D> 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 =3D obj.send(method, field_name =3D> 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 Allen

3/2/2009 10:44:00 AM

0

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
--
Posted via http://www.ruby-....

Michael Fellinger

3/2/2009 10:55:00 AM

0

On Mon, Mar 2, 2009 at 7:44 PM, Sarah Allen <sarah@ultrasaurus.com> wrote:
> Wow. =C2=A0Awesome run through of various Ruby syntax options -- I think =
I'll
> print that out and hang it on my wall. =C2=A0Oddly none of those match th=
e
> original definition which uses send but has just a single
> "creation_method" parameter...
>
>>> =C2=A0# =C2=A0assert_required_fields :create_article, :subject, :body, =
:author
>>> =C2=A0def assert_required_fields(creation_method, *field_names)
>>> =C2=A0 =C2=A0field_names.each do |field|
>>> =C2=A0 =C2=A0 =C2=A0record =3D send(creation_method, field =3D> nil)
>>> =C2=A0 =C2=A0 =C2=A0assert_equal false, record.valid?
>>> =C2=A0 =C2=A0 =C2=A0assert_not_nil record.errors.on(field)
>>> =C2=A0 =C2=A0end
>>> =C2=A0end
>
> 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

> Thanks,
> Sarah
> --
> Posted via http://www.ruby-....
>
>

Sarah Allen

3/2/2009 3:17:00 PM

0

Michael Fellinger wrote:
> On Mon, Mar 2, 2009 at 7:44 PM, Sarah Allen <sarah@ultrasaurus.com>
> 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_tools/lib/topfunky/test...
), I figure there must be some standard way to call it

Thanks for your help,
Sarah
--
Posted via http://www.ruby-....

Michael Fellinger

3/2/2009 4:29:00 PM

0

On Tue, Mar 3, 2009 at 12:16 AM, Sarah Allen <sarah@ultrasaurus.com> wrote:
> Michael Fellinger wrote:
>> On Mon, Mar 2, 2009 at 7:44 PM, Sarah Allen <sarah@ultrasaurus.com>
>> wrote:
>>>>> =C2=A0 =C2=A0 =C2=A0assert_not_nil record.errors.on(field)
>>>>> =C2=A0 =C2=A0end
>>>>> =C2=A0end
>>>
>>> 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:
> =C2=A0assert_required_fields User.method(:create), :create, :email,
> :lastname, :password

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

^ manveru

> 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_tools/lib/topfun...
elper.rb
> ), I figure there must be some standard way to call it
>
> Thanks for your help,
> Sarah

Rick DeNatale

3/2/2009 6:05:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

On Mon, Mar 2, 2009 at 10:16 AM, Sarah Allen <sarah@ultrasaurus.com> wrote:

> Michael Fellinger wrote:
> > On Mon, Mar 2, 2009 at 7:44 PM, Sarah Allen <sarah@ultrasaurus.com>
> > 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_tools/lib/topfunky/test...
> ), 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.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

Sarah Allen

3/2/2009 6:42:00 PM

0

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

--
Posted via http://www.ruby-....

Rick DeNatale

3/2/2009 8:17:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

On Mon, Mar 2, 2009 at 1:41 PM, Sarah Allen <sarah@ultrasaurus.com> wrote:

> 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>
>

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 => "fred@foo.com",
: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.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...