activemodel 4.0.0.beta1 → 4.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a123b304fffb488ab66aab52d5fc0d41b0c0b511
4
- data.tar.gz: 1890c14c3ab9251044e70e38f993d4c55707cb52
3
+ metadata.gz: 250ef70b10d4ec2e30333cfffc80da63aed87895
4
+ data.tar.gz: 69c232cc5ed875faedbb29a0f0d6c1a01bcf5d19
5
5
  SHA512:
6
- metadata.gz: 882ad1f17ccb90c6a79d86a42d3f91685a1ece5e7ec63ed83be888a20d086ea38928aba2af650e13b79c1955d5f62d78c4b865311be1a8ae065197ee2a858aaa
7
- data.tar.gz: 5452a0c0afabc7f3c3f536e670cb61244dd8d9236bfac6dd049da917dbe6bed0d110b4c6ed3bd0a374c7e09b42988cd937ae57cef83ff03e42a33aeea2cbb276
6
+ metadata.gz: 0be6ba150a3151982443cf95e5c2a04da6af1b807282767e5ca44a4367830b070cbaa631dffaf3d65494a9e8cafe72f6ba19dcdb71d504c01009902a09865964
7
+ data.tar.gz: 836ccca90ace183c3e7944cbefb229a369db445f34fe68289d9af0444e29058f6834b9495b5554d95180c8777517977009eb94ad5de1d4880bdbc0125616bbaa
data/CHANGELOG.md CHANGED
@@ -1,3 +1,73 @@
1
+ ## Rails 4.0.0 (unreleased) ##
2
+
3
+ * Add `ActiveModel::Errors#full_messages_for`, to return all the error messages
4
+ for a given attribute.
5
+
6
+ Example:
7
+
8
+ class Person
9
+ include ActiveModel::Validations
10
+
11
+ attr_reader :name, :email
12
+ validates_presence_of :name, :email
13
+ end
14
+
15
+ person = Person.new
16
+ person.valid? # => false
17
+ person.errors.full_messages_for(:name) # => ["Name can't be blank"]
18
+
19
+ *Volodymyr Shatsky*
20
+
21
+ * Added a method so that validations can be easily cleared on a model.
22
+ For example:
23
+
24
+ class Person
25
+ include ActiveModel::Validations
26
+
27
+ validates_uniqueness_of :first_name
28
+ validate :cannot_be_robot
29
+
30
+ def cannot_be_robot
31
+ errors.add(:base, 'A person cannot be a robot') if person_is_robot
32
+ end
33
+ end
34
+
35
+ Now, if someone runs `Person.clear_validators!`, then the following occurs:
36
+
37
+ Person.validators # => []
38
+ Person._validate_callbacks.empty? # => true
39
+
40
+ *John Wang*
41
+
42
+ * `has_secure_password` does not fail the confirmation validation
43
+ when assigning empty String to `password` and `password_confirmation`.
44
+ Fixes #9535.
45
+
46
+ Example:
47
+
48
+ # Given User has_secure_password.
49
+ @user.password = ""
50
+ @user.password_confirmation = ""
51
+ @user.valid?(:update) # used to be false
52
+
53
+ *Yves Senn*
54
+
55
+ * `validates_confirmation_of` does not override writer methods for
56
+ the confirmation attribute if no reader is defined.
57
+
58
+ Example:
59
+
60
+ class Blog
61
+ def title=(new_title)
62
+ @title = new_title.downcase
63
+ end
64
+
65
+ # previously this would override the setter above.
66
+ validates_confirmation_of :title
67
+ end
68
+
69
+ *Yves Senn*
70
+
1
71
  ## Rails 4.0.0.beta1 (February 25, 2013) ##
2
72
 
3
73
  * Add `ActiveModel::Validations::AbsenceValidator`, a validator to check the
@@ -40,7 +110,7 @@
40
110
 
41
111
  *Yves Senn*
42
112
 
43
- * Use BCrypt's `MIN_COST` in the test environment for speedier tests when using `has_secure_pasword`.
113
+ * Use BCrypt's `MIN_COST` in the test environment for speedier tests when using `has_secure_password`.
44
114
 
45
115
  *Brian Cardarella + Jeremy Kemper + Trevor Turk*
46
116
 
@@ -81,7 +151,7 @@
81
151
 
82
152
  * Changed `ActiveModel::Serializers::Xml::Serializer#add_associations` to by default
83
153
  propagate `:skip_types, :dasherize, :camelize` keys to included associations.
84
- It can be overriden on each association by explicitly specifying the option on one
154
+ It can be overridden on each association by explicitly specifying the option on one
85
155
  or more associations
86
156
 
87
157
  *Anthony Alberto*
data/README.rdoc CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Active Model provides a known set of interfaces for usage in model classes.
4
4
  They allow for Action Pack helpers to interact with non-Active Record models,
5
- for example. Active Model also helps building custom ORMs for use outside of
5
+ for example. Active Model also helps with building custom ORMs for use outside of
6
6
  the Rails framework.
7
7
 
8
8
  Prior to Rails 3.0, if a plugin or gem developer wanted to have an object
@@ -24,8 +24,8 @@ to integrate with Action Pack out of the box: <tt>ActiveModel::Model</tt>.
24
24
  end
25
25
 
26
26
  person = Person.new(name: 'bob', age: '18')
27
- person.name # => 'bob'
28
- person.age # => '18'
27
+ person.name # => 'bob'
28
+ person.age # => '18'
29
29
  person.valid? # => true
30
30
 
31
31
  It includes model name introspections, conversions, translations and
@@ -82,12 +82,12 @@ behavior out of the box:
82
82
  end
83
83
 
84
84
  person = Person.new
85
- person.name # => nil
86
- person.changed? # => false
85
+ person.name # => nil
86
+ person.changed? # => false
87
87
  person.name = 'bob'
88
- person.changed? # => true
89
- person.changed # => ['name']
90
- person.changes # => { 'name' => [nil, 'bob'] }
88
+ person.changed? # => true
89
+ person.changed # => ['name']
90
+ person.changes # => { 'name' => [nil, 'bob'] }
91
91
  person.name = 'robert'
92
92
  person.save
93
93
  person.previous_changes # => {'name' => ['bob, 'robert']}
@@ -12,19 +12,21 @@ module ActiveModel
12
12
  # # => ActiveModel::MissingAttributeError: missing attribute: user_id
13
13
  class MissingAttributeError < NoMethodError
14
14
  end
15
+
15
16
  # == Active \Model Attribute Methods
16
17
  #
17
18
  # <tt>ActiveModel::AttributeMethods</tt> provides a way to add prefixes and
18
- # suffixes to your methods as well as handling the creation of Active Record
19
- # like class methods such as +table_name+.
19
+ # suffixes to your methods as well as handling the creation of
20
+ # <tt>ActiveRecord::Base</tt>-like class methods such as +table_name+.
20
21
  #
21
- # The requirements to implement ActiveModel::AttributeMethods are to:
22
+ # The requirements to implement <tt>ActiveModel::AttributeMethods</tt> are to:
22
23
  #
23
- # * <tt>include ActiveModel::AttributeMethods</tt> in your object.
24
- # * Call each Attribute Method module method you want to add, such as
25
- # +attribute_method_suffix+ or +attribute_method_prefix+.
24
+ # * <tt>include ActiveModel::AttributeMethods</tt> in your class.
25
+ # * Call each of its method you want to add, such as +attribute_method_suffix+
26
+ # or +attribute_method_prefix+.
26
27
  # * Call +define_attribute_methods+ after the other methods are called.
27
28
  # * Define the various generic +_attribute+ methods that you have declared.
29
+ # * Define an +attributes+ method, see below.
28
30
  #
29
31
  # A minimal implementation could be:
30
32
  #
@@ -38,6 +40,10 @@ module ActiveModel
38
40
  #
39
41
  # attr_accessor :name
40
42
  #
43
+ # def attributes
44
+ # {'name' => @name}
45
+ # end
46
+ #
41
47
  # private
42
48
  #
43
49
  # def attribute_contrived?(attr)
@@ -53,10 +59,10 @@ module ActiveModel
53
59
  # end
54
60
  # end
55
61
  #
56
- # Note that whenever you include ActiveModel::AttributeMethods in your class,
57
- # it requires you to implement an +attributes+ method which returns a hash
58
- # with each attribute name in your model as hash key and the attribute value as
59
- # hash value.
62
+ # Note that whenever you include <tt>ActiveModel::AttributeMethods</tt> in
63
+ # your class, it requires you to implement an +attributes+ method which
64
+ # returns a hash with each attribute name in your model as hash key and the
65
+ # attribute value as hash value.
60
66
  #
61
67
  # Hash keys must be strings.
62
68
  module AttributeMethods
@@ -179,7 +185,6 @@ module ActiveModel
179
185
  undefine_attribute_methods
180
186
  end
181
187
 
182
-
183
188
  # Allows you to make aliases for attributes.
184
189
  #
185
190
  # class Person
@@ -413,17 +418,16 @@ module ActiveModel
413
418
  end
414
419
  end
415
420
 
416
- # Allows access to the object attributes, which are held in the
417
- # <tt>@attributes</tt> hash, as though they were first-class methods. So a
418
- # Person class with a name attribute can use Person#name and Person#name=
419
- # and never directly use the attributes hash -- except for multiple assigns
420
- # with ActiveRecord#attributes=. A Milestone class can also ask
421
- # Milestone#completed? to test that the completed attribute is not +nil+
422
- # or 0.
421
+ # Allows access to the object attributes, which are held in the hash
422
+ # returned by <tt>attributes</tt>, as though they were first-class
423
+ # methods. So a +Person+ class with a +name+ attribute can for example use
424
+ # <tt>Person#name</tt> and <tt>Person#name=</tt> and never directly use
425
+ # the attributes hash -- except for multiple assigns with
426
+ # <tt>ActiveRecord::Base#attributes=</tt>.
423
427
  #
424
- # It's also possible to instantiate related objects, so a Client class
425
- # belonging to the clients table with a +master_id+ foreign key can
426
- # instantiate master through Client#master.
428
+ # It's also possible to instantiate related objects, so a <tt>Client</tt>
429
+ # class belonging to the +clients+ table with a +master_id+ foreign key
430
+ # can instantiate master through <tt>Client#master</tt>.
427
431
  def method_missing(method, *args, &block)
428
432
  if respond_to_without_attributes?(method, true)
429
433
  super
@@ -433,17 +437,17 @@ module ActiveModel
433
437
  end
434
438
  end
435
439
 
436
- # attribute_missing is like method_missing, but for attributes. When method_missing is
437
- # called we check to see if there is a matching attribute method. If so, we call
438
- # attribute_missing to dispatch the attribute. This method can be overloaded to
439
- # customize the behavior.
440
+ # +attribute_missing+ is like +method_missing+, but for attributes. When
441
+ # +method_missing+ is called we check to see if there is a matching
442
+ # attribute method. If so, we tell +attribute_missing+ to dispatch the
443
+ # attribute. This method can be overloaded to customize the behavior.
440
444
  def attribute_missing(match, *args, &block)
441
445
  __send__(match.target, match.attr_name, *args, &block)
442
446
  end
443
447
 
444
- # A Person object with a name attribute can ask <tt>person.respond_to?(:name)</tt>,
445
- # <tt>person.respond_to?(:name=)</tt>, and <tt>person.respond_to?(:name?)</tt>
446
- # which will all return +true+.
448
+ # A +Person+ instance with a +name+ attribute can ask
449
+ # <tt>person.respond_to?(:name)</tt>, <tt>person.respond_to?(:name=)</tt>,
450
+ # and <tt>person.respond_to?(:name?)</tt> which will all return +true+.
447
451
  alias :respond_to_without_attributes? :respond_to?
448
452
  def respond_to?(method, include_private_methods = false)
449
453
  if super
@@ -1,5 +1,5 @@
1
1
  module ActiveModel
2
- # == Active \Model Conversions
2
+ # == Active \Model Conversion
3
3
  #
4
4
  # Handles default conversions: to_model, to_key, to_param, and to_partial_path.
5
5
  #
@@ -46,7 +46,7 @@ module ActiveModel
46
46
  #
47
47
  # A newly instantiated object is unchanged:
48
48
  #
49
- # person = Person.find_by_name('Uncle Bob')
49
+ # person = Person.find_by(name: 'Uncle Bob')
50
50
  # person.changed? # => false
51
51
  #
52
52
  # Change the name:
@@ -12,7 +12,6 @@ module ActiveModel
12
12
  # A minimal implementation could be:
13
13
  #
14
14
  # class Person
15
- #
16
15
  # # Required dependency for ActiveModel::Errors
17
16
  # extend ActiveModel::Naming
18
17
  #
@@ -40,7 +39,6 @@ module ActiveModel
40
39
  # def Person.lookup_ancestors
41
40
  # [self]
42
41
  # end
43
- #
44
42
  # end
45
43
  #
46
44
  # The last three methods are required in your object for Errors to be
@@ -352,6 +350,20 @@ module ActiveModel
352
350
  map { |attribute, message| full_message(attribute, message) }
353
351
  end
354
352
 
353
+ # Returns all the full error messages for a given attribute in an array.
354
+ #
355
+ # class Person
356
+ # validates_presence_of :name, :email
357
+ # validates_length_of :name, in: 5..30
358
+ # end
359
+ #
360
+ # person = Person.create()
361
+ # person.errors.full_messages_for(:name)
362
+ # # => ["Name is too short (minimum is 5 characters)", "Name can't be blank"]
363
+ def full_messages_for(attribute)
364
+ (get(attribute) || []).map { |message| full_message(attribute, message) }
365
+ end
366
+
355
367
  # Returns a full message for a given attribute.
356
368
  #
357
369
  # person.errors.full_message(:name, 'is invalid') # => "Name is invalid"
@@ -30,24 +30,31 @@ module ActiveModel
30
30
  # end
31
31
  #
32
32
  # user = User.new(name: 'david', password: '', password_confirmation: 'nomatch')
33
- # user.save # => false, password required
33
+ # user.save # => false, password required
34
34
  # user.password = 'mUc3m00RsqyRe'
35
- # user.save # => false, confirmation doesn't match
35
+ # user.save # => false, confirmation doesn't match
36
36
  # user.password_confirmation = 'mUc3m00RsqyRe'
37
- # user.save # => true
38
- # user.authenticate('notright') # => false
39
- # user.authenticate('mUc3m00RsqyRe') # => user
40
- # User.find_by_name('david').try(:authenticate, 'notright') # => false
41
- # User.find_by_name('david').try(:authenticate, 'mUc3m00RsqyRe') # => user
37
+ # user.save # => true
38
+ # user.authenticate('notright') # => false
39
+ # user.authenticate('mUc3m00RsqyRe') # => user
40
+ # User.find_by(name: 'david').try(:authenticate, 'notright') # => false
41
+ # User.find_by(name: 'david').try(:authenticate, 'mUc3m00RsqyRe') # => user
42
42
  def has_secure_password(options = {})
43
43
  # Load bcrypt-ruby only when has_secure_password is used.
44
44
  # This is to avoid ActiveModel (and by extension the entire framework)
45
45
  # being dependent on a binary library.
46
- gem 'bcrypt-ruby', '~> 3.0.0'
47
- require 'bcrypt'
46
+ begin
47
+ gem 'bcrypt-ruby', '~> 3.0.0'
48
+ require 'bcrypt'
49
+ rescue LoadError
50
+ $stderr.puts "You don't have bcrypt-ruby installed in your application. Please add it to your Gemfile and run bundle install"
51
+ raise
52
+ end
48
53
 
49
54
  attr_reader :password
50
55
 
56
+ include InstanceMethodsOnActivation
57
+
51
58
  if options.fetch(:validations, true)
52
59
  validates_confirmation_of :password
53
60
  validates_presence_of :password, :on => :create
@@ -55,8 +62,6 @@ module ActiveModel
55
62
  before_create { raise "Password digest missing on new record" if password_digest.blank? }
56
63
  end
57
64
 
58
- include InstanceMethodsOnActivation
59
-
60
65
  if respond_to?(:attributes_protected_by_default)
61
66
  def self.attributes_protected_by_default #:nodoc:
62
67
  super + ['password_digest']
@@ -99,6 +104,12 @@ module ActiveModel
99
104
  self.password_digest = BCrypt::Password.create(unencrypted_password, cost: cost)
100
105
  end
101
106
  end
107
+
108
+ def password_confirmation=(unencrypted_password)
109
+ unless unencrypted_password.blank?
110
+ @password_confirmation = unencrypted_password
111
+ end
112
+ end
102
113
  end
103
114
  end
104
115
  end
@@ -169,6 +169,49 @@ module ActiveModel
169
169
  _validators.values.flatten.uniq
170
170
  end
171
171
 
172
+ # Clears all of the validators and validations.
173
+ #
174
+ # Note that this will clear anything that is being used to validate
175
+ # the model for both the +validates_with+ and +validate+ methods.
176
+ # It clears the validators that are created with an invocation of
177
+ # +validates_with+ and the callbacks that are set by an invocation
178
+ # of +validate+.
179
+ #
180
+ # class Person
181
+ # include ActiveModel::Validations
182
+ #
183
+ # validates_with MyValidator
184
+ # validates_with OtherValidator, on: :create
185
+ # validates_with StrictValidator, strict: true
186
+ # validate :cannot_be_robot
187
+ #
188
+ # def cannot_be_robot
189
+ # errors.add(:base, 'A person cannot be a robot') if person_is_robot
190
+ # end
191
+ # end
192
+ #
193
+ # Person.validators
194
+ # # => [
195
+ # # #<MyValidator:0x007fbff403e808 @options={}>,
196
+ # # #<OtherValidator:0x007fbff403d930 @options={on: :create}>,
197
+ # # #<StrictValidator:0x007fbff3204a30 @options={strict:true}>
198
+ # # ]
199
+ #
200
+ # If one runs Person.clear_validators! and then checks to see what
201
+ # validators this class has, you would obtain:
202
+ #
203
+ # Person.validators # => []
204
+ #
205
+ # Also, the callback set by +validate :cannot_be_robot+ will be erased
206
+ # so that:
207
+ #
208
+ # Person._validate_callbacks.empty? # => true
209
+ #
210
+ def clear_validators!
211
+ reset_callbacks(:validate)
212
+ _validators.clear
213
+ end
214
+
172
215
  # List all validators that are being used to validate a specific attribute.
173
216
  #
174
217
  # class Person
@@ -333,7 +376,4 @@ module ActiveModel
333
376
  end
334
377
  end
335
378
 
336
- Dir[File.dirname(__FILE__) + "/validations/*.rb"].sort.each do |path|
337
- filename = File.basename(path)
338
- require "active_model/validations/#{filename}"
339
- end
379
+ Dir[File.dirname(__FILE__) + "/validations/*.rb"].each { |file| require file }
@@ -10,9 +10,13 @@ module ActiveModel
10
10
  end
11
11
 
12
12
  def setup(klass)
13
- klass.send(:attr_accessor, *attributes.map do |attribute|
13
+ klass.send(:attr_reader, *attributes.map do |attribute|
14
14
  :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation")
15
15
  end.compact)
16
+
17
+ klass.send(:attr_writer, *attributes.map do |attribute|
18
+ :"#{attribute}_confirmation" unless klass.method_defined?(:"#{attribute}_confirmation=")
19
+ end.compact)
16
20
  end
17
21
  end
18
22
 
@@ -1,10 +1,11 @@
1
1
  module ActiveModel
2
- module VERSION #:nodoc:
3
- MAJOR = 4
4
- MINOR = 0
5
- TINY = 0
6
- PRE = "beta1"
2
+ # Returns the version of the currently loaded ActiveModel as a Gem::Version
3
+ def self.version
4
+ Gem::Version.new "4.0.0.rc1"
5
+ end
7
6
 
8
- STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
7
+ module VERSION #:nodoc:
8
+ MAJOR, MINOR, TINY, PRE = ActiveModel.version.segments
9
+ STRING = ActiveModel.version.to_s
9
10
  end
10
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemodel
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.beta1
4
+ version: 4.0.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-02-26 00:00:00.000000000 Z
11
+ date: 2013-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 4.0.0.beta1
19
+ version: 4.0.0.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 4.0.0.beta1
26
+ version: 4.0.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: builder
29
29
  requirement: !ruby/object:Gem::Requirement