欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

6.2 user validations

程序员文章站 2022-07-15 16:49:32
...

1. ok, let's add validations to our models:

a. name should not be blank.

b. email should follow email format.

c. email should be unique.

 

2. there are some common validations:

validates pressences, length, unique, format, and add confirmation.

 

3. we will continue to use test-driven dev.

 

since we are going to test, we need to copy the dev database structure are copied over to test database:

 

rake db:test:prepare

 

this command will copied the structure in db/development.sqlite3 to db/test.sqlite3

 

4. sometimes, you are not clear about what to test during TDD, at this time, you can dev first, then, after it is clear, comment out the dev code, write a failing test, then uncomment your dev code, see if the test pass.

 

This comment-write_test-uncomment, work flow will also work if you want to write test to code writen by another guy.

 

5. Validates the pressence of a attribute:

 

validates :name, :pressence => true

 

note: :pressence => true, is a hash, remember, if the last argument is a hash, the braces can be omitted.

 

attr_accessible,

valiates

are both just methods, 

 

6. let's see if our validates are working?

 

user = User.new(:name => "", :email => "[email protected]")

user.save

=> false

user.valid?

=> false

 

user.valid?  this method will check all validations, if one fails, will return false.

 

when checking the pressence of a field, rails is using this method:

 

object.blank? 

 

so an empty string will fail the pressence validation.

 

7. the validations will generate a errors object.

 

user.errors.full_messages

 

this will return an array of all error messages from validations.

 

=> ["Name can't be blank"]

 

8. ok, let's comment out the validate, then write a failing test:

 

 

we will use rspec:

 

 

describe User do
  before(:each) do
    @attr = {:name = "fjdlfds",  :email => "[email protected]"}
  end
  
  it "should create a valid user" do
    User.create!(@attr)
  end

  it "should have a user name"

end

 ok, let's anlyze this part of code:

 

a. before(:each) is saying, before each spec run, this part of code must be executed first.

b. User.create!(@attr),  read as "create bang", this will throw a exception if the create failed!!

c. it "should have a user name", this is without do .... end,  rspec will know this is a pending.

 

9, next, we will try to fill in the pending test.

we need to hash with a blank user name.

to do this, we can use the merge method of hash class:

 

*merge method is an important method of hash class*

 

this will add new key-value pair to a hash, if this key already exist, the new value will replace old one.

 

it "should require a name" do
    no_name_user = User.new(@attr.merge(:name => ""))
    no_name_user.should_not be_valid
  end
 

looking at this code, merge method is doing its job.

 

and should_not is a method of rspec.

 

be_valid is a little tricky, this model is responding to the valid? method, so rspec will automatically have be_valid method.

 

so if a model has a fdsfdsds? method, then the rspec will auto have a be_fdsfdsds method

 

 

10. next, let's add some validation to the length of the name field:

 

also, first, let's write a failing test:

 

 

it "should reject names that are too long" do
    long_name = "a" * 51
    long_name_user = User.new(@attr.merge(:name => long_name))
    long_name_user.should_not be_valid
end

 

then, let's add a line of code to user.rb to make the test pass

 

validates :name, :presence => true, :length => {:maximum => 50}

 

("a" * 51 = "aaaaaaaaaaaaaaaa.......")

 

 

11. the next validation is email format validation

 

we can't say we have a perfect validation, but we should try to allow most valid email format, and forbid most invalid format.

 

again, we start from test, we first should have a collection of valid and invalid email format, for convenience, we first introduce a useful way to define a string array:

 

%w[foo bar baz]

 

addresses = %w[[email protected] [email protected] [email protected]]

 

 

we need to use regular expression (regex) in ruby to verify the email format.

 

email_regex = /\A[\w+\-.][email protected][a-z\d\-.]+\.[a-z]+\z/i

 

to understand this regex, you can refer to www.rubular.com, or check against the Table 6.1 in rubyonrails tutorial book.

 

 

12. next, let's add a uniqueness check on email address:

again, start from test.

 

a. we need a existing user record, so we will use:

 

User.create!(@attr)

 

we use create! because if it fails, it will throw an exception, so that we know it fails.

or, we won't observe it fails, that will cause trouble.

 

b. the validation code in the model will be:

 

validates :email, :presence => true, :format => {:with => email_regex}, :uniqueness => true

 

 

c. we are not done yet, we haven't consider the case-insensitive issue, so the test code should be:

 

it "should reject email addresses identical up to case" do

  upcased_email = @attr[:email].upcase

  User.create!(@attr.merge(:email => upcased_email))

  user_with_dup_email = User.new(@attr)

  user_with_dup_email.should_not be_valid

end

 

and the validation code in the model will be:

 

validates :email, :presence => true, :format => {:with => email_regex}, 

:uniqueness => {:case_sensitive => false}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ok, we are done, congrats, we follow the TDD principle!!

 

 

 

 

相关标签: rspec validate