Commit 50c8896f958f1cb6de2b90a83e70f17495b857f8
1 parent
1a041f1c
Exists in
master
and in
22 other branches
ActionItem9: adding validations to user and profile models
git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@102 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
4 changed files
with
76 additions
and
1 deletions
Show diff stats
app/models/profile.rb
| @@ -3,6 +3,9 @@ | @@ -3,6 +3,9 @@ | ||
| 3 | # which by default is the one returned by VirtualCommunity:default. | 3 | # which by default is the one returned by VirtualCommunity:default. |
| 4 | class Profile < ActiveRecord::Base | 4 | class Profile < ActiveRecord::Base |
| 5 | 5 | ||
| 6 | + # Valid identifiers must match this format. | ||
| 7 | + IDENTIFIER_FORMAT = /^[a-z][a-z0-9_]+[a-z0-9]$/ | ||
| 8 | + | ||
| 6 | # These names cannot be used as identifiers for Profiles | 9 | # These names cannot be used as identifiers for Profiles |
| 7 | RESERVED_IDENTIFIERS = %w[ | 10 | RESERVED_IDENTIFIERS = %w[ |
| 8 | admin | 11 | admin |
| @@ -17,10 +20,26 @@ class Profile < ActiveRecord::Base | @@ -17,10 +20,26 @@ class Profile < ActiveRecord::Base | ||
| 17 | belongs_to :virtual_community | 20 | belongs_to :virtual_community |
| 18 | belongs_to :user | 21 | belongs_to :user |
| 19 | 22 | ||
| 23 | + | ||
| 24 | + # Sets the identifier for this profile. Raises an exception when called on a | ||
| 25 | + # existing profile (since profiles cannot be renamed) | ||
| 26 | + def identifier=(value) | ||
| 27 | + unless self.new_record? | ||
| 28 | + raise ArgumentError.new(_('An existing profile cannot be renamed.')) | ||
| 29 | + end | ||
| 30 | + self[:identifier] = value | ||
| 31 | + end | ||
| 32 | + | ||
| 20 | validates_presence_of :identifier | 33 | validates_presence_of :identifier |
| 21 | - validates_format_of :identifier, :with => /^[a-z][a-z0-9_]+[a-z0-9]$/ | 34 | + validates_format_of :identifier, :with => IDENTIFIER_FORMAT |
| 22 | validates_exclusion_of :identifier, :in => RESERVED_IDENTIFIERS | 35 | validates_exclusion_of :identifier, :in => RESERVED_IDENTIFIERS |
| 23 | 36 | ||
| 37 | + # A user cannot have more than one profile, but many profiles can exist | ||
| 38 | + # without being associated to a particular user. | ||
| 39 | + validates_uniqueness_of :user_id, :if => (lambda do |profile| | ||
| 40 | + ! profile.user_id.nil? | ||
| 41 | + end) | ||
| 42 | + | ||
| 24 | # creates a new Profile. By default, it is attached to the default | 43 | # creates a new Profile. By default, it is attached to the default |
| 25 | # VirtualCommunity (see VirtualCommunity#default), unless you tell it | 44 | # VirtualCommunity (see VirtualCommunity#default), unless you tell it |
| 26 | # otherwise | 45 | # otherwise |
app/models/user.rb
| 1 | require 'digest/sha1' | 1 | require 'digest/sha1' |
| 2 | + | ||
| 2 | class User < ActiveRecord::Base | 3 | class User < ActiveRecord::Base |
| 3 | 4 | ||
| 4 | after_create do |user| | 5 | after_create do |user| |
| @@ -10,6 +11,7 @@ class User < ActiveRecord::Base | @@ -10,6 +11,7 @@ class User < ActiveRecord::Base | ||
| 10 | attr_accessor :password | 11 | attr_accessor :password |
| 11 | 12 | ||
| 12 | validates_presence_of :login, :email | 13 | validates_presence_of :login, :email |
| 14 | + validates_format_of :login, :with => Profile::IDENTIFIER_FORMAT | ||
| 13 | validates_presence_of :password, :if => :password_required? | 15 | validates_presence_of :password, :if => :password_required? |
| 14 | validates_presence_of :password_confirmation, :if => :password_required? | 16 | validates_presence_of :password_confirmation, :if => :password_required? |
| 15 | validates_length_of :password, :within => 4..40, :if => :password_required? | 17 | validates_length_of :password, :within => 4..40, :if => :password_required? |
test/unit/profile_test.rb
| @@ -50,4 +50,31 @@ class ProfileTest < Test::Unit::TestCase | @@ -50,4 +50,31 @@ class ProfileTest < Test::Unit::TestCase | ||
| 50 | assert p.valid? | 50 | assert p.valid? |
| 51 | end | 51 | end |
| 52 | 52 | ||
| 53 | + def test_only_one_profile_per_user | ||
| 54 | + p1 = profiles(:johndoe) | ||
| 55 | + assert_equal users(:johndoe), p1.user | ||
| 56 | + | ||
| 57 | + p2 = Profile.new | ||
| 58 | + p2.user = users(:johndoe) | ||
| 59 | + assert !p2.valid? | ||
| 60 | + assert p2.errors.invalid?(:user_id) | ||
| 61 | + end | ||
| 62 | + | ||
| 63 | + def test_several_profiles_without_user | ||
| 64 | + p1 = profiles(:john_and_joe) | ||
| 65 | + assert p1.valid? | ||
| 66 | + assert_nil p1.user | ||
| 67 | + | ||
| 68 | + p2 = Profile.new | ||
| 69 | + assert !p2.valid? | ||
| 70 | + assert !p2.errors.invalid?(:user_id) | ||
| 71 | + end | ||
| 72 | + | ||
| 73 | + def test_cannot_rename | ||
| 74 | + p1 = profiles(:johndoe) | ||
| 75 | + assert_raise ArgumentError do | ||
| 76 | + p1.identifier = 'bli' | ||
| 77 | + end | ||
| 78 | + end | ||
| 79 | + | ||
| 53 | end | 80 | end |
test/unit/user_test.rb
| @@ -75,10 +75,37 @@ class UserTest < Test::Unit::TestCase | @@ -75,10 +75,37 @@ class UserTest < Test::Unit::TestCase | ||
| 75 | user = User.create!(:login => 'new_user', :email => 'new_user@example.com', :password => 'test', :password_confirmation => 'test') | 75 | user = User.create!(:login => 'new_user', :email => 'new_user@example.com', :password => 'test', :password_confirmation => 'test') |
| 76 | 76 | ||
| 77 | assert Profile.exists?(['user_id = ?', user.id]) | 77 | assert Profile.exists?(['user_id = ?', user.id]) |
| 78 | + | ||
| 78 | assert_equal users_count + 1, User.count | 79 | assert_equal users_count + 1, User.count |
| 79 | assert_equal profiles_count + 1, Profile.count | 80 | assert_equal profiles_count + 1, Profile.count |
| 80 | end | 81 | end |
| 81 | 82 | ||
| 83 | + def test_login_validation | ||
| 84 | + u = User.new | ||
| 85 | + u.valid? | ||
| 86 | + assert u.errors.invalid?(:login) | ||
| 87 | + | ||
| 88 | + u.login = 'with space' | ||
| 89 | + u.valid? | ||
| 90 | + assert u.errors.invalid?(:login) | ||
| 91 | + | ||
| 92 | + u.login = 'áéíóú' | ||
| 93 | + u.valid? | ||
| 94 | + assert u.errors.invalid?(:login) | ||
| 95 | + | ||
| 96 | + u.login = 'rightformat2007' | ||
| 97 | + u.valid? | ||
| 98 | + assert ! u.errors.invalid?(:login) | ||
| 99 | + | ||
| 100 | + u.login = 'rightformat' | ||
| 101 | + u.valid? | ||
| 102 | + assert ! u.errors.invalid?(:login) | ||
| 103 | + | ||
| 104 | + u.login = 'right_format' | ||
| 105 | + u.valid? | ||
| 106 | + assert ! u.errors.invalid?(:login) | ||
| 107 | + end | ||
| 108 | + | ||
| 82 | protected | 109 | protected |
| 83 | def create_user(options = {}) | 110 | def create_user(options = {}) |
| 84 | User.create({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options)) | 111 | User.create({ :login => 'quire', :email => 'quire@example.com', :password => 'quire', :password_confirmation => 'quire' }.merge(options)) |