cassandra_object 0.6.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/cassandra_object/associations/one_to_many.rb +136 -0
- data/lib/cassandra_object/associations/one_to_one.rb +77 -0
- data/lib/cassandra_object/associations.rb +35 -0
- data/lib/cassandra_object/attributes.rb +93 -0
- data/lib/cassandra_object/base.rb +104 -0
- data/lib/cassandra_object/callbacks.rb +10 -0
- data/lib/cassandra_object/collection.rb +8 -0
- data/lib/cassandra_object/cursor.rb +86 -0
- data/lib/cassandra_object/dirty.rb +27 -0
- data/lib/cassandra_object/identity/abstract_key_factory.rb +36 -0
- data/lib/cassandra_object/identity/key.rb +20 -0
- data/lib/cassandra_object/identity/natural_key_factory.rb +51 -0
- data/lib/cassandra_object/identity/uuid_key_factory.rb +37 -0
- data/lib/cassandra_object/identity.rb +61 -0
- data/lib/cassandra_object/indexes.rb +129 -0
- data/lib/cassandra_object/legacy_callbacks.rb +33 -0
- data/lib/cassandra_object/migrations.rb +72 -0
- data/lib/cassandra_object/mocking.rb +15 -0
- data/lib/cassandra_object/persistence.rb +193 -0
- data/lib/cassandra_object/serialization.rb +6 -0
- data/lib/cassandra_object/type_registration.rb +7 -0
- data/lib/cassandra_object/types.rb +128 -0
- data/lib/cassandra_object/validation.rb +58 -0
- data/lib/cassandra_object.rb +30 -0
- data/vendor/active_support_shims.rb +4 -0
- data/vendor/activemodel/CHANGELOG +13 -0
- data/vendor/activemodel/CHANGES +12 -0
- data/vendor/activemodel/MIT-LICENSE +21 -0
- data/vendor/activemodel/README +21 -0
- data/vendor/activemodel/Rakefile +52 -0
- data/vendor/activemodel/activemodel.gemspec +19 -0
- data/vendor/activemodel/examples/validations.rb +29 -0
- data/vendor/activemodel/lib/active_model/attribute_methods.rb +291 -0
- data/vendor/activemodel/lib/active_model/callbacks.rb +91 -0
- data/vendor/activemodel/lib/active_model/conversion.rb +8 -0
- data/vendor/activemodel/lib/active_model/deprecated_error_methods.rb +33 -0
- data/vendor/activemodel/lib/active_model/dirty.rb +126 -0
- data/vendor/activemodel/lib/active_model/errors.rb +162 -0
- data/vendor/activemodel/lib/active_model/lint.rb +91 -0
- data/vendor/activemodel/lib/active_model/locale/en.yml +27 -0
- data/vendor/activemodel/lib/active_model/naming.rb +45 -0
- data/vendor/activemodel/lib/active_model/observing.rb +191 -0
- data/vendor/activemodel/lib/active_model/railtie.rb +2 -0
- data/vendor/activemodel/lib/active_model/serialization.rb +30 -0
- data/vendor/activemodel/lib/active_model/serializers/json.rb +96 -0
- data/vendor/activemodel/lib/active_model/serializers/xml.rb +204 -0
- data/vendor/activemodel/lib/active_model/state_machine/event.rb +62 -0
- data/vendor/activemodel/lib/active_model/state_machine/machine.rb +75 -0
- data/vendor/activemodel/lib/active_model/state_machine/state.rb +47 -0
- data/vendor/activemodel/lib/active_model/state_machine/state_transition.rb +40 -0
- data/vendor/activemodel/lib/active_model/state_machine.rb +70 -0
- data/vendor/activemodel/lib/active_model/test_case.rb +18 -0
- data/vendor/activemodel/lib/active_model/translation.rb +44 -0
- data/vendor/activemodel/lib/active_model/validations/acceptance.rb +55 -0
- data/vendor/activemodel/lib/active_model/validations/confirmation.rb +47 -0
- data/vendor/activemodel/lib/active_model/validations/exclusion.rb +42 -0
- data/vendor/activemodel/lib/active_model/validations/format.rb +64 -0
- data/vendor/activemodel/lib/active_model/validations/inclusion.rb +42 -0
- data/vendor/activemodel/lib/active_model/validations/length.rb +117 -0
- data/vendor/activemodel/lib/active_model/validations/numericality.rb +111 -0
- data/vendor/activemodel/lib/active_model/validations/presence.rb +42 -0
- data/vendor/activemodel/lib/active_model/validations/with.rb +59 -0
- data/vendor/activemodel/lib/active_model/validations.rb +120 -0
- data/vendor/activemodel/lib/active_model/validator.rb +110 -0
- data/vendor/activemodel/lib/active_model/version.rb +9 -0
- data/vendor/activemodel/lib/active_model.rb +61 -0
- data/vendor/activemodel/test/cases/attribute_methods_test.rb +46 -0
- data/vendor/activemodel/test/cases/callbacks_test.rb +70 -0
- data/vendor/activemodel/test/cases/helper.rb +23 -0
- data/vendor/activemodel/test/cases/lint_test.rb +28 -0
- data/vendor/activemodel/test/cases/naming_test.rb +28 -0
- data/vendor/activemodel/test/cases/observing_test.rb +133 -0
- data/vendor/activemodel/test/cases/serializeration/json_serialization_test.rb +83 -0
- data/vendor/activemodel/test/cases/serializeration/xml_serialization_test.rb +110 -0
- data/vendor/activemodel/test/cases/state_machine/event_test.rb +49 -0
- data/vendor/activemodel/test/cases/state_machine/machine_test.rb +43 -0
- data/vendor/activemodel/test/cases/state_machine/state_test.rb +72 -0
- data/vendor/activemodel/test/cases/state_machine/state_transition_test.rb +84 -0
- data/vendor/activemodel/test/cases/state_machine_test.rb +312 -0
- data/vendor/activemodel/test/cases/tests_database.rb +37 -0
- data/vendor/activemodel/test/cases/translation_test.rb +45 -0
- data/vendor/activemodel/test/cases/validations/acceptance_validation_test.rb +71 -0
- data/vendor/activemodel/test/cases/validations/conditional_validation_test.rb +141 -0
- data/vendor/activemodel/test/cases/validations/confirmation_validation_test.rb +58 -0
- data/vendor/activemodel/test/cases/validations/exclusion_validation_test.rb +47 -0
- data/vendor/activemodel/test/cases/validations/format_validation_test.rb +118 -0
- data/vendor/activemodel/test/cases/validations/i18n_generate_message_validation_test.rb +175 -0
- data/vendor/activemodel/test/cases/validations/i18n_validation_test.rb +527 -0
- data/vendor/activemodel/test/cases/validations/inclusion_validation_test.rb +71 -0
- data/vendor/activemodel/test/cases/validations/length_validation_test.rb +437 -0
- data/vendor/activemodel/test/cases/validations/numericality_validation_test.rb +180 -0
- data/vendor/activemodel/test/cases/validations/presence_validation_test.rb +70 -0
- data/vendor/activemodel/test/cases/validations/with_validation_test.rb +166 -0
- data/vendor/activemodel/test/cases/validations_test.rb +215 -0
- data/vendor/activemodel/test/config.rb +3 -0
- data/vendor/activemodel/test/fixtures/topics.yml +41 -0
- data/vendor/activemodel/test/models/contact.rb +7 -0
- data/vendor/activemodel/test/models/custom_reader.rb +17 -0
- data/vendor/activemodel/test/models/developer.rb +6 -0
- data/vendor/activemodel/test/models/person.rb +9 -0
- data/vendor/activemodel/test/models/reply.rb +34 -0
- data/vendor/activemodel/test/models/topic.rb +9 -0
- data/vendor/activemodel/test/models/track_back.rb +4 -0
- data/vendor/activemodel/test/schema.rb +14 -0
- data/vendor/activesupport/lib/active_support/autoload.rb +48 -0
- data/vendor/activesupport/lib/active_support/concern.rb +25 -0
- data/vendor/activesupport/lib/active_support/core_ext/array/wrap.rb +20 -0
- data/vendor/activesupport/lib/active_support/core_ext/object/blank.rb +58 -0
- data/vendor/activesupport/lib/active_support/core_ext/object/tap.rb +6 -0
- data/vendor/activesupport/lib/active_support/dependency_module.rb +17 -0
- data/vendor/activesupport/lib/active_support/i18n.rb +2 -0
- data/vendor/activesupport/lib/active_support/locale/en.yml +33 -0
- metadata +230 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require 'active_support/core_ext/array/extract_options'
|
|
2
|
+
require 'active_support/core_ext/hash/keys'
|
|
3
|
+
require 'active_model/errors'
|
|
4
|
+
|
|
5
|
+
module ActiveModel
|
|
6
|
+
module Validations
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
include ActiveSupport::Callbacks
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
extend ActiveModel::Translation
|
|
12
|
+
define_callbacks :validate, :scope => :name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module ClassMethods
|
|
16
|
+
# Validates each attribute against a block.
|
|
17
|
+
#
|
|
18
|
+
# class Person < ActiveRecord::Base
|
|
19
|
+
# validates_each :first_name, :last_name do |record, attr, value|
|
|
20
|
+
# record.errors.add attr, 'starts with z.' if value[0] == ?z
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# Options:
|
|
25
|
+
# * <tt>:on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>).
|
|
26
|
+
# * <tt>:allow_nil</tt> - Skip validation if attribute is +nil+.
|
|
27
|
+
# * <tt>:allow_blank</tt> - Skip validation if attribute is blank.
|
|
28
|
+
# * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
|
|
29
|
+
# occur (e.g. <tt>:if => :allow_validation</tt>, or <tt>:if => Proc.new { |user| user.signup_step > 2 }</tt>). The
|
|
30
|
+
# method, proc or string should return or evaluate to a true or false value.
|
|
31
|
+
# * <tt>:unless</tt> - Specifies a method, proc or string to call to determine if the validation should
|
|
32
|
+
# not occur (e.g. <tt>:unless => :skip_validation</tt>, or <tt>:unless => Proc.new { |user| user.signup_step <= 2 }</tt>). The
|
|
33
|
+
# method, proc or string should return or evaluate to a true or false value.
|
|
34
|
+
def validates_each(*attr_names, &block)
|
|
35
|
+
options = attr_names.extract_options!.symbolize_keys
|
|
36
|
+
validates_with BlockValidator, options.merge(:attributes => attr_names.flatten), &block
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Adds a validation method or block to the class. This is useful when
|
|
40
|
+
# overriding the +validate+ instance method becomes too unwieldly and
|
|
41
|
+
# you're looking for more descriptive declaration of your validations.
|
|
42
|
+
#
|
|
43
|
+
# This can be done with a symbol pointing to a method:
|
|
44
|
+
#
|
|
45
|
+
# class Comment < ActiveRecord::Base
|
|
46
|
+
# validate :must_be_friends
|
|
47
|
+
#
|
|
48
|
+
# def must_be_friends
|
|
49
|
+
# errors.add_to_base("Must be friends to leave a comment") unless commenter.friend_of?(commentee)
|
|
50
|
+
# end
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
# Or with a block which is passed the current record to be validated:
|
|
54
|
+
#
|
|
55
|
+
# class Comment < ActiveRecord::Base
|
|
56
|
+
# validate do |comment|
|
|
57
|
+
# comment.must_be_friends
|
|
58
|
+
# end
|
|
59
|
+
#
|
|
60
|
+
# def must_be_friends
|
|
61
|
+
# errors.add_to_base("Must be friends to leave a comment") unless commenter.friend_of?(commentee)
|
|
62
|
+
# end
|
|
63
|
+
# end
|
|
64
|
+
#
|
|
65
|
+
# This usage applies to +validate_on_create+ and +validate_on_update as well+.
|
|
66
|
+
def validate(*args, &block)
|
|
67
|
+
options = args.last
|
|
68
|
+
if options.is_a?(Hash) && options.key?(:on)
|
|
69
|
+
options[:if] = Array(options[:if])
|
|
70
|
+
options[:if] << "@_on_validate == :#{options[:on]}"
|
|
71
|
+
end
|
|
72
|
+
set_callback(:validate, *args, &block)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns the Errors object that holds all information about attribute error messages.
|
|
77
|
+
def errors
|
|
78
|
+
@errors ||= Errors.new(self)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Runs all the specified validations and returns true if no errors were added otherwise false.
|
|
82
|
+
def valid?
|
|
83
|
+
errors.clear
|
|
84
|
+
_run_validate_callbacks
|
|
85
|
+
errors.empty?
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Performs the opposite of <tt>valid?</tt>. Returns true if errors were added, false otherwise.
|
|
89
|
+
def invalid?
|
|
90
|
+
!valid?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
protected
|
|
94
|
+
# Hook method defining how an attribute value should be retieved. By default this is assumed
|
|
95
|
+
# to be an instance named after the attribute. Override this method in subclasses should you
|
|
96
|
+
# need to retrieve the value for a given attribute differently e.g.
|
|
97
|
+
# class MyClass
|
|
98
|
+
# include ActiveModel::Validations
|
|
99
|
+
#
|
|
100
|
+
# def initialize(data = {})
|
|
101
|
+
# @data = data
|
|
102
|
+
# end
|
|
103
|
+
#
|
|
104
|
+
# private
|
|
105
|
+
#
|
|
106
|
+
# def read_attribute_for_validation(key)
|
|
107
|
+
# @data[key]
|
|
108
|
+
# end
|
|
109
|
+
# end
|
|
110
|
+
#
|
|
111
|
+
def read_attribute_for_validation(key)
|
|
112
|
+
send(key)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
Dir[File.dirname(__FILE__) + "/validations/*.rb"].sort.each do |path|
|
|
118
|
+
filename = File.basename(path)
|
|
119
|
+
require "active_model/validations/#{filename}"
|
|
120
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
module ActiveModel #:nodoc:
|
|
2
|
+
# A simple base class that can be used along with ActiveModel::Base.validates_with
|
|
3
|
+
#
|
|
4
|
+
# class Person < ActiveModel::Base
|
|
5
|
+
# validates_with MyValidator
|
|
6
|
+
# end
|
|
7
|
+
#
|
|
8
|
+
# class MyValidator < ActiveModel::Validator
|
|
9
|
+
# def validate
|
|
10
|
+
# if some_complex_logic
|
|
11
|
+
# record.errors[:base] = "This record is invalid"
|
|
12
|
+
# end
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# private
|
|
16
|
+
# def some_complex_logic
|
|
17
|
+
# # ...
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# Any class that inherits from ActiveModel::Validator will have access to <tt>record</tt>,
|
|
22
|
+
# which is an instance of the record being validated, and must implement a method called <tt>validate</tt>.
|
|
23
|
+
#
|
|
24
|
+
# class Person < ActiveModel::Base
|
|
25
|
+
# validates_with MyValidator
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# class MyValidator < ActiveModel::Validator
|
|
29
|
+
# def validate
|
|
30
|
+
# record # => The person instance being validated
|
|
31
|
+
# options # => Any non-standard options passed to validates_with
|
|
32
|
+
# end
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# To cause a validation error, you must add to the <tt>record<tt>'s errors directly
|
|
36
|
+
# from within the validators message
|
|
37
|
+
#
|
|
38
|
+
# class MyValidator < ActiveModel::Validator
|
|
39
|
+
# def validate
|
|
40
|
+
# record.errors[:base] << "This is some custom error message"
|
|
41
|
+
# record.errors[:first_name] << "This is some complex validation"
|
|
42
|
+
# # etc...
|
|
43
|
+
# end
|
|
44
|
+
# end
|
|
45
|
+
#
|
|
46
|
+
# To add behavior to the initialize method, use the following signature:
|
|
47
|
+
#
|
|
48
|
+
# class MyValidator < ActiveModel::Validator
|
|
49
|
+
# def initialize(record, options)
|
|
50
|
+
# super
|
|
51
|
+
# @my_custom_field = options[:field_name] || :first_name
|
|
52
|
+
# end
|
|
53
|
+
# end
|
|
54
|
+
class Validator
|
|
55
|
+
attr_reader :options
|
|
56
|
+
|
|
57
|
+
def initialize(options)
|
|
58
|
+
@options = options
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def validate(record)
|
|
62
|
+
raise NotImplementedError
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# EachValidator is a validator which iterates through the attributes given
|
|
67
|
+
# in the options hash invoking the validate_each method passing in the
|
|
68
|
+
# record, attribute and value.
|
|
69
|
+
#
|
|
70
|
+
# All ActiveModel validations are built on top of this Validator.
|
|
71
|
+
class EachValidator < Validator
|
|
72
|
+
attr_reader :attributes
|
|
73
|
+
|
|
74
|
+
def initialize(options)
|
|
75
|
+
@attributes = Array(options.delete(:attributes))
|
|
76
|
+
raise ":attributes cannot be blank" if @attributes.empty?
|
|
77
|
+
super
|
|
78
|
+
check_validity!
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def validate(record)
|
|
82
|
+
attributes.each do |attribute|
|
|
83
|
+
value = record.send(:read_attribute_for_validation, attribute)
|
|
84
|
+
next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
|
|
85
|
+
validate_each(record, attribute, value)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def validate_each(record, attribute, value)
|
|
90
|
+
raise NotImplementedError
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def check_validity!
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# BlockValidator is a special EachValidator which receives a block on initialization
|
|
98
|
+
# and call this block for each attribute being validated. +validates_each+ uses this
|
|
99
|
+
# Validator.
|
|
100
|
+
class BlockValidator < EachValidator
|
|
101
|
+
def initialize(options, &block)
|
|
102
|
+
@block = block
|
|
103
|
+
super
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def validate_each(record, attribute, value)
|
|
107
|
+
@block.call(record, attribute, value)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2004-2009 David Heinemeier Hansson
|
|
3
|
+
#
|
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
|
+
# a copy of this software and associated documentation files (the
|
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
|
+
# the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be
|
|
13
|
+
# included in all copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
|
|
25
|
+
$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
|
|
26
|
+
require 'active_support'
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
module ActiveModel
|
|
30
|
+
extend ActiveSupport::Autoload
|
|
31
|
+
|
|
32
|
+
autoload :AttributeMethods
|
|
33
|
+
autoload :Callbacks
|
|
34
|
+
autoload :Conversion
|
|
35
|
+
autoload :DeprecatedErrorMethods
|
|
36
|
+
autoload :Dirty
|
|
37
|
+
autoload :Errors
|
|
38
|
+
autoload :Lint
|
|
39
|
+
autoload :Name, 'active_model/naming'
|
|
40
|
+
autoload :Naming
|
|
41
|
+
autoload :Observer, 'active_model/observing'
|
|
42
|
+
autoload :Observing
|
|
43
|
+
autoload :Serialization
|
|
44
|
+
autoload :StateMachine
|
|
45
|
+
autoload :Translation
|
|
46
|
+
autoload :Validations
|
|
47
|
+
autoload :Validator
|
|
48
|
+
autoload :EachValidator, 'active_model/validator'
|
|
49
|
+
autoload :BlockValidator, 'active_model/validator'
|
|
50
|
+
autoload :VERSION
|
|
51
|
+
|
|
52
|
+
module Serializers
|
|
53
|
+
extend ActiveSupport::Autoload
|
|
54
|
+
|
|
55
|
+
autoload :JSON
|
|
56
|
+
autoload :Xml
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
require 'active_support/i18n'
|
|
61
|
+
I18n.load_path << File.dirname(__FILE__) + '/active_model/locale/en.yml'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'cases/helper'
|
|
2
|
+
|
|
3
|
+
class ModelWithAttributes
|
|
4
|
+
include ActiveModel::AttributeMethods
|
|
5
|
+
|
|
6
|
+
attribute_method_suffix ''
|
|
7
|
+
|
|
8
|
+
def attributes
|
|
9
|
+
{ :foo => 'value of foo' }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
def attribute(name)
|
|
14
|
+
attributes[name.to_sym]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class ModelWithAttributes2
|
|
19
|
+
include ActiveModel::AttributeMethods
|
|
20
|
+
|
|
21
|
+
attribute_method_suffix '_test'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class AttributeMethodsTest < ActiveModel::TestCase
|
|
25
|
+
test 'unrelated classes should not share attribute method matchers' do
|
|
26
|
+
assert_not_equal ModelWithAttributes.send(:attribute_method_matchers),
|
|
27
|
+
ModelWithAttributes2.send(:attribute_method_matchers)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test '#define_attribute_methods generates attribute methods' do
|
|
31
|
+
ModelWithAttributes.define_attribute_methods([:foo])
|
|
32
|
+
|
|
33
|
+
assert ModelWithAttributes.attribute_methods_generated?
|
|
34
|
+
assert ModelWithAttributes.new.respond_to?(:foo)
|
|
35
|
+
assert_equal "value of foo", ModelWithAttributes.new.foo
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test '#undefine_attribute_methods removes attribute methods' do
|
|
39
|
+
ModelWithAttributes.define_attribute_methods([:foo])
|
|
40
|
+
ModelWithAttributes.undefine_attribute_methods
|
|
41
|
+
|
|
42
|
+
assert !ModelWithAttributes.attribute_methods_generated?
|
|
43
|
+
assert !ModelWithAttributes.new.respond_to?(:foo)
|
|
44
|
+
assert_raises(NoMethodError) { ModelWithAttributes.new.foo }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require "cases/helper"
|
|
2
|
+
|
|
3
|
+
class CallbacksTest < ActiveModel::TestCase
|
|
4
|
+
|
|
5
|
+
class CallbackValidator
|
|
6
|
+
def around_create(model)
|
|
7
|
+
model.callbacks << :before_around_create
|
|
8
|
+
yield
|
|
9
|
+
model.callbacks << :after_around_create
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class ModelCallbacks
|
|
14
|
+
attr_reader :callbacks
|
|
15
|
+
extend ActiveModel::Callbacks
|
|
16
|
+
|
|
17
|
+
define_model_callbacks :create
|
|
18
|
+
define_model_callbacks :initialize, :only => :after
|
|
19
|
+
|
|
20
|
+
before_create :before_create
|
|
21
|
+
around_create CallbackValidator.new
|
|
22
|
+
|
|
23
|
+
after_create do |model|
|
|
24
|
+
model.callbacks << :after_create
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
after_create "@callbacks << :final_callback"
|
|
28
|
+
|
|
29
|
+
def initialize(valid=true)
|
|
30
|
+
@callbacks, @valid = [], valid
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def before_create
|
|
34
|
+
@callbacks << :before_create
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def create
|
|
38
|
+
_run_create_callbacks do
|
|
39
|
+
@callbacks << :create
|
|
40
|
+
@valid
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
test "complete callback chain" do
|
|
46
|
+
model = ModelCallbacks.new
|
|
47
|
+
model.create
|
|
48
|
+
assert_equal model.callbacks, [ :before_create, :before_around_create, :create,
|
|
49
|
+
:after_around_create, :after_create, :final_callback]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
test "after callbacks are always appended" do
|
|
53
|
+
model = ModelCallbacks.new
|
|
54
|
+
model.create
|
|
55
|
+
assert_equal model.callbacks.last, :final_callback
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
test "after callbacks are not executed if the block returns false" do
|
|
59
|
+
model = ModelCallbacks.new(false)
|
|
60
|
+
model.create
|
|
61
|
+
assert_equal model.callbacks, [ :before_create, :before_around_create,
|
|
62
|
+
:create, :after_around_create]
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
test "only selects which types of callbacks should be created" do
|
|
66
|
+
assert !ModelCallbacks.respond_to?(:before_initialize)
|
|
67
|
+
assert !ModelCallbacks.respond_to?(:around_initialize)
|
|
68
|
+
assert ModelCallbacks.respond_to?(:after_initialize)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require File.expand_path('../../../../vendor/gems/environment', __FILE__)
|
|
3
|
+
rescue LoadError
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
lib = File.expand_path('../../../lib', __FILE__)
|
|
7
|
+
$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
|
|
8
|
+
|
|
9
|
+
require 'config'
|
|
10
|
+
require 'active_model'
|
|
11
|
+
require 'active_model/test_case'
|
|
12
|
+
|
|
13
|
+
# Show backtraces for deprecated behavior for quicker cleanup.
|
|
14
|
+
ActiveSupport::Deprecation.debug = true
|
|
15
|
+
|
|
16
|
+
require 'rubygems'
|
|
17
|
+
require 'test/unit'
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
require 'ruby-debug'
|
|
21
|
+
Debugger.start
|
|
22
|
+
rescue LoadError
|
|
23
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require "cases/helper"
|
|
2
|
+
|
|
3
|
+
class LintTest < ActiveModel::TestCase
|
|
4
|
+
include ActiveModel::Lint::Tests
|
|
5
|
+
|
|
6
|
+
class CompliantModel
|
|
7
|
+
extend ActiveModel::Naming
|
|
8
|
+
|
|
9
|
+
def to_model
|
|
10
|
+
self
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def valid?() true end
|
|
14
|
+
def new_record?() true end
|
|
15
|
+
def destroyed?() true end
|
|
16
|
+
|
|
17
|
+
def errors
|
|
18
|
+
obj = Object.new
|
|
19
|
+
def obj.[](key) [] end
|
|
20
|
+
def obj.full_messages() [] end
|
|
21
|
+
obj
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def setup
|
|
26
|
+
@model = CompliantModel.new
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'cases/helper'
|
|
2
|
+
require 'models/track_back'
|
|
3
|
+
|
|
4
|
+
class NamingTest < ActiveModel::TestCase
|
|
5
|
+
def setup
|
|
6
|
+
@model_name = ActiveModel::Name.new(Post::TrackBack)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def test_singular
|
|
10
|
+
assert_equal 'post_track_back', @model_name.singular
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_plural
|
|
14
|
+
assert_equal 'post_track_backs', @model_name.plural
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_element
|
|
18
|
+
assert_equal 'track_back', @model_name.element
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_collection
|
|
22
|
+
assert_equal 'post/track_backs', @model_name.collection
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_partial_path
|
|
26
|
+
assert_equal 'post/track_backs/track_back', @model_name.partial_path
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
require 'cases/helper'
|
|
2
|
+
|
|
3
|
+
class ObservedModel
|
|
4
|
+
include ActiveModel::Observing
|
|
5
|
+
|
|
6
|
+
class Observer
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class FooObserver < ActiveModel::Observer
|
|
11
|
+
class << self
|
|
12
|
+
public :new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_accessor :stub
|
|
16
|
+
|
|
17
|
+
def on_spec(record)
|
|
18
|
+
stub.event_with(record) if stub
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Foo
|
|
23
|
+
include ActiveModel::Observing
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class ObservingTest < ActiveModel::TestCase
|
|
27
|
+
def setup
|
|
28
|
+
ObservedModel.observers.clear
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
test "initializes model with no cached observers" do
|
|
32
|
+
assert ObservedModel.observers.empty?, "Not empty: #{ObservedModel.observers.inspect}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
test "stores cached observers in an array" do
|
|
36
|
+
ObservedModel.observers << :foo
|
|
37
|
+
assert ObservedModel.observers.include?(:foo), ":foo not in #{ObservedModel.observers.inspect}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
test "flattens array of assigned cached observers" do
|
|
41
|
+
ObservedModel.observers = [[:foo], :bar]
|
|
42
|
+
assert ObservedModel.observers.include?(:foo), ":foo not in #{ObservedModel.observers.inspect}"
|
|
43
|
+
assert ObservedModel.observers.include?(:bar), ":bar not in #{ObservedModel.observers.inspect}"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
test "instantiates observer names passed as strings" do
|
|
47
|
+
ObservedModel.observers << 'foo_observer'
|
|
48
|
+
FooObserver.expects(:instance)
|
|
49
|
+
ObservedModel.instantiate_observers
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
test "instantiates observer names passed as symbols" do
|
|
53
|
+
ObservedModel.observers << :foo_observer
|
|
54
|
+
FooObserver.expects(:instance)
|
|
55
|
+
ObservedModel.instantiate_observers
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
test "instantiates observer classes" do
|
|
59
|
+
ObservedModel.observers << ObservedModel::Observer
|
|
60
|
+
ObservedModel::Observer.expects(:instance)
|
|
61
|
+
ObservedModel.instantiate_observers
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
test "passes observers to subclasses" do
|
|
65
|
+
FooObserver.instance
|
|
66
|
+
bar = Class.new(Foo)
|
|
67
|
+
assert_equal Foo.count_observers, bar.count_observers
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class ObserverTest < ActiveModel::TestCase
|
|
72
|
+
def setup
|
|
73
|
+
ObservedModel.observers = :foo_observer
|
|
74
|
+
FooObserver.instance_eval do
|
|
75
|
+
alias_method :original_observed_classes, :observed_classes
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def teardown
|
|
80
|
+
FooObserver.instance_eval do
|
|
81
|
+
undef_method :observed_classes
|
|
82
|
+
alias_method :observed_classes, :original_observed_classes
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
test "guesses implicit observable model name" do
|
|
87
|
+
assert_equal Foo, FooObserver.observed_class
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
test "tracks implicit observable models" do
|
|
91
|
+
instance = FooObserver.new
|
|
92
|
+
assert instance.send(:observed_classes).include?(Foo), "Foo not in #{instance.send(:observed_classes).inspect}"
|
|
93
|
+
assert !instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{instance.send(:observed_classes).inspect}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
test "tracks explicit observed model class" do
|
|
97
|
+
old_instance = FooObserver.new
|
|
98
|
+
assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}"
|
|
99
|
+
FooObserver.observe ObservedModel
|
|
100
|
+
instance = FooObserver.new
|
|
101
|
+
assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
test "tracks explicit observed model as string" do
|
|
105
|
+
old_instance = FooObserver.new
|
|
106
|
+
assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}"
|
|
107
|
+
FooObserver.observe 'observed_model'
|
|
108
|
+
instance = FooObserver.new
|
|
109
|
+
assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
test "tracks explicit observed model as symbol" do
|
|
113
|
+
old_instance = FooObserver.new
|
|
114
|
+
assert !old_instance.send(:observed_classes).include?(ObservedModel), "ObservedModel in #{old_instance.send(:observed_classes).inspect}"
|
|
115
|
+
FooObserver.observe :observed_model
|
|
116
|
+
instance = FooObserver.new
|
|
117
|
+
assert instance.send(:observed_classes).include?(ObservedModel), "ObservedModel not in #{instance.send(:observed_classes).inspect}"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
test "calls existing observer event" do
|
|
121
|
+
foo = Foo.new
|
|
122
|
+
FooObserver.instance.stub = stub
|
|
123
|
+
FooObserver.instance.stub.expects(:event_with).with(foo)
|
|
124
|
+
Foo.send(:changed)
|
|
125
|
+
Foo.send(:notify_observers, :on_spec, foo)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
test "skips nonexistent observer event" do
|
|
129
|
+
foo = Foo.new
|
|
130
|
+
Foo.send(:changed)
|
|
131
|
+
Foo.send(:notify_observers, :whatever, foo)
|
|
132
|
+
end
|
|
133
|
+
end
|