6.2 user validations

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 => "jfjdsl@jdlj.com")

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 => "ajflds@fjldsjf.com"}
  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[chad@chad.com THE_USER@foo.bar.org first.last@foo.jp]

 

 

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

 

email_regex = /\A[\w+\-.]+@[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!!

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值