ardm 0.0.1
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.
- checksums.yaml +15 -0
- data/.gitignore +35 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/Rakefile +4 -0
- data/ardm.gemspec +29 -0
- data/db/.gitignore +1 -0
- data/lib/ardm/active_record/associations.rb +80 -0
- data/lib/ardm/active_record/base.rb +49 -0
- data/lib/ardm/active_record/dirty.rb +25 -0
- data/lib/ardm/active_record/hooks.rb +31 -0
- data/lib/ardm/active_record/inheritance.rb +37 -0
- data/lib/ardm/active_record/is/state_machine.rb +21 -0
- data/lib/ardm/active_record/is.rb +22 -0
- data/lib/ardm/active_record/not_found.rb +7 -0
- data/lib/ardm/active_record/predicate_builder/array_handler.rb +31 -0
- data/lib/ardm/active_record/predicate_builder/rails3.rb +147 -0
- data/lib/ardm/active_record/predicate_builder/rails4.rb +139 -0
- data/lib/ardm/active_record/predicate_builder/relation_handler.rb +15 -0
- data/lib/ardm/active_record/predicate_builder.rb +19 -0
- data/lib/ardm/active_record/property.rb +357 -0
- data/lib/ardm/active_record/query.rb +108 -0
- data/lib/ardm/active_record/record.rb +70 -0
- data/lib/ardm/active_record/relation.rb +83 -0
- data/lib/ardm/active_record/repository.rb +38 -0
- data/lib/ardm/active_record/serialization.rb +164 -0
- data/lib/ardm/active_record/storage_names.rb +28 -0
- data/lib/ardm/active_record/validations.rb +111 -0
- data/lib/ardm/active_record.rb +43 -0
- data/lib/ardm/data_mapper/not_found.rb +5 -0
- data/lib/ardm/data_mapper/record.rb +41 -0
- data/lib/ardm/data_mapper.rb +5 -0
- data/lib/ardm/env.rb +5 -0
- data/lib/ardm/property/api_key.rb +30 -0
- data/lib/ardm/property/bcrypt_hash.rb +31 -0
- data/lib/ardm/property/binary.rb +23 -0
- data/lib/ardm/property/boolean.rb +29 -0
- data/lib/ardm/property/class.rb +19 -0
- data/lib/ardm/property/comma_separated_list.rb +28 -0
- data/lib/ardm/property/csv.rb +35 -0
- data/lib/ardm/property/date.rb +12 -0
- data/lib/ardm/property/datetime.rb +12 -0
- data/lib/ardm/property/decimal.rb +38 -0
- data/lib/ardm/property/discriminator.rb +65 -0
- data/lib/ardm/property/enum.rb +51 -0
- data/lib/ardm/property/epoch_time.rb +38 -0
- data/lib/ardm/property/file_path.rb +25 -0
- data/lib/ardm/property/flag.rb +65 -0
- data/lib/ardm/property/float.rb +18 -0
- data/lib/ardm/property/integer.rb +24 -0
- data/lib/ardm/property/invalid_value_error.rb +22 -0
- data/lib/ardm/property/ip_address.rb +35 -0
- data/lib/ardm/property/json.rb +49 -0
- data/lib/ardm/property/lookup.rb +29 -0
- data/lib/ardm/property/numeric.rb +40 -0
- data/lib/ardm/property/object.rb +36 -0
- data/lib/ardm/property/paranoid_boolean.rb +18 -0
- data/lib/ardm/property/paranoid_datetime.rb +17 -0
- data/lib/ardm/property/regexp.rb +22 -0
- data/lib/ardm/property/serial.rb +16 -0
- data/lib/ardm/property/slug.rb +29 -0
- data/lib/ardm/property/string.rb +40 -0
- data/lib/ardm/property/support/dirty_minder.rb +169 -0
- data/lib/ardm/property/support/flags.rb +41 -0
- data/lib/ardm/property/support/paranoid_base.rb +78 -0
- data/lib/ardm/property/text.rb +11 -0
- data/lib/ardm/property/time.rb +12 -0
- data/lib/ardm/property/uri.rb +27 -0
- data/lib/ardm/property/uuid.rb +65 -0
- data/lib/ardm/property/validation.rb +208 -0
- data/lib/ardm/property/yaml.rb +38 -0
- data/lib/ardm/property.rb +891 -0
- data/lib/ardm/property_set.rb +152 -0
- data/lib/ardm/query/expression.rb +85 -0
- data/lib/ardm/query/ext/symbol.rb +37 -0
- data/lib/ardm/query/operator.rb +64 -0
- data/lib/ardm/record.rb +1 -0
- data/lib/ardm/support/assertions.rb +8 -0
- data/lib/ardm/support/deprecate.rb +12 -0
- data/lib/ardm/support/descendant_set.rb +89 -0
- data/lib/ardm/support/equalizer.rb +48 -0
- data/lib/ardm/support/ext/array.rb +22 -0
- data/lib/ardm/support/ext/blank.rb +25 -0
- data/lib/ardm/support/ext/hash.rb +67 -0
- data/lib/ardm/support/ext/module.rb +47 -0
- data/lib/ardm/support/ext/object.rb +57 -0
- data/lib/ardm/support/ext/string.rb +24 -0
- data/lib/ardm/support/ext/try_dup.rb +12 -0
- data/lib/ardm/support/hook.rb +405 -0
- data/lib/ardm/support/lazy_array.rb +451 -0
- data/lib/ardm/support/local_object_space.rb +13 -0
- data/lib/ardm/support/logger.rb +201 -0
- data/lib/ardm/support/mash.rb +176 -0
- data/lib/ardm/support/naming_conventions.rb +90 -0
- data/lib/ardm/support/ordered_set.rb +380 -0
- data/lib/ardm/support/subject.rb +33 -0
- data/lib/ardm/support/subject_set.rb +250 -0
- data/lib/ardm/version.rb +3 -0
- data/lib/ardm.rb +56 -0
- data/spec/fixtures/api_user.rb +11 -0
- data/spec/fixtures/article.rb +22 -0
- data/spec/fixtures/bookmark.rb +14 -0
- data/spec/fixtures/invention.rb +5 -0
- data/spec/fixtures/network_node.rb +23 -0
- data/spec/fixtures/person.rb +17 -0
- data/spec/fixtures/software_package.rb +22 -0
- data/spec/fixtures/ticket.rb +12 -0
- data/spec/fixtures/tshirt.rb +15 -0
- data/spec/integration/api_key_spec.rb +25 -0
- data/spec/integration/bcrypt_hash_spec.rb +45 -0
- data/spec/integration/comma_separated_list_spec.rb +85 -0
- data/spec/integration/dirty_minder_spec.rb +197 -0
- data/spec/integration/enum_spec.rb +79 -0
- data/spec/integration/epoch_time_spec.rb +59 -0
- data/spec/integration/file_path_spec.rb +158 -0
- data/spec/integration/flag_spec.rb +72 -0
- data/spec/integration/ip_address_spec.rb +151 -0
- data/spec/integration/json_spec.rb +70 -0
- data/spec/integration/slug_spec.rb +65 -0
- data/spec/integration/uri_spec.rb +136 -0
- data/spec/integration/uuid_spec.rb +102 -0
- data/spec/integration/yaml_spec.rb +85 -0
- data/spec/public/property/binary_spec.rb +41 -0
- data/spec/public/property/boolean_spec.rb +30 -0
- data/spec/public/property/class_spec.rb +28 -0
- data/spec/public/property/date_spec.rb +22 -0
- data/spec/public/property/date_time_spec.rb +22 -0
- data/spec/public/property/decimal_spec.rb +23 -0
- data/spec/public/property/discriminator_spec.rb +133 -0
- data/spec/public/property/float_spec.rb +22 -0
- data/spec/public/property/integer_spec.rb +22 -0
- data/spec/public/property/object_spec.rb +103 -0
- data/spec/public/property/serial_spec.rb +22 -0
- data/spec/public/property/string_spec.rb +22 -0
- data/spec/public/property/text_spec.rb +23 -0
- data/spec/public/property/time_spec.rb +22 -0
- data/spec/public/property_spec.rb +316 -0
- data/spec/rcov.opts +6 -0
- data/spec/schema.rb +86 -0
- data/spec/semipublic/property/binary_spec.rb +14 -0
- data/spec/semipublic/property/boolean_spec.rb +48 -0
- data/spec/semipublic/property/class_spec.rb +36 -0
- data/spec/semipublic/property/date_spec.rb +44 -0
- data/spec/semipublic/property/date_time_spec.rb +47 -0
- data/spec/semipublic/property/decimal_spec.rb +83 -0
- data/spec/semipublic/property/discriminator_spec.rb +22 -0
- data/spec/semipublic/property/float_spec.rb +83 -0
- data/spec/semipublic/property/integer_spec.rb +83 -0
- data/spec/semipublic/property/lookup_spec.rb +27 -0
- data/spec/semipublic/property/serial_spec.rb +14 -0
- data/spec/semipublic/property/string_spec.rb +14 -0
- data/spec/semipublic/property/text_spec.rb +30 -0
- data/spec/semipublic/property/time_spec.rb +49 -0
- data/spec/semipublic/property_spec.rb +51 -0
- data/spec/shared/flags_shared_spec.rb +36 -0
- data/spec/shared/identity_function_group.rb +5 -0
- data/spec/shared/public_property_spec.rb +229 -0
- data/spec/shared/semipublic_property_spec.rb +159 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/unit/bcrypt_hash_spec.rb +154 -0
- data/spec/unit/csv_spec.rb +139 -0
- data/spec/unit/dirty_minder_spec.rb +64 -0
- data/spec/unit/enum_spec.rb +125 -0
- data/spec/unit/epoch_time_spec.rb +72 -0
- data/spec/unit/file_path_spec.rb +75 -0
- data/spec/unit/flag_spec.rb +114 -0
- data/spec/unit/ip_address_spec.rb +109 -0
- data/spec/unit/json_spec.rb +127 -0
- data/spec/unit/paranoid_boolean_spec.rb +142 -0
- data/spec/unit/paranoid_datetime_spec.rb +149 -0
- data/spec/unit/regexp_spec.rb +62 -0
- data/spec/unit/uri_spec.rb +64 -0
- data/spec/unit/yaml_spec.rb +111 -0
- data/tasks/spec.rake +40 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +350 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
require 'active_record'
|
|
3
|
+
|
|
4
|
+
module Ardm
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
module Relation
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
included do
|
|
10
|
+
alias_method :destory_without_ardm, :destroy
|
|
11
|
+
alias_method :update_without_ardm, :update
|
|
12
|
+
|
|
13
|
+
# we need to overrite the implementation in the class
|
|
14
|
+
class_eval do
|
|
15
|
+
def update(*a)
|
|
16
|
+
if a.size == 1
|
|
17
|
+
# need to translate attributes
|
|
18
|
+
options = @klass.send(:dump_properties_hash, a.first)
|
|
19
|
+
update_all(options)
|
|
20
|
+
else
|
|
21
|
+
update_without_ardm(*a)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def destroy(id = nil)
|
|
26
|
+
if id
|
|
27
|
+
destroy_without_ardm(id)
|
|
28
|
+
else
|
|
29
|
+
destroy_all
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def first_or_create(attributes = nil, options = {}, &block)
|
|
34
|
+
first(attributes) || create(attributes, options, &block)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def first_or_create!(attributes = nil, options = {}, &block)
|
|
38
|
+
first(attributes) || create!(attributes, options, &block)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def first_or_initialize(attributes = nil, options = {}, &block)
|
|
42
|
+
first(attributes) || create(attributes, options, &block)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def all(options={})
|
|
48
|
+
apply_finder_options(options)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def apply_finder_options(options)
|
|
52
|
+
return super if options.nil? || options.empty?
|
|
53
|
+
options = options.dup
|
|
54
|
+
conditions = options.slice!(*::ActiveRecord::SpawnMethods::VALID_FIND_OPTIONS)
|
|
55
|
+
super(options).where(conditions)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def calculate(operation, column_name, options={})
|
|
59
|
+
if property = properties[column_name]
|
|
60
|
+
column_name = property.field
|
|
61
|
+
end
|
|
62
|
+
super(operation, column_name, options)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def method_missing(meth, *a, &b)
|
|
66
|
+
if a.empty? && association = reflect_on_association(meth.to_sym)
|
|
67
|
+
case association.macro
|
|
68
|
+
when :belongs_to
|
|
69
|
+
association.klass.where(klass.primary_key => self.select(association.foreign_key))
|
|
70
|
+
when :has_many, :has_one
|
|
71
|
+
association.klass.where(association.foreign_key => self.clone)
|
|
72
|
+
end
|
|
73
|
+
else
|
|
74
|
+
super
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def destroy!
|
|
79
|
+
delete_all
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module Ardm
|
|
4
|
+
module ActiveRecord
|
|
5
|
+
module Repository
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
def repository
|
|
9
|
+
self.class.repository
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module ClassMethods
|
|
13
|
+
def repository
|
|
14
|
+
if block_given?
|
|
15
|
+
yield
|
|
16
|
+
else
|
|
17
|
+
Ardm::ActiveRecord::Repository::Proxy.new self
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Proxy
|
|
23
|
+
def initialize(model)
|
|
24
|
+
@model = model
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def adapter
|
|
28
|
+
self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def select(*args)
|
|
32
|
+
array_of_hashes = @model.connection.select_all(@model.send(:sanitize_sql_array, args))
|
|
33
|
+
array_of_hashes.map { |h| Hashie::Mash.new(h) }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module Ardm
|
|
4
|
+
module ActiveRecord
|
|
5
|
+
module Serialization
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
included do
|
|
9
|
+
# Returns a hash of all the attributes that have been specified for
|
|
10
|
+
# serialization as keys and their class restriction as values.
|
|
11
|
+
class_attribute :serialized_attributes, instance_accessor: false
|
|
12
|
+
self.serialized_attributes = {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module ClassMethods
|
|
16
|
+
##
|
|
17
|
+
# :method: serialized_attributes
|
|
18
|
+
#
|
|
19
|
+
# Returns a hash of all the attributes that have been specified for
|
|
20
|
+
# serialization as keys and their class restriction as values.
|
|
21
|
+
|
|
22
|
+
# If you have an attribute that needs to be saved to the database as an
|
|
23
|
+
# object, and retrieved as the same object, then specify the name of that
|
|
24
|
+
# attribute using this method and it will be handled automatically. The
|
|
25
|
+
# serialization is done through YAML. If +class_name+ is specified, the
|
|
26
|
+
# serialized object must be of that class on retrieval or
|
|
27
|
+
# <tt>SerializationTypeMismatch</tt> will be raised.
|
|
28
|
+
#
|
|
29
|
+
# ==== Parameters
|
|
30
|
+
#
|
|
31
|
+
# * +attr_name+ - The field name that should be serialized.
|
|
32
|
+
# * +class_name+ - Optional, class name that the object type should be equal to.
|
|
33
|
+
#
|
|
34
|
+
# ==== Example
|
|
35
|
+
#
|
|
36
|
+
# # Serialize a preferences attribute.
|
|
37
|
+
# class User < ActiveRecord::Base
|
|
38
|
+
# serialize :preferences
|
|
39
|
+
# end
|
|
40
|
+
def serialize(attr_name, class_name = Object)
|
|
41
|
+
include Behavior
|
|
42
|
+
|
|
43
|
+
coder = if [:load, :dump].all? { |x| class_name.respond_to?(x) }
|
|
44
|
+
class_name
|
|
45
|
+
else
|
|
46
|
+
Coders::YAMLColumn.new(class_name)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# merge new serialized attribute and create new hash to ensure that each class in inheritance hierarchy
|
|
50
|
+
# has its own hash of own serialized attributes
|
|
51
|
+
self.serialized_attributes = serialized_attributes.merge(attr_name.to_s => coder)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# *DEPRECATED*: Use ActiveRecord::AttributeMethods::Serialization::ClassMethods#serialized_attributes class level method instead.
|
|
56
|
+
def serialized_attributes
|
|
57
|
+
message = "Instance level serialized_attributes method is deprecated, please use class level method."
|
|
58
|
+
ActiveSupport::Deprecation.warn message
|
|
59
|
+
defined?(@serialized_attributes) ? @serialized_attributes : self.class.serialized_attributes
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
class Type # :nodoc:
|
|
63
|
+
def initialize(column)
|
|
64
|
+
@column = column
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def type_cast(value)
|
|
68
|
+
if value.state == :serialized
|
|
69
|
+
value.unserialized_value @column.type_cast value.value
|
|
70
|
+
else
|
|
71
|
+
value.unserialized_value
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def type
|
|
76
|
+
@column.type
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
class Attribute < Struct.new(:coder, :value, :state) # :nodoc:
|
|
81
|
+
def unserialized_value(v = value)
|
|
82
|
+
state == :serialized ? unserialize(v) : value
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def serialized_value
|
|
86
|
+
state == :unserialized ? serialize : value
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def unserialize(v)
|
|
90
|
+
self.state = :unserialized
|
|
91
|
+
self.value = coder.load(v)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def serialize
|
|
95
|
+
self.state = :serialized
|
|
96
|
+
self.value = coder.dump(value)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# This is only added to the model when serialize is called, which
|
|
101
|
+
# ensures we do not make things slower when serialization is not used.
|
|
102
|
+
module Behavior # :nodoc:
|
|
103
|
+
extend ActiveSupport::Concern
|
|
104
|
+
|
|
105
|
+
module ClassMethods # :nodoc:
|
|
106
|
+
def initialize_attributes(attributes, options = {})
|
|
107
|
+
serialized = (options.delete(:serialized) { true }) ? :serialized : :unserialized
|
|
108
|
+
super(attributes, options)
|
|
109
|
+
|
|
110
|
+
serialized_attributes.each do |key, coder|
|
|
111
|
+
if attributes.key?(key)
|
|
112
|
+
attributes[key] = Attribute.new(coder, attributes[key], serialized)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
attributes
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def type_cast_attribute_for_write(column, value)
|
|
121
|
+
if column && coder = self.class.serialized_attributes[column.name]
|
|
122
|
+
Attribute.new(coder, value, :unserialized)
|
|
123
|
+
else
|
|
124
|
+
super
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def _field_changed?(attr, old, value)
|
|
129
|
+
if self.class.serialized_attributes.include?(attr)
|
|
130
|
+
old != value
|
|
131
|
+
else
|
|
132
|
+
super
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def read_attribute_before_type_cast(attr_name)
|
|
137
|
+
if self.class.serialized_attributes.include?(attr_name)
|
|
138
|
+
super.unserialized_value
|
|
139
|
+
else
|
|
140
|
+
super
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def attributes_before_type_cast
|
|
145
|
+
super.dup.tap do |attributes|
|
|
146
|
+
self.class.serialized_attributes.each_key do |key|
|
|
147
|
+
if attributes.key?(key)
|
|
148
|
+
attributes[key] = attributes[key].unserialized_value
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def typecasted_attribute_value(name)
|
|
155
|
+
if self.class.serialized_attributes.include?(name)
|
|
156
|
+
@attributes[name].serialized_value
|
|
157
|
+
else
|
|
158
|
+
super
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
|
|
3
|
+
module Ardm
|
|
4
|
+
module ActiveRecord
|
|
5
|
+
module StorageNames
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
module ClassMethods
|
|
9
|
+
def storage_names
|
|
10
|
+
Ardm::ActiveRecord::StorageNames::Proxy.new(self)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Proxy
|
|
15
|
+
def initialize(model)
|
|
16
|
+
@model = model
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def []=(repo, table_name)
|
|
20
|
+
unless repo == :default
|
|
21
|
+
raise ArgumentError, "repositories other than :default not supported."
|
|
22
|
+
end
|
|
23
|
+
@model.table_name = table_name
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
require 'active_model/validations'
|
|
3
|
+
|
|
4
|
+
module Ardm
|
|
5
|
+
module ActiveRecord
|
|
6
|
+
# Extend ActiveRecord to support DataMapper validations
|
|
7
|
+
module Validations
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
include ActiveModel::Validations
|
|
11
|
+
|
|
12
|
+
# Extract and convert options from DM style to AR style
|
|
13
|
+
def self.extract_options(fields, *keep)
|
|
14
|
+
keep += [:on, :message, :if, :unless]
|
|
15
|
+
|
|
16
|
+
if Hash === fields.last
|
|
17
|
+
ar = fields.pop.dup
|
|
18
|
+
ar[:on] = ar.delete(:when) if ar[:when] && [:create, :update].include?(ar[:when])
|
|
19
|
+
ar[:maximum] = ar.delete(:max) if ar[:max]
|
|
20
|
+
ar[:in] = ar.delete(:set) if ar[:set]
|
|
21
|
+
|
|
22
|
+
removed = ar.slice!(*keep)
|
|
23
|
+
unless removed.empty?
|
|
24
|
+
$stderr.puts "WARNING validation options not handled: #{removed.inspect} in:"
|
|
25
|
+
$stderr.puts caller[0..1]
|
|
26
|
+
end
|
|
27
|
+
else
|
|
28
|
+
ar = {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
[fields, ar]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
module ClassMethods
|
|
35
|
+
|
|
36
|
+
def validates_belongs_to(*fields)
|
|
37
|
+
fields, options = Ardm::ActiveRecord::Validations.extract_options(fields)
|
|
38
|
+
validates *fields, presence: options
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def validates_presence_of(*fields)
|
|
42
|
+
fields, options = Ardm::ActiveRecord::Validations.extract_options(fields)
|
|
43
|
+
validates *fields, presence: options
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def validates_length_of(*fields)
|
|
47
|
+
fields, options = Ardm::ActiveRecord::Validations.extract_options(fields, :in, :within, :maximum, :minimum, :is)
|
|
48
|
+
validates *fields, length: options
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def validates_uniqueness_of(*fields)
|
|
52
|
+
fields, options = Ardm::ActiveRecord::Validations.extract_options(fields, :scope)
|
|
53
|
+
fields = fields.map do |field|
|
|
54
|
+
if property = properties[field]
|
|
55
|
+
property.field
|
|
56
|
+
elsif assoc = reflect_on_association(field)
|
|
57
|
+
assoc.foreign_key
|
|
58
|
+
else
|
|
59
|
+
field
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
if options[:scope]
|
|
64
|
+
options[:scope] = Array(options[:scope]).map do |scope|
|
|
65
|
+
assoc = reflect_on_association(scope)
|
|
66
|
+
assoc ? assoc.foreign_key : scope
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
validates *fields, uniqueness: options
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def validates_within(*fields)
|
|
74
|
+
fields, options = Ardm::ActiveRecord::Validations.extract_options(fields, :in)
|
|
75
|
+
validates *fields, inclusion: options
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Possible formats:
|
|
79
|
+
#
|
|
80
|
+
# validates_with_method :attr, :method_name
|
|
81
|
+
# validates_with_method :attr, method: :method_name
|
|
82
|
+
# validates_with_method :method_name, options: "here"
|
|
83
|
+
def validates_with_method(*fields)
|
|
84
|
+
fields, options = Ardm::ActiveRecord::Validations.extract_options(fields, :method)
|
|
85
|
+
|
|
86
|
+
# validates_with_method :attr, :method_name
|
|
87
|
+
att, meth = *fields
|
|
88
|
+
|
|
89
|
+
# validates_with_method :attr, method: :method_name
|
|
90
|
+
meth = options[:method] if options[:method]
|
|
91
|
+
|
|
92
|
+
# validates_with_method :method_name
|
|
93
|
+
att, meth = :base, att if !meth
|
|
94
|
+
|
|
95
|
+
validates_with_block(att) do
|
|
96
|
+
self.send(meth)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def validates_with_block(att=nil, &block)
|
|
101
|
+
validate do |record|
|
|
102
|
+
val, message = instance_eval(&block)
|
|
103
|
+
unless val
|
|
104
|
+
errors.add(att, message)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
puts __FILE__
|
|
2
|
+
require 'ardm'
|
|
3
|
+
|
|
4
|
+
# only load support libs in active record mode (dm will supply its own libs)
|
|
5
|
+
require 'ardm/support/ext/blank'
|
|
6
|
+
require 'ardm/support/ext/hash'
|
|
7
|
+
require 'ardm/support/ext/object'
|
|
8
|
+
require 'ardm/support/ext/string'
|
|
9
|
+
|
|
10
|
+
require 'ardm/support/ext/module'
|
|
11
|
+
require 'ardm/support/ext/array'
|
|
12
|
+
require 'ardm/support/ext/try_dup'
|
|
13
|
+
|
|
14
|
+
require 'ardm/support/mash'
|
|
15
|
+
require 'ardm/support/deprecate'
|
|
16
|
+
require 'ardm/support/descendant_set'
|
|
17
|
+
require 'ardm/support/equalizer'
|
|
18
|
+
require 'ardm/support/assertions'
|
|
19
|
+
require 'ardm/support/lazy_array'
|
|
20
|
+
require 'ardm/support/local_object_space'
|
|
21
|
+
require 'ardm/support/hook'
|
|
22
|
+
require 'ardm/support/subject'
|
|
23
|
+
require 'ardm/support/ordered_set'
|
|
24
|
+
require 'ardm/support/subject_set'
|
|
25
|
+
require 'ardm/support/descendant_set'
|
|
26
|
+
|
|
27
|
+
require 'active_record'
|
|
28
|
+
require 'active_record/relation'
|
|
29
|
+
|
|
30
|
+
require 'ardm/active_record/record'
|
|
31
|
+
require 'ardm/active_record/relation'
|
|
32
|
+
|
|
33
|
+
module Ardm
|
|
34
|
+
Record = Ardm::ActiveRecord::Record
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#::ActiveRecord::Base.class_eval do
|
|
38
|
+
# include Ardm::ActiveRecord::Base
|
|
39
|
+
#end
|
|
40
|
+
|
|
41
|
+
::ActiveRecord::Relation.class_eval do
|
|
42
|
+
include Ardm::ActiveRecord::Relation
|
|
43
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'awsm/resource'
|
|
2
|
+
|
|
3
|
+
module Ardm
|
|
4
|
+
module DataMapper
|
|
5
|
+
module Record
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
NotFound = DataMapper::ObjectNotFoundError
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
def inherited(base)
|
|
12
|
+
base.send(:include, DataMapper::Resource)
|
|
13
|
+
base.send(:include, Awsm::Resource)
|
|
14
|
+
#base.send(:extend, DataMapper::CollectionRaise)
|
|
15
|
+
|
|
16
|
+
unless %w[Alert Association Nonce Account::Cancellation::Handler].include?(base.name)
|
|
17
|
+
base.timestamps :at
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
extend Forwardable
|
|
22
|
+
def datamapper() DataMapper end
|
|
23
|
+
def_delegators :datamapper, :repository, :finalize, :logger, :logger=
|
|
24
|
+
|
|
25
|
+
def execute_sql(sql)
|
|
26
|
+
DataMapper.repository.adapter.execute(sql)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def alias_attribute(new, old)
|
|
30
|
+
alias_method new, old
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def attr_accessible(*attrs)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def abstract_class=(val)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/ardm/env.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'ardm/property/string'
|
|
2
|
+
|
|
3
|
+
require 'digest/sha1'
|
|
4
|
+
|
|
5
|
+
module Ardm
|
|
6
|
+
class Property
|
|
7
|
+
class APIKey < String
|
|
8
|
+
|
|
9
|
+
# The amount of random seed data to use to generate tha API Key
|
|
10
|
+
PADDING = 256
|
|
11
|
+
|
|
12
|
+
length 40
|
|
13
|
+
unique true
|
|
14
|
+
default proc { APIKey.generate }
|
|
15
|
+
|
|
16
|
+
#
|
|
17
|
+
# Generates a new API Key.
|
|
18
|
+
#
|
|
19
|
+
# @return [String]
|
|
20
|
+
# The new API Key.
|
|
21
|
+
#
|
|
22
|
+
def self.generate
|
|
23
|
+
sha1 = Digest::SHA1.new
|
|
24
|
+
|
|
25
|
+
PADDING.times { sha1 << rand(256).chr }
|
|
26
|
+
return sha1.hexdigest
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'ardm/property/string'
|
|
2
|
+
require 'bcrypt'
|
|
3
|
+
|
|
4
|
+
module Ardm
|
|
5
|
+
class Property
|
|
6
|
+
class BCryptHash < String
|
|
7
|
+
load_as BCrypt::Password
|
|
8
|
+
|
|
9
|
+
length 60
|
|
10
|
+
|
|
11
|
+
def load(value)
|
|
12
|
+
unless value.nil?
|
|
13
|
+
begin
|
|
14
|
+
value_loaded?(value) ? value : BCrypt::Password.new(value)
|
|
15
|
+
rescue BCrypt::Errors::InvalidHash
|
|
16
|
+
BCrypt::Password.create(value, :cost => BCrypt::Engine::DEFAULT_COST)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def dump(value)
|
|
22
|
+
load(value)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def typecast(value)
|
|
26
|
+
load(value)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end # class BCryptHash
|
|
30
|
+
end # class Property
|
|
31
|
+
end # module Ardm
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'ardm/property/string'
|
|
2
|
+
|
|
3
|
+
module Ardm
|
|
4
|
+
class Property
|
|
5
|
+
class Binary < String
|
|
6
|
+
|
|
7
|
+
if RUBY_VERSION >= "1.9"
|
|
8
|
+
|
|
9
|
+
def load(value)
|
|
10
|
+
super.dup.force_encoding("BINARY") unless value.nil?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def dump(value)
|
|
14
|
+
value.dup.force_encoding("BINARY") unless value.nil?
|
|
15
|
+
rescue
|
|
16
|
+
value
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end # class Binary
|
|
22
|
+
end # class Property
|
|
23
|
+
end # module Ardm
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'ardm/property/object'
|
|
2
|
+
|
|
3
|
+
module Ardm
|
|
4
|
+
class Property
|
|
5
|
+
class Boolean < Object
|
|
6
|
+
load_as ::TrueClass
|
|
7
|
+
dump_as ::TrueClass
|
|
8
|
+
coercion_method :to_boolean
|
|
9
|
+
|
|
10
|
+
def initialize(model, name, options = {})
|
|
11
|
+
# validates presence in rails fails for false.
|
|
12
|
+
# Boolean must therefore behave like a set.
|
|
13
|
+
options[:set] = [true, false]
|
|
14
|
+
super model, name, options
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @api semipublic
|
|
18
|
+
def value_dumped?(value)
|
|
19
|
+
value_loaded?(value)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @api semipublic
|
|
23
|
+
def value_loaded?(value)
|
|
24
|
+
value == true || value == false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end # class Boolean
|
|
28
|
+
end # class Property
|
|
29
|
+
end # module Ardm
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'ardm/property/object'
|
|
2
|
+
|
|
3
|
+
module Ardm
|
|
4
|
+
class Property
|
|
5
|
+
class Class < Object
|
|
6
|
+
load_as ::Class
|
|
7
|
+
dump_as ::Class
|
|
8
|
+
coercion_method :to_constant
|
|
9
|
+
|
|
10
|
+
# @api semipublic
|
|
11
|
+
def typecast(value)
|
|
12
|
+
Ardm::Ext::Module.find_const(model, value.to_s) unless value.nil?
|
|
13
|
+
rescue NameError
|
|
14
|
+
value
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end # class Class
|
|
18
|
+
end # class Property
|
|
19
|
+
end # module Ardm
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'ardm/property/yaml'
|
|
2
|
+
|
|
3
|
+
module Ardm
|
|
4
|
+
class Property
|
|
5
|
+
class CommaSeparatedList < Yaml
|
|
6
|
+
|
|
7
|
+
def dump(value)
|
|
8
|
+
if value.nil?
|
|
9
|
+
nil
|
|
10
|
+
elsif value.kind_of?(::Array)
|
|
11
|
+
super(value)
|
|
12
|
+
elsif value.kind_of?(::String)
|
|
13
|
+
v = []
|
|
14
|
+
|
|
15
|
+
value.split(',').each do |element|
|
|
16
|
+
element.strip!
|
|
17
|
+
v << element unless element.empty?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
super(v)
|
|
21
|
+
else
|
|
22
|
+
raise ArgumentError, "+value+ of CommaSeparatedList must be a string, an array or nil, but given #{value.inspect}"
|
|
23
|
+
end
|
|
24
|
+
end # dump
|
|
25
|
+
|
|
26
|
+
end # CommaSeparatedList
|
|
27
|
+
end # Property
|
|
28
|
+
end # Ardm
|