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