Dave says:

I added the following line to the file product.rb in the app/models directory

validates_length_of :title, :minimum => 10

To find the syntax, I looked up the method on http://api.rubyonrails.com You may add an alert message:

validates_length_of :title, :minimum => 10, :message => "at least 10 characters" 

Ana says:

You can also use an already implemented error message by using :too_short instead of message. So you can also write:

validates_length_of :title, :minimum => 10, :too_short

Florent says:

validates_length_of :title, :minimum => 10, :too_short
did not work for me (with Rails 2.3.2), I got in my browser the error /depot/app/models/product.rb:5: syntax error, unexpected '\n', expecting tASSOC I had to specify a message for :too_short:

validates_length_of :title, :minimum => 10, :too_short => "must have at least %d characters" 

Max says:

I’m not sure about the old version of Rails, but you can completely bypass the ”:too_short” part, leaving:

validates_length_of :title, :minimum => 10

Claudio says:

In Rails 3 you can now use:

validates :title, :length => { :minimum => 10 }

Dominik says:

At first I tried:

validates :title, :length => {:greater_than_or_equal_to => 10}
but it didn’t work. This one works:
validates :title, :length => {:minimum => 10}

André says:

Added validation to class Product:

validates :title, :uniqueness => true, :length => {
    :minimum => 10,
    :message => 'must be at least ten characters long.'

Added validation test:

test "product title must be at least ten characters long" do
    product = products(:ruby)
    assert product.valid?, "product title shouldn't be invalid" 

    product.title = product.title.first(9)
    assert product.invalid?, "product title shouldn't be valid" 
Is this the right approach? Thanks.

Andrew says:

Added almost the same validation to class Product as André

validates :title, :uniqueness => true, :length => {:minimum => 10}

But I used the following validation test instead:

  test "title is at least 10 characters long" do
    product = Product.new(:price        =>  9.99,
                          :description  =>  "yyy",
                          :image_url    =>  "zzz.jpg")

    product.title = "This is an acceptable title" 
    assert product.valid?

    product.title = "So is this" 
    assert product.valid?

    product.title = "not this" 
    assert product.invalid?
    assert_equal "is too short (minimum is 10 characters)", 
      product.errors[:title].join('; ')

I like the succinctness of André’s unit test.

Doc says:

A minor tweak to the model validation to provide message consistency in the event the length validation is changed.

  validates :title, :uniqueness => true, :length => {
    :minimum => minimum = 10,
    :message => "must be at least #{minimum} characters." 

Charles says:

Combining Doc’s and Ana’s solution works.

  validates :title, :uniqueness => true, :length => { 
    :minimum => 10, 
    :message => :too_short 

(You’ll get a message that reads “Title is too short (minimum is 10 characters)”.)

Peter says:

I half-like André’s approach: product.title = product.title.first(9)

The problem with this is that the value of the invalid length is hard-coded here in the test method, and not derived from the value stored elsewhere in the validation rule. Two places to maintain the same value (well, n_ and _n-1).

As a noob, I experimented with something like (Product.validates_length_of.minimum – 1), but that didn’t fly. Does anyone here know the syntax to achieve this?

DaveB says:

Would the following be a good unit test for this addition given you used the approach provided by Charles?

  test "product is not valid without a title of at least 10 characters" do
    product = Product.new(:title => "blah",
                          :description => "yyy",
                          :price => 1,
                          :image_url => "fred.gif")

    assert product.invalid?
    assert_equal I18n.translate('errors.messages.too_short', 
                                :count => 10), product.errors[:title].join('; ')

    product.title = "This is longer than 10 characters" 
    assert product.valid?

Manuel says:

This is odd. I first wrote the test, which fails as expected:

  test "product is not valid if title is shorter than 10 chars - i18n" do
    product = Product.new(title: 'Short',
                          description: 'yyyyyyyyyy',
                          price: 1,
                          image_url: 'short.png')
    assert !product.save
    assert_equal I18n.translate('errors.messages.too_short', count: 10),
                  product.errors[:title].join('; ')
     PASS image url (0.13s) 
     PASS product attributes must not be empty (0.00s) 
     FAIL product is not valid if title is shorter than 10 chars - i18n (0.00s) 
          Failed assertion, no message given.

     PASS product is not valid without an unique title - i18n (0.00s) 
     PASS product price must be positive (0.00s)
But after changing
validates :title, uniqueness: true
in product.rb to
validates :title, uniqueness: true, length: {minimum: 10}
, the OTHER tests start to fail!
     FAIL image url (0.08s) 
          fred.gif shouldn't be invalid

     PASS product attributes must not be empty (0.00s) 
     PASS product is not valid if title is shorter than 10 chars - i18n (0.00s) 
     PASS product is not valid without an unique title - i18n (0.00s) 
     FAIL product price must be positive (0.00s) 
          Failed assertion, no message given.

am I missing something?