passing a method as a paramter

Discussion in 'Ruby' started by Sarah Allen, Mar 2, 2009.

  1. Sarah Allen

    Sarah Allen Guest

    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 => "", :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-forum.com/.
     
    Sarah Allen, Mar 2, 2009
    #1
    1. Advertising

  2. Sarah Allen

    Leo Guest

    > =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
     
    Leo, Mar 2, 2009
    #2
    1. Advertising

  3. Sarah Allen

    Sarah Allen Guest

    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-forum.com/.
     
    Sarah Allen, Mar 2, 2009
    #3
  4. On Mon, Mar 2, 2009 at 6:49 PM, Sarah Allen <> 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
     
    Michael Fellinger, Mar 2, 2009
    #4
  5. Sarah Allen

    Sarah Allen Guest

    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-forum.com/.
     
    Sarah Allen, Mar 2, 2009
    #5
  6. On Mon, Mar 2, 2009 at 7:44 PM, Sarah Allen <> 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-forum.com/.
    >
    >
     
    Michael Fellinger, Mar 2, 2009
    #6
  7. Sarah Allen

    Sarah Allen Guest

    Michael Fellinger wrote:
    > On Mon, Mar 2, 2009 at 7:44 PM, Sarah Allen <>
    > 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_helper.rb
    ), I figure there must be some standard way to call it

    Thanks for your help,
    Sarah
    --
    Posted via http://www.ruby-forum.com/.
     
    Sarah Allen, Mar 2, 2009
    #7
  8. On Tue, Mar 3, 2009 at 12:16 AM, Sarah Allen <> wrote:
    > Michael Fellinger wrote:
    >> On Mon, Mar 2, 2009 at 7:44 PM, Sarah Allen <>
    >> 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/topfunky/test_h=

    elper.rb
    > ), I figure there must be some standard way to call it
    >
    > Thanks for your help,
    > Sarah
     
    Michael Fellinger, Mar 2, 2009
    #8
  9. [Note: parts of this message were removed to make it a legal post.]

    On Mon, Mar 2, 2009 at 10:16 AM, Sarah Allen <> wrote:

    > Michael Fellinger wrote:
    > > On Mon, Mar 2, 2009 at 7:44 PM, Sarah Allen <>
    > > 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_helper.rb
    > ), 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
     
    Rick DeNatale, Mar 2, 2009
    #9
  10. Sarah Allen

    Sarah Allen Guest

    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-forum.com/.
     
    Sarah Allen, Mar 2, 2009
    #10
  11. [Note: parts of this message were removed to make it a legal post.]

    On Mon, Mar 2, 2009 at 1:41 PM, Sarah Allen <> 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 => "",
    :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
     
    Rick DeNatale, Mar 2, 2009
    #11
  12. Sarah Allen

    Gary Wright Guest

    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 Wright
     
    Gary Wright, Mar 2, 2009
    #12
  13. Sarah Allen

    Sarah Allen Guest

    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
    --
    Posted via http://www.ruby-forum.com/.
     
    Sarah Allen, Mar 2, 2009
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Randy

    Grabbing paramter in the URL

    Randy, Feb 8, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    373
    Eliyahu Goldin
    Feb 8, 2005
  2. tshad
    Replies:
    5
    Views:
    564
    Steve C. Orr [MVP, MCSD]
    May 17, 2005
  3. Islamegy®

    SQL Output Paramter problem

    Islamegy®, Apr 16, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    2,234
  4. Replies:
    2
    Views:
    340
  5. Replies:
    7
    Views:
    990
    Bo Persson
    Oct 30, 2006
Loading...

Share This Page