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 +4 -4
- data/CHANGELOG.md +72 -2
- data/README.rdoc +8 -8
- data/lib/active_model/attribute_methods.rb +32 -28
- data/lib/active_model/conversion.rb +1 -1
- data/lib/active_model/dirty.rb +1 -1
- data/lib/active_model/errors.rb +14 -2
- data/lib/active_model/secure_password.rb +22 -11
- data/lib/active_model/validations.rb +44 -4
- data/lib/active_model/validations/confirmation.rb +5 -1
- data/lib/active_model/version.rb +7 -6
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 250ef70b10d4ec2e30333cfffc80da63aed87895
|
4
|
+
data.tar.gz: 69c232cc5ed875faedbb29a0f0d6c1a01bcf5d19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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 `
|
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
|
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
|
28
|
-
person.age
|
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
|
86
|
-
person.changed?
|
85
|
+
person.name # => nil
|
86
|
+
person.changed? # => false
|
87
87
|
person.name = 'bob'
|
88
|
-
person.changed?
|
89
|
-
person.changed
|
90
|
-
person.changes
|
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
|
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
|
24
|
-
# * Call each
|
25
|
-
#
|
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
|
57
|
-
# it requires you to implement an +attributes+ method which
|
58
|
-
# with each attribute name in your model as hash key and the
|
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
|
418
|
-
# Person class with a name attribute can
|
419
|
-
# and never directly use
|
420
|
-
#
|
421
|
-
#
|
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
|
425
|
-
# belonging to the clients table with a +master_id+ foreign key
|
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
|
437
|
-
# called we check to see if there is a matching
|
438
|
-
#
|
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
|
445
|
-
# <tt>person.respond_to?(:name
|
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
|
data/lib/active_model/dirty.rb
CHANGED
data/lib/active_model/errors.rb
CHANGED
@@ -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
|
33
|
+
# user.save # => false, password required
|
34
34
|
# user.password = 'mUc3m00RsqyRe'
|
35
|
-
# user.save
|
35
|
+
# user.save # => false, confirmation doesn't match
|
36
36
|
# user.password_confirmation = 'mUc3m00RsqyRe'
|
37
|
-
# user.save
|
38
|
-
# user.authenticate('notright')
|
39
|
-
# user.authenticate('mUc3m00RsqyRe')
|
40
|
-
# User.
|
41
|
-
# 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
|
-
|
47
|
-
|
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"].
|
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(:
|
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
|
|
data/lib/active_model/version.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module ActiveModel
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
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
|
-
|
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.
|
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-
|
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.
|
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.
|
26
|
+
version: 4.0.0.rc1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: builder
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|