OT: Implementation Question


#1

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.


#2

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


#3

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,


#4

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


#5

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.