Forum: RSpec OT: Implementation Question

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.
James B. (Guest)
on 2008-12-19 17:50
I have asked about this issue on several different mailing lists and
have had no response. If anyone here can offer some advice then I would
be much obliged.

I have a feature that essentially says:

  Given I have a user "myuser"
  When I fill in "User Name" with "MyUser"
    And I press "Login"
  Then I should find a user "myuser"
    And I should be logged in

The steps definitions for this are all quite conventional and at the
moment "Then I should find the user "myuser"" is failing, as expected.

My question is: What is best practice with respect to normalizing form
input data?  My feeling is that this sort of thing belongs in the model
but I cannot see a way to get this to work.  In short, how to implement
this feature?

I have extended String with a method called hll_keycase which preforms
the desired normalization.  The setter for Users.username is overridden
in the model and the stored values in the database are all properly
normalized.  But, it seems to me at the moment that the only place to
normalize form input data for the SELECT required to determine if the
username exists or not is either in the form or in the controller.  Is
that the case?

This has to be a recurring issue for data input forms and yet I can find
very few resources on the web that address this issue at all, and those
are often terse to the point of unintelligible.

Not exactly a test issue but I really could use some guidance with this
as whatever technique I finally adopt will pervade the entire project.
Pat M. (Guest)
on 2008-12-19 19:14
(Received via mailing list)
On Fri, Dec 19, 2008 at 7:50 AM, James B. <removed_email_address@domain.invalid>
wrote:
>    And I should be logged in
> the desired normalization.  The setter for Users.username is overridden
> Not exactly a test issue but I really could use some guidance with this
> as whatever technique I finally adopt will pervade the entire project.
> --
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> rspec-users mailing list
> removed_email_address@domain.invalid
> http://rubyforge.org/mailman/listinfo/rspec-users
>

There are a couple things you can do.  First, if you're using webrat
and you've labeled fields exactly as you have them in that feature,
you can offload the work to webrat:

When /^I fill in "(.*)" with "(.*)$/" do |field, value|
  fills_in field, :with => value
end

Or you can do some kind of transformation:

prop_map = {"User name" => :username}
When /^I fill in "(.*)" with "(.*)$/" do |prop_name, value|
  fills_in prop_map[prop_name], :with => value
end

or if you're accessing the model directly
  @user.send(prop_map[prop_name] + '=', value)

Looking back at the full email now though I think you're asking about
how to just convert MyUser to myuser?

class User < ActiveRecord::Base
  def username=(new_username)
    self[:username] = new_username.downcase
  end
end

or non-AR

class User
  attr_reader :username
  def username=(new_username)
    @username = new_username.downcase
  end
end

Is that what you're looking for?

Pat
Andrew P. (Guest)
on 2008-12-19 19:20
(Received via mailing list)
You can use read_attribute and write_attribute in models to do this sort
of
thing - though I'm not really clear exactly what it is you're trying to
do.
I don't think normalising is quite the right term here.

Anyhow I think you're saying that you have an attribute whose storage
format
is different from its presenation format. To deal with this you can
override
the attribute accessor in the model e.g. you present product_names in a
capitlalized form even if they are stored lower case

  # Always titleize product names when showing
  def name
    read_attribute(:name).titleize
  end

Another example, you're seriously old school and believe only capital
letters should be in databases

    def name=(name)
      write_attribute(:name, name.upcase)
    end

Another technique would be to create a virtual attribute, so you can
have
two representations of the same value. For example a price and a
currency_price where both refer to the same attribute but one deals with
an
integer and the other deals with nicely formatted prices.

HTH


2008/12/19 James B. <removed_email_address@domain.invalid>
James B. (Guest)
on 2008-12-19 19:25
Thanks for the responses.  For some reason they showed up in the digest
email and yet have still not made it to the RSpec forum at
Ruby_forum.com.

I have been trying variants of these suggestions, indeed my very first
approach was:

 def username
   @username.hll_keycase
 end

However, I am working with authlogic and the UserSession Class of that
gem throws an error complaining about a missing username= method when I
provide the username method.  When I provide username= then it complains
about a missing password= method.  At the time that I asked my question
here I was trying to determine if there was something fundamentally
wrong with my approach.

Evidently this is not the case so I have now contacted the author
directly since these issues are definitely outside the scope of this
mailing list.

Many thanks for the advice.

Regards,
James B. (Guest)
on 2008-12-19 19:37
Andrew P. wrote:
> You can use read_attribute and write_attribute in models to do this sort
> of thing - though I'm not really clear exactly what it is you're trying
> to  do.
> I don't think normalising is quite the right term here.

Ahh.  Well when I was working with sendmail email addresses the practice
was called munging.  But I believe that text normalization is defined as
the practice of modifying any arbitrary text to a standard
representation.  In this case user logins are all stored as lowercase,
whitespace trimmed, left-shifted, single spaced token delimited,
phrases.  So that MYUSER == MyUser == myuser.  It avoids much
unhappiness with users.
This topic is locked and can not be replied to.