cassandra_object 0.6.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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
|