Rails 2.0: How to enforce upcase in new & edit methods

Hi,

I generated a Ruby 2.0 app and created a Portfolio model with two data
items:
symbol:string
name:string.

The default ACID functions work fine. But I want to add constraints
one the New and Edit functions for symbol:
1. Can't be blank
2. Must be uppercase
3. May not duplicate an existing symbol

ADWR shows me how to do this with Rails 1.x validation. Is there any
documentation that shows how this changed in Rails 2.0?

Thanks in Advance,
Richad

Here's my controller after I added my old-style validations:

class Portfolio < ActiveRecord::Base
  def before_validation_on_create
    self.symbol == self.symbol.upcase
  end
  validates_presence_of :symbol, "can't be blank!"
  validates_length_of :symbol, :maximum=>6, "may not exceed 5
characters!"
end

My app bombed in the index method of the portfolios_controller.rb. I
thought the first three lines might be malformed, but commenting them
out did no better. Commenting them all, however, the app worked fine.

So, as I expected, Rails 2.0.2 wants something different. I've
scoured the Web but found no answer, so far. Any suggestions would be
appreciated.

Regards,
Richard

RichardOnRails wrote:

Hi,

I generated a Ruby 2.0 app and created a Portfolio model with two data
items:
symbol:string
name:string.

The default ACID functions work fine. But I want to add constraints
one the New and Edit functions for symbol:
1. Can't be blank
2. Must be uppercase
3. May not duplicate an existing symbol

ADWR shows me how to do this with Rails 1.x validation. Is there any
documentation that shows how this changed in Rails 2.0?

Thanks in Advance,
Richad

Hi Richad,

You can use validates_format_of and a regex to make sure it's all
uppercase. But instead of raising an error if it's not, why can't you
just convert it to uppercase automatically? If you are using a
case-sensitive database, you can use the before_validation callback.
That way your validates_uniqueness_of will work properly. Otherwise, you
could do it in the before_save callback.

I am working on a project right now in which the client wants all user
entered data to be uppercase, so I wrote a simple method that I can call
from any controller

def upcase_data(data_hash, exclusions = [])
  exclusions += [:controller, :action, :return_to_controller,
:return_to_action]
  data_hash.each_pair do |key, value|
    data_hash[key] = value.upcase if value.class.name == 'String' &&
!exclusions.include?(key.to_sym)
  end
end

I never want to upcase controller or action, and then there are some
others that I don't want to touch, which is why I have exclusions. I
call it like

upcase_data(params[:person], [:email, :sms_domain, :time_zone,
:date_format, :time_format])

at the beginning of save methods. It works well for me.

Peace,
Phillip

RichardOnRails wrote:

Here's my controller after I added my old-style validations:

class Portfolio < ActiveRecord::Base
  def before_validation_on_create
    self.symbol == self.symbol.upcase
  end
  validates_presence_of :symbol, "can't be blank!"
  validates_length_of :symbol, :maximum=>6, "may not exceed 5
characters!"
end

Hi Richard,

Without seeing the error, I'd say that you need to specify the :message
hash key.

validates_presence_of :symbol, :message => "can't be blank!"
validates_length_of :symbol, :maximum => 6, :message => "may not exceed
5 characters!"

[Note that your :maximum and :message don't agree in the
validates_length_of.]

It is my understanding that when you provide a list of "things" (no hash
pairs) to validates_presence_of, they are all assumed to be field/method
names, so you can do something like

validates_presence_of :first_name, :last_name, :age, :gender

so "can't be blank" is probably being interpreted as a field/method name
and I'm going to guess that the error you're getting says something
about an undefined method.

What is the error?

Peace,
Phillip

Quick question... why must the data be in upper case?

From a user-interaction perspective, that's pretty lame. This
shouldn't be a requirement forced on the end-user of the application.

You might consider using the ActiveRecord callbacks to uppercase the
data that you want to store that way.

before_save :uppercase_data

def uppercase_data
  self.attrname.upcase!
end

You could iterate through your attributes and do this in the model and
not force people to do this themselves.

Robby

Hi Phillip,

Thank you for your excellent advice. I now have 2 of my 3 wishes
granted :slight_smile: I've got the following working perfectly:

class Portfolio < ActiveRecord::Base
  validates_presence_of :symbol
  validates_length_of :symbol, :maximum=>5, :message=>"exceeds %d
characters"
end

But I couldn't follow your automatic upcase: it's too sophisticated
for this newbie. So I tried

class Portfolio < ActiveRecord::Base
   def before_validation_on_create
                params[:symbol] == params[:symbol].upcase
        end

  validates_presence_of :symbol
  validates_length_of :symbol, :maximum=>5, :message=>"exceeds %d
characters"
end

but that crashed in portfolios_controller.rb.

Can you think of f a hopefully simple fix for my error?

Again, thanks for your wonderful help.

Best wishes,
Richard

Hi Robby,

That's perfect! Thank you very much.

Best wishes,
Richard

Hi again Phillip,

I just saw Robby's advice and it solves my final problem perfectly.

Thanks again for your wonderful help.

Best wishes,
Richard

RichardOnRails wrote:

Hi again Phillip,

I just saw Robby's advice and it solves my final problem perfectly.

Thanks again for your wonderful help.

Best wishes,
Richard

On Jun 23, 12:06 am, Phillip Koebbe <rails-mailing-l...@andreas-s.net>

Super!

But for the sake of being thorough, where you had

def before_validation_on_create
    params[:symbol] == params[:symbol].upcase
end

You would want

def before_validation_on_create
    self.symbol = self.symbol.upcase
end

Peace,
Phillip

Hi again Phillip,

Thank you VERY MUCH for hanging in there with me. I've tested "my
perfect model" thoroughly and it works perfectly. (I do have a one
improvement I want in my regex, but that's for a different day.)

Aside from getting my initial Rails project working, I learned a lot
about programming in the Rails environment. That's probably the most
important gift you and the other respondents have given me.

Best wishes,
Richard

class Portfolio < ActiveRecord::Base
  def before_validation
    # Remove leading/trailing blanks, if any
    self.symbol =~ /^(\s*)([A-Za-z0-9]+)(\s*)$/
    self.symbol = $2 if $1 or $3
    # Upshift before following validations are applied
    self.symbol.upcase!
  end

  validates_presence_of :symbol
  validates_format_of :symbol, :with => /^[a-zA-Z\d]+$/, :on
=> :create,
    :message => "(Character other than letter or digit found, e.g a
blank)"
  validates_length_of :symbol, :maximum=>5, :message=>"exceeds %d
characters"
  validates_uniqueness_of :symbol
end