ardm 0.0.1 → 0.1.0
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 +5 -13
- data/Gemfile +1 -2
- data/LICENSE +2 -2
- data/README.md +72 -16
- data/ardm.gemspec +1 -0
- data/lib/ardm.rb +2 -1
- data/lib/ardm/active_record.rb +8 -1
- data/lib/ardm/active_record/associations.rb +33 -4
- data/lib/ardm/active_record/base.rb +2 -0
- data/lib/ardm/active_record/collection.rb +5 -0
- data/lib/ardm/active_record/data_mapper_constant.rb +1 -0
- data/lib/ardm/active_record/data_mapper_constant_proxy.rb +24 -0
- data/lib/ardm/active_record/finalize.rb +18 -0
- data/lib/ardm/active_record/predicate_builder/array_handler.rb +10 -16
- data/lib/ardm/active_record/predicate_builder/rails3.rb +42 -15
- data/lib/ardm/active_record/predicate_builder/rails4.rb +39 -13
- data/lib/ardm/active_record/property.rb +24 -12
- data/lib/ardm/active_record/query.rb +9 -18
- data/lib/ardm/active_record/record.rb +54 -11
- data/lib/ardm/active_record/relation.rb +36 -6
- data/lib/ardm/active_record/repository.rb +6 -2
- data/lib/ardm/data_mapper.rb +2 -0
- data/lib/ardm/data_mapper/record.rb +3 -9
- data/lib/ardm/version.rb +1 -1
- data/spec/ardm/datamapper_constants_spec.rb +31 -0
- data/spec/fixtures/article.rb +2 -0
- data/spec/integration/api_key_spec.rb +3 -3
- data/spec/integration/bcrypt_hash_spec.rb +7 -7
- data/spec/integration/comma_separated_list_spec.rb +11 -11
- data/spec/integration/dirty_minder_spec.rb +23 -39
- data/spec/integration/enum_spec.rb +11 -11
- data/spec/integration/epoch_time_spec.rb +6 -6
- data/spec/integration/file_path_spec.rb +23 -23
- data/spec/integration/flag_spec.rb +11 -13
- data/spec/integration/ip_address_spec.rb +15 -15
- data/spec/integration/json_spec.rb +7 -7
- data/spec/integration/slug_spec.rb +6 -6
- data/spec/integration/uri_spec.rb +11 -11
- data/spec/integration/uuid_spec.rb +16 -16
- data/spec/integration/yaml_spec.rb +8 -8
- data/spec/public/model_spec.rb +193 -0
- data/spec/public/property/binary_spec.rb +4 -4
- data/spec/public/property/boolean_spec.rb +3 -3
- data/spec/public/property/class_spec.rb +2 -2
- data/spec/public/property/date_spec.rb +2 -2
- data/spec/public/property/date_time_spec.rb +2 -2
- data/spec/public/property/decimal_spec.rb +2 -2
- data/spec/public/property/discriminator_spec.rb +21 -20
- data/spec/public/property/float_spec.rb +2 -2
- data/spec/public/property/integer_spec.rb +2 -2
- data/spec/public/property/object_spec.rb +14 -13
- data/spec/public/property/serial_spec.rb +2 -2
- data/spec/public/property/string_spec.rb +2 -2
- data/spec/public/property/text_spec.rb +2 -2
- data/spec/public/property/time_spec.rb +2 -2
- data/spec/public/property_spec.rb +44 -48
- data/spec/public/resource_spec.rb +278 -0
- data/spec/schema.rb +33 -4
- data/spec/semipublic/property/boolean_spec.rb +5 -5
- data/spec/semipublic/property/class_spec.rb +3 -3
- data/spec/semipublic/property/date_spec.rb +8 -8
- data/spec/semipublic/property/date_time_spec.rb +9 -9
- data/spec/semipublic/property/decimal_spec.rb +16 -16
- data/spec/semipublic/property/float_spec.rb +16 -16
- data/spec/semipublic/property/integer_spec.rb +16 -16
- data/spec/semipublic/property/lookup_spec.rb +4 -4
- data/spec/semipublic/property/text_spec.rb +2 -2
- data/spec/semipublic/property/time_spec.rb +10 -10
- data/spec/semipublic/property_spec.rb +4 -4
- data/spec/shared/finder_shared_spec.rb +1151 -0
- data/spec/shared/flags_shared_spec.rb +6 -6
- data/spec/shared/identity_function_group.rb +1 -1
- data/spec/shared/public_property_spec.rb +26 -25
- data/spec/shared/resource_spec.rb +1218 -0
- data/spec/shared/semipublic_property_spec.rb +23 -22
- data/spec/spec_helper.rb +17 -0
- data/spec/unit/bcrypt_hash_spec.rb +15 -15
- data/spec/unit/csv_spec.rb +11 -11
- data/spec/unit/dirty_minder_spec.rb +3 -5
- data/spec/unit/enum_spec.rb +17 -17
- data/spec/unit/epoch_time_spec.rb +8 -8
- data/spec/unit/file_path_spec.rb +9 -9
- data/spec/unit/flag_spec.rb +9 -9
- data/spec/unit/ip_address_spec.rb +9 -9
- data/spec/unit/json_spec.rb +11 -11
- data/spec/unit/paranoid_boolean_spec.rb +19 -17
- data/spec/unit/paranoid_datetime_spec.rb +21 -19
- data/spec/unit/regexp_spec.rb +4 -4
- data/spec/unit/uri_spec.rb +8 -8
- data/spec/unit/yaml_spec.rb +9 -9
- metadata +35 -27
- data/lib/ardm/active_record/not_found.rb +0 -7
- data/lib/ardm/data_mapper/not_found.rb +0 -5
@@ -78,25 +78,51 @@ module Ardm
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def expand(klass, table, column, value)
|
81
|
-
|
81
|
+
if klass && association = klass.reflect_on_association(column.to_sym)
|
82
|
+
expand_association(association, table, column, value)
|
83
|
+
else
|
84
|
+
[build(table[column], value)]
|
85
|
+
end
|
86
|
+
end
|
82
87
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
88
|
+
# Find the foreign key when using queries such as:
|
89
|
+
# Post.where(author: author)
|
90
|
+
#
|
91
|
+
# For polymorphic relationships, find the foreign key and type:
|
92
|
+
# PriceEstimate.where(estimate_of: treasure)
|
93
|
+
#
|
94
|
+
# Attempt to build a query that makes sense for an association name
|
95
|
+
# in the query, but if we can't generate a propery query, fallback
|
96
|
+
# to using the original key we received.
|
97
|
+
def expand_association(association, table, column, value)
|
98
|
+
queries = []
|
99
|
+
case association.macro
|
100
|
+
when :belongs_to
|
101
|
+
if association.polymorphic? && base_class = polymorphic_base_class_from_value(value)
|
102
|
+
queries << build(table[association.foreign_type], base_class)
|
91
103
|
end
|
92
|
-
|
93
|
-
|
104
|
+
queries << build(table[association.foreign_key], value)
|
105
|
+
when :has_many, :has_one
|
106
|
+
table = Arel::Table.new(association.klass.table_name, table.engine)
|
107
|
+
queries << build(table[association.klass.primary_key], value)
|
108
|
+
else
|
109
|
+
queries << build(table[column], value)
|
94
110
|
end
|
95
|
-
|
96
|
-
queries << build(table[column], value)
|
97
111
|
queries
|
98
112
|
end
|
99
113
|
|
114
|
+
def polymorphic_base_class_from_value(value)
|
115
|
+
case value
|
116
|
+
when Relation
|
117
|
+
value.klass.base_class
|
118
|
+
when Array
|
119
|
+
val = value.compact.first
|
120
|
+
val.class.base_class if val.is_a?(Base)
|
121
|
+
when Base
|
122
|
+
value.class.base_class
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
100
126
|
def references(attributes)
|
101
127
|
attributes.map do |key, value|
|
102
128
|
if value.is_a?(Hash)
|
@@ -51,7 +51,7 @@ module Ardm
|
|
51
51
|
# use that class rather than the primitive
|
52
52
|
klass = Ardm::Property.determine_class(type)
|
53
53
|
|
54
|
-
|
54
|
+
if !klass || klass == NilClass
|
55
55
|
raise ArgumentError, "+type+ was #{type.inspect}, which is not a supported type"
|
56
56
|
end
|
57
57
|
|
@@ -100,7 +100,11 @@ module Ardm
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def columns
|
103
|
-
@columns ||=
|
103
|
+
@columns ||= _ardm_load_columns
|
104
|
+
end
|
105
|
+
|
106
|
+
def _ardm_load_columns
|
107
|
+
properties.map do |property|
|
104
108
|
sql_type = connection.type_to_sql(
|
105
109
|
property.dump_as.name.to_sym,
|
106
110
|
property.options[:limit],
|
@@ -109,8 +113,7 @@ module Ardm
|
|
109
113
|
)
|
110
114
|
|
111
115
|
column = ::ActiveRecord::ConnectionAdapters::Column.new(
|
112
|
-
#property.name.to_s,
|
113
|
-
property.field.to_s,
|
116
|
+
property.field.to_s, #property.name.to_s,
|
114
117
|
nil,#property.dump(property.default),
|
115
118
|
sql_type,
|
116
119
|
property.allow_nil?
|
@@ -141,6 +144,13 @@ module Ardm
|
|
141
144
|
end
|
142
145
|
end
|
143
146
|
|
147
|
+
def assert_valid_attributes(options)
|
148
|
+
options.each do |key, value|
|
149
|
+
property = properties[key]
|
150
|
+
property.assert_valid_value(value)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
144
154
|
# Gets the list of key fields for this Model
|
145
155
|
#
|
146
156
|
# @return [Array]
|
@@ -280,19 +290,21 @@ module Ardm
|
|
280
290
|
|
281
291
|
# This not the same as read_attribute in AR
|
282
292
|
def attribute_get(name)
|
283
|
-
property = self.class.properties[name]
|
284
|
-
|
285
|
-
|
286
|
-
|
293
|
+
if property = self.class.properties[name]
|
294
|
+
val = read_attribute property.field
|
295
|
+
if new_record? && val.nil? && property.default?
|
296
|
+
write_attribute property.field, property.typecast(property.default_for(self))
|
297
|
+
end
|
298
|
+
read_attribute property.field
|
287
299
|
end
|
288
|
-
read_attribute property.field
|
289
300
|
end
|
290
301
|
|
291
302
|
# This not the same as write_attribute in AR
|
292
303
|
def attribute_set(name, value)
|
293
|
-
property = self.class.properties[name]
|
294
|
-
|
295
|
-
|
304
|
+
if property = self.class.properties[name]
|
305
|
+
write_attribute property.field, property.typecast(value)
|
306
|
+
read_attribute property.field
|
307
|
+
end
|
296
308
|
end
|
297
309
|
|
298
310
|
# Retrieve the key(s) for this resource.
|
@@ -52,10 +52,18 @@ module Ardm
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def get(id)
|
55
|
-
|
55
|
+
if Array === id && id.size == 1
|
56
|
+
# Model#key returns an array
|
57
|
+
id = id.first
|
58
|
+
end
|
59
|
+
where(primary_key => id).first
|
56
60
|
end
|
57
61
|
|
58
62
|
def get!(id)
|
63
|
+
if Array === id && id.size == 1
|
64
|
+
# Model#key returns an array
|
65
|
+
id = id.first
|
66
|
+
end
|
59
67
|
find(id)
|
60
68
|
end
|
61
69
|
|
@@ -71,23 +79,6 @@ module Ardm
|
|
71
79
|
all(find_params).first_or_initialize
|
72
80
|
end
|
73
81
|
|
74
|
-
#def first(args=nil)
|
75
|
-
# if Hash === args
|
76
|
-
# all(args).first
|
77
|
-
# else
|
78
|
-
# puts "#{self}.first(#{args.inspect})"
|
79
|
-
# puts caller[0..1]
|
80
|
-
# super(args)
|
81
|
-
# end
|
82
|
-
#end
|
83
|
-
|
84
|
-
#def all(options={})
|
85
|
-
# puts "#{self}.all(#{options.inspect})"
|
86
|
-
# puts caller[0..1]
|
87
|
-
# binding.pry if options[:account]
|
88
|
-
# Ardm::Query.all(self, options)
|
89
|
-
#end
|
90
|
-
|
91
82
|
#def exist?(options={})
|
92
83
|
# puts "#{self}.exist?(#{options.inspect})"
|
93
84
|
# puts caller[0..10]
|
@@ -9,42 +9,85 @@ module Ardm
|
|
9
9
|
|
10
10
|
self.abstract_class = true
|
11
11
|
|
12
|
-
|
12
|
+
class_attribute :raise_on_save_failure
|
13
|
+
self.raise_on_save_failure = false
|
13
14
|
|
14
|
-
|
15
|
-
end
|
15
|
+
JSON = Json
|
16
16
|
|
17
17
|
def self.execute_sql(sql)
|
18
18
|
connection.execute(sql)
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.property(property_name, property_type, options={})
|
22
|
-
|
22
|
+
prop = super
|
23
23
|
begin
|
24
|
-
attr_accessible
|
25
|
-
attr_accessible
|
24
|
+
attr_accessible prop.name
|
25
|
+
attr_accessible prop.field
|
26
26
|
rescue => e
|
27
|
-
puts "WARNING: Error silenced. FIXME before release.\n#{e}"
|
27
|
+
puts "WARNING: Error silenced. FIXME before release.\n#{e}" unless $attr_accessible_warning
|
28
|
+
$attr_accessible_warning = true
|
28
29
|
end
|
29
|
-
|
30
|
+
prop
|
30
31
|
end
|
31
32
|
|
32
33
|
# no-op in active record
|
33
|
-
def self.timestamps(
|
34
|
+
def self.timestamps(at=:at)
|
35
|
+
case at
|
36
|
+
when :at
|
37
|
+
property :created_at, DateTime
|
38
|
+
property :updated_at, DateTime
|
39
|
+
when :on
|
40
|
+
property :created_on, Date
|
41
|
+
property :updated_on, Date
|
42
|
+
else
|
43
|
+
raise ArgumentError, "Unknown argument: timestamps(#{at.inspect})"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# The reflections returned here don't look like datamapper relationships.
|
48
|
+
# @todo improve this if needed with a wrapper
|
49
|
+
def self.relationships
|
50
|
+
reflections
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.update(*a)
|
54
|
+
options = dump_properties_hash(a.first)
|
55
|
+
options = dump_associations_hash(options)
|
56
|
+
assert_valid_attributes(options)
|
57
|
+
update_all(options) != 0
|
34
58
|
end
|
35
59
|
|
36
|
-
def
|
37
|
-
|
60
|
+
def self.update!(*a)
|
61
|
+
options = dump_properties_hash(a.first)
|
62
|
+
options = dump_associations_hash(options)
|
63
|
+
assert_valid_attributes(options)
|
64
|
+
update_all(options) != 0
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.destroy(*a)
|
68
|
+
destroy_all
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.destroy!(*a)
|
72
|
+
delete_all
|
38
73
|
end
|
39
74
|
|
40
75
|
def new?
|
41
76
|
new_record?
|
42
77
|
end
|
43
78
|
|
79
|
+
def saved?
|
80
|
+
!new_record?
|
81
|
+
end
|
82
|
+
|
44
83
|
def save_self(*)
|
45
84
|
save
|
46
85
|
end
|
47
86
|
|
87
|
+
def save
|
88
|
+
super || (raise_on_save_failure && raise(Ardm::SaveFailureError, "Save Failed"))
|
89
|
+
end
|
90
|
+
|
48
91
|
def update(*a)
|
49
92
|
if a.size == 1
|
50
93
|
update_attributes(*a)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'active_support/concern'
|
2
|
-
require 'active_record'
|
2
|
+
require 'ardm/active_record/collection'
|
3
3
|
|
4
4
|
module Ardm
|
5
5
|
module ActiveRecord
|
@@ -15,7 +15,8 @@ module Ardm
|
|
15
15
|
def update(*a)
|
16
16
|
if a.size == 1
|
17
17
|
# need to translate attributes
|
18
|
-
options = @klass.
|
18
|
+
options = @klass.dump_properties_hash(a.first)
|
19
|
+
options = @klass.dump_associations_hash(options)
|
19
20
|
update_all(options)
|
20
21
|
else
|
21
22
|
update_without_ardm(*a)
|
@@ -48,13 +49,42 @@ module Ardm
|
|
48
49
|
apply_finder_options(options)
|
49
50
|
end
|
50
51
|
|
52
|
+
#def apply_finder_options(options)
|
53
|
+
# return super if options.nil? || options.empty?
|
54
|
+
# options = options.dup
|
55
|
+
# conditions = options.slice!(*::ActiveRecord::SpawnMethods::VALID_FIND_OPTIONS)
|
56
|
+
# super(options).where(conditions)
|
57
|
+
#end
|
58
|
+
|
59
|
+
VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
|
60
|
+
:order, :select, :readonly, :group, :having, :from, :lock ]
|
61
|
+
|
62
|
+
# We used to just patch this, like above, but we need to copy it over
|
63
|
+
# completely for rails4 since it no longer supports the old style finder
|
64
|
+
# methods that act more like the datamapper finders.
|
51
65
|
def apply_finder_options(options)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
66
|
+
relation = clone
|
67
|
+
return relation if options.nil?
|
68
|
+
|
69
|
+
finders = options.dup
|
70
|
+
finders[:select] = finders.delete(:fields)
|
71
|
+
conditions = finders.slice!(*VALID_FIND_OPTIONS)
|
72
|
+
|
73
|
+
finders.delete_if { |key, value| value.nil? && key != :limit }
|
74
|
+
|
75
|
+
([:joins, :select, :group, :order, :having, :limit, :offset, :from, :lock, :readonly] & finders.keys).each do |finder|
|
76
|
+
relation = relation.send(finder, finders[finder])
|
77
|
+
end
|
78
|
+
|
79
|
+
relation = relation.where(conditions) if conditions.any?
|
80
|
+
relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
|
81
|
+
relation = relation.includes(finders[:include]) if options.has_key?(:include)
|
82
|
+
relation = relation.extending(finders[:extend]) if options.has_key?(:extend)
|
83
|
+
|
84
|
+
relation
|
56
85
|
end
|
57
86
|
|
87
|
+
|
58
88
|
def calculate(operation, column_name, options={})
|
59
89
|
if property = properties[column_name]
|
60
90
|
column_name = property.field
|
@@ -5,12 +5,16 @@ module Ardm
|
|
5
5
|
module Repository
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
-
def repository
|
8
|
+
def repository(name=nil)
|
9
9
|
self.class.repository
|
10
10
|
end
|
11
11
|
|
12
12
|
module ClassMethods
|
13
|
-
def repository
|
13
|
+
def repository(name=nil)
|
14
|
+
if name && name != :default
|
15
|
+
raise Ardm::NotImplemented, "Alternate repository names not supported"
|
16
|
+
end
|
17
|
+
|
14
18
|
if block_given?
|
15
19
|
yield
|
16
20
|
else
|
data/lib/ardm/data_mapper.rb
CHANGED
@@ -5,12 +5,11 @@ module Ardm
|
|
5
5
|
module Record
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
-
NotFound = DataMapper::ObjectNotFoundError
|
9
|
-
|
10
8
|
module ClassMethods
|
9
|
+
extend Forwardable
|
10
|
+
|
11
11
|
def inherited(base)
|
12
12
|
base.send(:include, DataMapper::Resource)
|
13
|
-
base.send(:include, Awsm::Resource)
|
14
13
|
#base.send(:extend, DataMapper::CollectionRaise)
|
15
14
|
|
16
15
|
unless %w[Alert Association Nonce Account::Cancellation::Handler].include?(base.name)
|
@@ -18,13 +17,8 @@ module Ardm
|
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
|
-
extend Forwardable
|
22
|
-
def datamapper() DataMapper end
|
23
20
|
def_delegators :datamapper, :repository, :finalize, :logger, :logger=
|
24
|
-
|
25
|
-
def execute_sql(sql)
|
26
|
-
DataMapper.repository.adapter.execute(sql)
|
27
|
-
end
|
21
|
+
def datamapper() DataMapper end
|
28
22
|
|
29
23
|
def alias_attribute(new, old)
|
30
24
|
alias_method new, old
|
data/lib/ardm/version.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ardm::ActiveRecord::DataMapperConstantProxy do
|
4
|
+
it 'defines Resource' do
|
5
|
+
expect(described_class::Resource).to be_kind_of(Module)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'defines ObjectNotFoundError to ActiveRecord::RecordNotFound' do
|
9
|
+
expect(described_class::ObjectNotFoundError).to be(ActiveRecord::RecordNotFound)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'defines SaveFailureError to ActiveRecord::RecordNotSaved' do
|
13
|
+
expect(described_class::SaveFailureError).to be(ActiveRecord::RecordNotSaved)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'responds to finalize' do
|
17
|
+
expect(described_class.respond_to?(:finalize)).to be_truthy
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'responds to repository' do
|
21
|
+
expect(described_class.respond_to?(:repository)).to be_truthy
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'responds to logger' do
|
25
|
+
expect(described_class.respond_to?(:logger)).to be_truthy
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'responds to logger=' do
|
29
|
+
expect(described_class.respond_to?(:logger=)).to be_truthy
|
30
|
+
end
|
31
|
+
end
|