ardm 0.1.0 → 0.2.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.
- data/.ruby-version +1 -0
- data/Gemfile +14 -2
- data/ardm.gemspec +1 -1
- data/lib/ardm.rb +8 -0
- data/lib/ardm/active_record.rb +0 -5
- data/lib/ardm/active_record/associations.rb +27 -10
- data/lib/ardm/active_record/predicate_builder/rails4.rb +12 -5
- data/lib/ardm/active_record/property.rb +4 -3
- data/lib/ardm/active_record/record.rb +10 -6
- data/lib/ardm/active_record/relation.rb +67 -2
- data/lib/ardm/data_mapper.rb +2 -0
- data/lib/ardm/data_mapper/record.rb +19 -22
- data/lib/ardm/property/support/paranoid_base.rb +1 -1
- data/lib/ardm/query/expression.rb +5 -15
- data/lib/ardm/query/operator.rb +3 -3
- data/lib/ardm/version.rb +1 -1
- data/spec/fixtures/article.rb +1 -1
- data/spec/fixtures/resource_blog.rb +53 -0
- data/spec/integration/comma_separated_list_spec.rb +4 -4
- data/spec/integration/dirty_minder_spec.rb +1 -1
- data/spec/integration/enum_spec.rb +2 -2
- data/spec/integration/epoch_time_spec.rb +2 -2
- data/spec/integration/file_path_spec.rb +4 -4
- data/spec/integration/flag_spec.rb +5 -3
- data/spec/integration/json_spec.rb +3 -3
- data/spec/public/model_spec.rb +78 -8
- data/spec/public/property_spec.rb +10 -6
- data/spec/public/resource_spec.rb +9 -64
- data/spec/shared/{finder_shared_spec.rb → finder_shared.rb} +134 -128
- data/spec/shared/{flags_shared_spec.rb → flags_shared.rb} +0 -0
- data/spec/shared/{public_property_spec.rb → public_property.rb} +0 -0
- data/spec/shared/{resource_spec.rb → resource.rb} +46 -31
- data/spec/shared/{semipublic_property_spec.rb → semipublic_property.rb} +0 -0
- data/spec/spec_helper.rb +11 -5
- data/spec/support/logger.rb +38 -0
- data/spec/unit/dirty_minder_spec.rb +4 -2
- data/spec/unit/paranoid_boolean_spec.rb +3 -3
- data/spec/unit/paranoid_datetime_spec.rb +3 -3
- metadata +59 -30
- checksums.yaml +0 -7
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3
|
data/Gemfile
CHANGED
@@ -3,10 +3,22 @@ source 'https://rubygems.org'
|
|
3
3
|
gemspec
|
4
4
|
|
5
5
|
gem 'pry'
|
6
|
+
gem 'pry-nav'
|
7
|
+
gem 'awesome_print'
|
6
8
|
|
7
9
|
group :test do
|
8
10
|
gem 'sqlite3'
|
9
|
-
gem 'activerecord', '~>
|
11
|
+
gem 'activerecord', '~> 4.0.0'
|
10
12
|
gem 'addressable'
|
11
|
-
gem 'database_cleaner'
|
13
|
+
gem 'database_cleaner', git: "git://github.com/lanej/database_cleaner.git", branch: "datamapper-fix"
|
14
|
+
gem 'rspec-its'
|
15
|
+
end
|
16
|
+
|
17
|
+
group :datamapper do
|
18
|
+
gem 'dm-core', '~> 1.2'
|
19
|
+
gem 'dm-sqlite-adapter', '~> 1.2'
|
20
|
+
gem 'dm-types', '~> 1.2', git: "git://github.com/engineyard/dm-types.git", branch: "1.2-multijson"
|
21
|
+
gem 'dm-validations', '~> 1.2'
|
22
|
+
gem 'dm-transactions', '~> 1.2'
|
23
|
+
gem 'dm-migrations', '~> 1.2'
|
12
24
|
end
|
data/ardm.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.require_paths = [ "lib" ]
|
18
18
|
gem.version = Ardm::VERSION
|
19
19
|
|
20
|
-
gem.add_runtime_dependency('activesupport', '>= 3.2')
|
20
|
+
gem.add_runtime_dependency('activesupport', '>= 3.2', '< 4.1')
|
21
21
|
gem.add_runtime_dependency('bcrypt-ruby', '~> 3.0.0')
|
22
22
|
gem.add_runtime_dependency('fastercsv', '~> 1.5.4')
|
23
23
|
gem.add_runtime_dependency('multi_json', '> 1.3.2')
|
data/lib/ardm.rb
CHANGED
@@ -44,6 +44,14 @@ module Ardm
|
|
44
44
|
yield if block_given? && active_record?
|
45
45
|
end
|
46
46
|
|
47
|
+
def self.rails3?
|
48
|
+
self.active_record? && ::ActiveRecord::VERSION::STRING >= "3.0" && ::ActiveRecord::VERSION::STRING <= "4.0"
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.rails4?
|
52
|
+
self.active_record? && !self.rails3?
|
53
|
+
end
|
54
|
+
|
47
55
|
# Yield if Ardm has loaded DataMapper ORM.
|
48
56
|
#
|
49
57
|
# @api public
|
data/lib/ardm/active_record.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
|
3
3
|
module Ardm
|
4
4
|
module ActiveRecord
|
@@ -33,14 +33,20 @@ module Ardm
|
|
33
33
|
ar[:foreign_key] = property.field
|
34
34
|
end
|
35
35
|
|
36
|
-
if
|
37
|
-
|
36
|
+
if Ardm.rails3?
|
37
|
+
if (conditions = ar.slice!(*keep)).any?
|
38
|
+
ar[:conditions] = conditions
|
39
|
+
end
|
40
|
+
[ar]
|
41
|
+
else
|
42
|
+
block = if (conditions = ar.slice!(*keep)).any?
|
43
|
+
lambda { where(conditions) }
|
44
|
+
end
|
45
|
+
[block, ar].compact
|
38
46
|
end
|
39
|
-
ar
|
40
47
|
end
|
41
48
|
|
42
49
|
module ClassMethods
|
43
|
-
|
44
50
|
def dump_associations_hash(options)
|
45
51
|
options.inject({}) do |new_attrs, (key, value)|
|
46
52
|
if reflection = reflect_on_association(key.to_sym)
|
@@ -73,9 +79,13 @@ module Ardm
|
|
73
79
|
options.delete(:default)
|
74
80
|
options.delete(:required)
|
75
81
|
opts = Ardm::ActiveRecord::Associations.convert_options(self, options)
|
76
|
-
super field, opts
|
82
|
+
super field, *opts
|
77
83
|
assoc = reflect_on_association(field)
|
78
|
-
|
84
|
+
Ardm::ActiveRecord::Record.on_finalize << lambda do
|
85
|
+
self.class_eval do
|
86
|
+
property assoc.foreign_key, assoc.klass.key.first.class, key: false
|
87
|
+
end
|
88
|
+
end
|
79
89
|
nil
|
80
90
|
end
|
81
91
|
|
@@ -97,9 +107,16 @@ module Ardm
|
|
97
107
|
options[:order] = Ardm::ActiveRecord::Query.order(self, options[:order]) if options[:order]
|
98
108
|
opts = Ardm::ActiveRecord::Associations.convert_options(self, options, :through, :order)
|
99
109
|
|
100
|
-
|
101
|
-
|
102
|
-
|
110
|
+
if Ardm.rails3?
|
111
|
+
case count
|
112
|
+
when 1 then has_one name, *opts
|
113
|
+
when "many" then has_many name, *opts
|
114
|
+
end
|
115
|
+
else
|
116
|
+
case count
|
117
|
+
when 1 then has_one name, *opts
|
118
|
+
when "many" then has_many name, *opts
|
119
|
+
end
|
103
120
|
end
|
104
121
|
end
|
105
122
|
|
@@ -58,19 +58,26 @@ module Ardm
|
|
58
58
|
end
|
59
59
|
else
|
60
60
|
if Ardm::Query::Operator === column
|
61
|
-
column = column.target.to_s
|
62
61
|
operator = column.operator
|
62
|
+
target_column = column.target.to_s
|
63
63
|
else
|
64
|
-
|
64
|
+
target_column = column.to_s
|
65
65
|
operator = nil
|
66
66
|
end
|
67
67
|
|
68
|
-
if
|
69
|
-
table_name,
|
68
|
+
if target_column.include?('.')
|
69
|
+
table_name, target_column = target_column.split('.', 2)
|
70
70
|
table = Arel::Table.new(table_name, default_table.engine)
|
71
71
|
end
|
72
72
|
|
73
|
-
|
73
|
+
query = expand(klass, table, target_column, value)
|
74
|
+
# TODO make nicer
|
75
|
+
if [:not_eq, :not_in].include?(operator)
|
76
|
+
# Logical not factorization !(a && b) == (!a || !b)
|
77
|
+
query.map! &:not
|
78
|
+
query = [query.inject { |composite, predicate| composite.or(predicate) }]
|
79
|
+
end
|
80
|
+
queries.concat query
|
74
81
|
end
|
75
82
|
end
|
76
83
|
|
@@ -212,7 +212,7 @@ module Ardm
|
|
212
212
|
|
213
213
|
def set_primary_key_for(property)
|
214
214
|
if property.key? || property.serial?
|
215
|
-
self.primary_key
|
215
|
+
self.primary_key ||= property.name
|
216
216
|
end
|
217
217
|
end
|
218
218
|
|
@@ -223,7 +223,6 @@ module Ardm
|
|
223
223
|
return if property.key? || property.serial? # let AR do it
|
224
224
|
name = property.name.to_s
|
225
225
|
reader_visibility = property.reader_visibility
|
226
|
-
instance_variable_name = property.instance_variable_name
|
227
226
|
property_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
228
227
|
#{reader_visibility}
|
229
228
|
def #{name}
|
@@ -254,7 +253,7 @@ module Ardm
|
|
254
253
|
property_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
|
255
254
|
#{writer_visibility}
|
256
255
|
def #{writer_name}(value)
|
257
|
-
attribute_set(
|
256
|
+
attribute_set(:#{name}, value)
|
258
257
|
end
|
259
258
|
RUBY
|
260
259
|
end
|
@@ -328,6 +327,8 @@ module Ardm
|
|
328
327
|
|
329
328
|
# only memoize a valid key
|
330
329
|
@_key = key if model_key.valid?(key)
|
330
|
+
|
331
|
+
key
|
331
332
|
end
|
332
333
|
|
333
334
|
# Gets this instance's Model's properties
|
@@ -21,8 +21,8 @@ module Ardm
|
|
21
21
|
def self.property(property_name, property_type, options={})
|
22
22
|
prop = super
|
23
23
|
begin
|
24
|
-
|
25
|
-
|
24
|
+
attr_accessible prop.name
|
25
|
+
attr_accessible prop.field
|
26
26
|
rescue => e
|
27
27
|
puts "WARNING: Error silenced. FIXME before release.\n#{e}" unless $attr_accessible_warning
|
28
28
|
$attr_accessible_warning = true
|
@@ -72,6 +72,10 @@ module Ardm
|
|
72
72
|
delete_all
|
73
73
|
end
|
74
74
|
|
75
|
+
def destroy
|
76
|
+
self.class.delete(self.send(self.class.primary_key))
|
77
|
+
end
|
78
|
+
|
75
79
|
def new?
|
76
80
|
new_record?
|
77
81
|
end
|
@@ -80,12 +84,12 @@ module Ardm
|
|
80
84
|
!new_record?
|
81
85
|
end
|
82
86
|
|
83
|
-
def save_self(*)
|
84
|
-
save
|
87
|
+
def save_self(*args)
|
88
|
+
save(*args)
|
85
89
|
end
|
86
90
|
|
87
|
-
def save
|
88
|
-
|
91
|
+
def save!(*args)
|
92
|
+
save(*args) || (raise_on_save_failure && raise(Ardm::SaveFailureError, "Save Failed"))
|
89
93
|
end
|
90
94
|
|
91
95
|
def update(*a)
|
@@ -57,7 +57,7 @@ module Ardm
|
|
57
57
|
#end
|
58
58
|
|
59
59
|
VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
|
60
|
-
|
60
|
+
:order, :select, :readonly, :group, :having, :from, :lock ]
|
61
61
|
|
62
62
|
# We used to just patch this, like above, but we need to copy it over
|
63
63
|
# completely for rails4 since it no longer supports the old style finder
|
@@ -76,7 +76,72 @@ module Ardm
|
|
76
76
|
relation = relation.send(finder, finders[finder])
|
77
77
|
end
|
78
78
|
|
79
|
-
|
79
|
+
conditions.each do |key, value|
|
80
|
+
if assoc = relation.reflect_on_association(key)
|
81
|
+
conditions.delete(key)
|
82
|
+
# strip out assocations
|
83
|
+
case assoc.macro
|
84
|
+
when :belongs_to
|
85
|
+
id = value.is_a?(Hash) ? value.with_indifferent_access[:id] : value
|
86
|
+
relation = if value.is_a?(::ActiveRecord::Relation)
|
87
|
+
if value.values.empty?
|
88
|
+
relation.where.not(assoc.foreign_key => nil)
|
89
|
+
else
|
90
|
+
relation.where(assoc.foreign_key => value)
|
91
|
+
end
|
92
|
+
else
|
93
|
+
relation.where(assoc.foreign_key => id)
|
94
|
+
end
|
95
|
+
when :has_one
|
96
|
+
foreign_class = assoc.options[:class_name].constantize
|
97
|
+
foreign_key = assoc.foreign_key
|
98
|
+
parent_key = assoc.options[:child_key] || klass.primary_key
|
99
|
+
|
100
|
+
if value.is_a?(::Array) && value.empty?
|
101
|
+
# @fixme: dm basically no-ops cause it knows you are stupid
|
102
|
+
return klass.where(klass.primary_key => nil)
|
103
|
+
end
|
104
|
+
|
105
|
+
relation = if value.is_a?(::ActiveRecord::Base)
|
106
|
+
relation.where(parent_key => value.send(assoc.foreign_key))
|
107
|
+
elsif value.is_a?(::ActiveRecord::Relation)
|
108
|
+
relation.where(parent_key => value.select(foreign_key))
|
109
|
+
elsif value.nil?
|
110
|
+
relation.where.not(parent_key => foreign_class.select(foreign_key).where.not(foreign_key => value))
|
111
|
+
else
|
112
|
+
relation.where(parent_key => foreign_class.select(foreign_key).where(value))
|
113
|
+
end
|
114
|
+
when :has_many
|
115
|
+
foreign_class = assoc.options[:class_name].constantize
|
116
|
+
foreign_key = assoc.foreign_key
|
117
|
+
parent_key = assoc.options[:child_key] || klass.primary_key
|
118
|
+
|
119
|
+
relation = if value.is_a?(::ActiveRecord::Relation)
|
120
|
+
relation.where(foreign_key => value)
|
121
|
+
else
|
122
|
+
relation.where(parent_key => foreign_class.select(foreign_class.primary_key).where.not(foreign_key => value))
|
123
|
+
end
|
124
|
+
else
|
125
|
+
raise("unknown: #{assoc.inspect}")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
processed_conditions = {}
|
131
|
+
|
132
|
+
conditions.each do |key, value|
|
133
|
+
key = key.is_a?(Ardm::Property) ? key.name : key
|
134
|
+
|
135
|
+
case key
|
136
|
+
when String, Symbol then
|
137
|
+
processed_conditions[key] = value
|
138
|
+
when Ardm::Query::Operator then
|
139
|
+
relation = key.to_arel(self, value).scope
|
140
|
+
else raise "unknown key: #{key.inspect} #{value.inspect}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
relation = relation.where(processed_conditions) if processed_conditions.any?
|
80
145
|
relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
|
81
146
|
relation = relation.includes(finders[:include]) if options.has_key?(:include)
|
82
147
|
relation = relation.extending(finders[:extend]) if options.has_key?(:extend)
|
data/lib/ardm/data_mapper.rb
CHANGED
@@ -1,34 +1,31 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'dm-core'
|
2
3
|
|
3
4
|
module Ardm
|
4
5
|
module DataMapper
|
5
|
-
|
6
|
-
extend
|
6
|
+
class Record
|
7
|
+
extend Forwardable
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def inherited(base)
|
12
|
-
base.send(:include, DataMapper::Resource)
|
13
|
-
#base.send(:extend, DataMapper::CollectionRaise)
|
9
|
+
def self.inherited(base)
|
10
|
+
base.send(:include, ::DataMapper::Resource)
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
13
|
+
def self.finalize
|
14
|
+
::DataMapper.finalize
|
15
|
+
end
|
19
16
|
|
20
|
-
|
21
|
-
|
17
|
+
def self.alias_attribute(new, old)
|
18
|
+
alias_method new, old
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
21
|
+
def self.attr_accessible(*attrs)
|
22
|
+
end
|
26
23
|
|
27
|
-
|
28
|
-
|
24
|
+
def self.abstract_class=(val)
|
25
|
+
end
|
29
26
|
|
30
|
-
|
31
|
-
|
27
|
+
def self.table_name=(name)
|
28
|
+
self.storage_names[:default] = name
|
32
29
|
end
|
33
30
|
end
|
34
31
|
end
|
@@ -7,20 +7,11 @@ module Ardm
|
|
7
7
|
new(relation, target, value).scope
|
8
8
|
end
|
9
9
|
|
10
|
-
def initialize(relation, target, value)
|
10
|
+
def initialize(relation, target, operator, value)
|
11
11
|
@relation = relation
|
12
12
|
@value = value
|
13
|
-
|
14
|
-
|
15
|
-
when Ardm::Query::Operator
|
16
|
-
@target = target.target
|
17
|
-
@operator = target.operator
|
18
|
-
when Symbol, String
|
19
|
-
@target = target
|
20
|
-
@operator = :eq
|
21
|
-
else
|
22
|
-
raise ArgumentError, "Unknown target #{target.inspect} in Expresion"
|
23
|
-
end
|
13
|
+
@target = target
|
14
|
+
@operator = operator
|
24
15
|
end
|
25
16
|
|
26
17
|
def resolved_target
|
@@ -54,14 +45,13 @@ module Ardm
|
|
54
45
|
if association.macro == :belongs_to
|
55
46
|
association.foreign_key.to_sym
|
56
47
|
else
|
57
|
-
|
58
|
-
association.primary_key.to_sym
|
48
|
+
association.klass.primary_key.to_sym
|
59
49
|
end
|
60
50
|
end
|
61
51
|
end
|
62
52
|
|
63
53
|
def arel_operator
|
64
|
-
value.respond_to?(:to_ary) ? operator.for_array : operator
|
54
|
+
value.respond_to?(:to_ary) ? operator.for_array : operator.operator
|
65
55
|
end
|
66
56
|
|
67
57
|
def arel_value(val = value)
|
data/lib/ardm/query/operator.rb
CHANGED
@@ -7,7 +7,7 @@ module Ardm
|
|
7
7
|
OPERATORS = {
|
8
8
|
# DM => ARel
|
9
9
|
:eql => :eq,
|
10
|
-
:not => :
|
10
|
+
:not => :not_eq,
|
11
11
|
:in => :in,
|
12
12
|
:gt => :gt,
|
13
13
|
:gte => :gteq,
|
@@ -47,8 +47,8 @@ module Ardm
|
|
47
47
|
FOR_ARRAY[operator]
|
48
48
|
end
|
49
49
|
|
50
|
-
def to_arel(
|
51
|
-
Ardm::Query::Expression.new(
|
50
|
+
def to_arel(relation, value)
|
51
|
+
Ardm::Query::Expression.new(relation, target, self, value)
|
52
52
|
end
|
53
53
|
|
54
54
|
private
|