ardm 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|