6.2 user validations

6584 단어 validaterspec
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+\-.]+@[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!!
 
 
 

좋은 웹페이지 즐겨찾기