active_repository 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/LICENSE +165 -22
- data/README.md +1 -1
- data/active_repository.gemspec +2 -1
- data/lib/active_repository/associations.rb +11 -16
- data/lib/active_repository/base.rb +35 -35
- data/lib/active_repository/finders.rb +5 -5
- data/lib/active_repository/sql_query_executor.rb +18 -9
- data/lib/active_repository/uniqueness.rb +21 -15
- data/lib/active_repository/version.rb +1 -1
- data/lib/active_repository/write_support.rb +1 -1
- data/lib/active_repository/writers.rb +17 -23
- data/spec/spec_helper.rb +2 -4
- data/spec/support/shared_examples.rb +8 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MDgyNmE5MmNiMjAxZjE2MTdmOWJkYzIxOTlmNDA2NTllZmUyNzJiNQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MGU3NmYwN2YzZTA1YTNjMWQ4ZDEwM2JlMGIzZGIzNTQ4ZmIzMTY1OA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTM2MGUwMzZmMGExNTAwM2I1YTc0ZGE4YjVlODkxNDJhZWM0ODBlOWY5ZGQz
|
10
|
+
NWVkMGNmNjQ1MjM2MjVlNmIxODM2Mzc3YmJhOGI2MzNmNDc5ZTllN2IwNzAx
|
11
|
+
NzhiNjU1MjhmM2NkZWFiYzZiMGVjOWE2ZWE5ZjA1NTVhOTIzZjk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTBkNWJhMDI1MDE5NDU0OGIxMTRjN2MyM2MyOTRjYmQwNjNlYjgwMTU4MjEw
|
14
|
+
NTRiOWE3OTU4N2Q1YTRkNWVjNGZmODM4YWViOGMyOTVhYjJjNjA2OWNkNTAw
|
15
|
+
OWUxMWIxYmRjOTFiYjllNDRhZWQ4NTRjODY0ZDQwNWU5MzMwOWM=
|
data/LICENSE
CHANGED
@@ -1,22 +1,165 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
the
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
1
|
+
GNU LESSER GENERAL PUBLIC LICENSE
|
2
|
+
Version 3, 29 June 2007
|
3
|
+
|
4
|
+
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
5
|
+
Everyone is permitted to copy and distribute verbatim copies
|
6
|
+
of this license document, but changing it is not allowed.
|
7
|
+
|
8
|
+
|
9
|
+
This version of the GNU Lesser General Public License incorporates
|
10
|
+
the terms and conditions of version 3 of the GNU General Public
|
11
|
+
License, supplemented by the additional permissions listed below.
|
12
|
+
|
13
|
+
0. Additional Definitions.
|
14
|
+
|
15
|
+
As used herein, "this License" refers to version 3 of the GNU Lesser
|
16
|
+
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
17
|
+
General Public License.
|
18
|
+
|
19
|
+
"The Library" refers to a covered work governed by this License,
|
20
|
+
other than an Application or a Combined Work as defined below.
|
21
|
+
|
22
|
+
An "Application" is any work that makes use of an interface provided
|
23
|
+
by the Library, but which is not otherwise based on the Library.
|
24
|
+
Defining a subclass of a class defined by the Library is deemed a mode
|
25
|
+
of using an interface provided by the Library.
|
26
|
+
|
27
|
+
A "Combined Work" is a work produced by combining or linking an
|
28
|
+
Application with the Library. The particular version of the Library
|
29
|
+
with which the Combined Work was made is also called the "Linked
|
30
|
+
Version".
|
31
|
+
|
32
|
+
The "Minimal Corresponding Source" for a Combined Work means the
|
33
|
+
Corresponding Source for the Combined Work, excluding any source code
|
34
|
+
for portions of the Combined Work that, considered in isolation, are
|
35
|
+
based on the Application, and not on the Linked Version.
|
36
|
+
|
37
|
+
The "Corresponding Application Code" for a Combined Work means the
|
38
|
+
object code and/or source code for the Application, including any data
|
39
|
+
and utility programs needed for reproducing the Combined Work from the
|
40
|
+
Application, but excluding the System Libraries of the Combined Work.
|
41
|
+
|
42
|
+
1. Exception to Section 3 of the GNU GPL.
|
43
|
+
|
44
|
+
You may convey a covered work under sections 3 and 4 of this License
|
45
|
+
without being bound by section 3 of the GNU GPL.
|
46
|
+
|
47
|
+
2. Conveying Modified Versions.
|
48
|
+
|
49
|
+
If you modify a copy of the Library, and, in your modifications, a
|
50
|
+
facility refers to a function or data to be supplied by an Application
|
51
|
+
that uses the facility (other than as an argument passed when the
|
52
|
+
facility is invoked), then you may convey a copy of the modified
|
53
|
+
version:
|
54
|
+
|
55
|
+
a) under this License, provided that you make a good faith effort to
|
56
|
+
ensure that, in the event an Application does not supply the
|
57
|
+
function or data, the facility still operates, and performs
|
58
|
+
whatever part of its purpose remains meaningful, or
|
59
|
+
|
60
|
+
b) under the GNU GPL, with none of the additional permissions of
|
61
|
+
this License applicable to that copy.
|
62
|
+
|
63
|
+
3. Object Code Incorporating Material from Library Header Files.
|
64
|
+
|
65
|
+
The object code form of an Application may incorporate material from
|
66
|
+
a header file that is part of the Library. You may convey such object
|
67
|
+
code under terms of your choice, provided that, if the incorporated
|
68
|
+
material is not limited to numerical parameters, data structure
|
69
|
+
layouts and accessors, or small macros, inline functions and templates
|
70
|
+
(ten or fewer lines in length), you do both of the following:
|
71
|
+
|
72
|
+
a) Give prominent notice with each copy of the object code that the
|
73
|
+
Library is used in it and that the Library and its use are
|
74
|
+
covered by this License.
|
75
|
+
|
76
|
+
b) Accompany the object code with a copy of the GNU GPL and this license
|
77
|
+
document.
|
78
|
+
|
79
|
+
4. Combined Works.
|
80
|
+
|
81
|
+
You may convey a Combined Work under terms of your choice that,
|
82
|
+
taken together, effectively do not restrict modification of the
|
83
|
+
portions of the Library contained in the Combined Work and reverse
|
84
|
+
engineering for debugging such modifications, if you also do each of
|
85
|
+
the following:
|
86
|
+
|
87
|
+
a) Give prominent notice with each copy of the Combined Work that
|
88
|
+
the Library is used in it and that the Library and its use are
|
89
|
+
covered by this License.
|
90
|
+
|
91
|
+
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
92
|
+
document.
|
93
|
+
|
94
|
+
c) For a Combined Work that displays copyright notices during
|
95
|
+
execution, include the copyright notice for the Library among
|
96
|
+
these notices, as well as a reference directing the user to the
|
97
|
+
copies of the GNU GPL and this license document.
|
98
|
+
|
99
|
+
d) Do one of the following:
|
100
|
+
|
101
|
+
0) Convey the Minimal Corresponding Source under the terms of this
|
102
|
+
License, and the Corresponding Application Code in a form
|
103
|
+
suitable for, and under terms that permit, the user to
|
104
|
+
recombine or relink the Application with a modified version of
|
105
|
+
the Linked Version to produce a modified Combined Work, in the
|
106
|
+
manner specified by section 6 of the GNU GPL for conveying
|
107
|
+
Corresponding Source.
|
108
|
+
|
109
|
+
1) Use a suitable shared library mechanism for linking with the
|
110
|
+
Library. A suitable mechanism is one that (a) uses at run time
|
111
|
+
a copy of the Library already present on the user's computer
|
112
|
+
system, and (b) will operate properly with a modified version
|
113
|
+
of the Library that is interface-compatible with the Linked
|
114
|
+
Version.
|
115
|
+
|
116
|
+
e) Provide Installation Information, but only if you would otherwise
|
117
|
+
be required to provide such information under section 6 of the
|
118
|
+
GNU GPL, and only to the extent that such information is
|
119
|
+
necessary to install and execute a modified version of the
|
120
|
+
Combined Work produced by recombining or relinking the
|
121
|
+
Application with a modified version of the Linked Version. (If
|
122
|
+
you use option 4d0, the Installation Information must accompany
|
123
|
+
the Minimal Corresponding Source and Corresponding Application
|
124
|
+
Code. If you use option 4d1, you must provide the Installation
|
125
|
+
Information in the manner specified by section 6 of the GNU GPL
|
126
|
+
for conveying Corresponding Source.)
|
127
|
+
|
128
|
+
5. Combined Libraries.
|
129
|
+
|
130
|
+
You may place library facilities that are a work based on the
|
131
|
+
Library side by side in a single library together with other library
|
132
|
+
facilities that are not Applications and are not covered by this
|
133
|
+
License, and convey such a combined library under terms of your
|
134
|
+
choice, if you do both of the following:
|
135
|
+
|
136
|
+
a) Accompany the combined library with a copy of the same work based
|
137
|
+
on the Library, uncombined with any other library facilities,
|
138
|
+
conveyed under the terms of this License.
|
139
|
+
|
140
|
+
b) Give prominent notice with the combined library that part of it
|
141
|
+
is a work based on the Library, and explaining where to find the
|
142
|
+
accompanying uncombined form of the same work.
|
143
|
+
|
144
|
+
6. Revised Versions of the GNU Lesser General Public License.
|
145
|
+
|
146
|
+
The Free Software Foundation may publish revised and/or new versions
|
147
|
+
of the GNU Lesser General Public License from time to time. Such new
|
148
|
+
versions will be similar in spirit to the present version, but may
|
149
|
+
differ in detail to address new problems or concerns.
|
150
|
+
|
151
|
+
Each version is given a distinguishing version number. If the
|
152
|
+
Library as you received it specifies that a certain numbered version
|
153
|
+
of the GNU Lesser General Public License "or any later version"
|
154
|
+
applies to it, you have the option of following the terms and
|
155
|
+
conditions either of that published version or of any later version
|
156
|
+
published by the Free Software Foundation. If the Library as you
|
157
|
+
received it does not specify a version number of the GNU Lesser
|
158
|
+
General Public License, you may choose any version of the GNU Lesser
|
159
|
+
General Public License ever published by the Free Software Foundation.
|
160
|
+
|
161
|
+
If the Library as you received it specifies that a proxy can decide
|
162
|
+
whether future versions of the GNU Lesser General Public License shall
|
163
|
+
apply, that proxy's public statement of acceptance of any version is
|
164
|
+
permanent authorization for you to choose that version for the
|
165
|
+
Library.
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# ActiveRepository
|
2
2
|
|
3
|
-
[![Build Status](https://secure.travis-ci.org/efreesen/active_repository.png)](http://travis-ci.org/efreesen/active_repository)[![Dependency Status](https://gemnasium.com/efreesen/active_repository.png)](https://gemnasium.com/efreesen/active_repository) [![Code Climate](https://codeclimate.com/github/efreesen/active_repository.png)](https://codeclimate.com/github/efreesen/active_repository)
|
3
|
+
[[![Coverage Status](https://coveralls.io/repos/efreesen/active_repository/badge.png)](https://coveralls.io/r/efreesen/active_repository)![Build Status](https://secure.travis-ci.org/efreesen/active_repository.png)](http://travis-ci.org/efreesen/active_repository)[![Dependency Status](https://gemnasium.com/efreesen/active_repository.png)](https://gemnasium.com/efreesen/active_repository) [![Code Climate](https://codeclimate.com/github/efreesen/active_repository.png)](https://codeclimate.com/github/efreesen/active_repository)
|
4
4
|
|
5
5
|
ActiveRepository was designed so you can build your Business Models without depending on any ORM. It by default saves your data in memory using ActiveHash (https://github.com/zilkey/active_hash). Then when you decide which ORM you want to use you only have to connect ActiveRepository with it.
|
6
6
|
|
data/active_repository.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.name = "active_repository"
|
14
14
|
gem.require_paths = ["lib"]
|
15
15
|
gem.version = ActiveRepository::VERSION
|
16
|
-
gem.license = "
|
16
|
+
gem.license = "GPL"
|
17
17
|
gem.files = [
|
18
18
|
"LICENSE",
|
19
19
|
"README.md",
|
@@ -36,6 +36,7 @@ Gem::Specification.new do |gem|
|
|
36
36
|
gem.add_development_dependency(%q<activerecord>, [">= 3.2.6"])
|
37
37
|
gem.add_development_dependency(%q<mongoid>, [">= 3.0.11"])
|
38
38
|
gem.add_development_dependency('rake', [">= 10.0.0"])
|
39
|
+
gem.add_development_dependency('coveralls')
|
39
40
|
gem.add_development_dependency(%q<sqlite3>) unless RUBY_PLATFORM == 'java'
|
40
41
|
gem.add_development_dependency(%q<jdbc-sqlite3>) if RUBY_PLATFORM == 'java'
|
41
42
|
gem.add_development_dependency(%q<jruby-openssl>) if RUBY_PLATFORM == 'java'
|
@@ -1,20 +1,17 @@
|
|
1
1
|
# Defines the relations between ActiveRepository objects and/or ActiveRecord Models.
|
2
2
|
#
|
3
3
|
# Author:: Caio Torres (mailto:efreesen@gmail.com)
|
4
|
-
# License::
|
4
|
+
# License:: GPL
|
5
5
|
|
6
6
|
module ActiveRepository
|
7
7
|
module Associations
|
8
|
-
|
9
8
|
#:nodoc:
|
10
9
|
module ActiveRecordExtensions
|
11
|
-
|
12
|
-
|
13
10
|
# Defines belongs to type relation between ActiveRepository objects and ActivRecord Models.
|
14
11
|
def belongs_to_active_repository(association_id, options = {})
|
15
12
|
options = {
|
16
|
-
:
|
17
|
-
:
|
13
|
+
class_name: association_id.to_s.classify,
|
14
|
+
foreign_key: association_id.to_s.foreign_key
|
18
15
|
}.merge(options)
|
19
16
|
|
20
17
|
define_method(association_id) do
|
@@ -30,9 +27,8 @@ module ActiveRepository
|
|
30
27
|
association_id.to_sym,
|
31
28
|
options,
|
32
29
|
options[:class_name].constantize
|
33
|
-
|
30
|
+
)
|
34
31
|
end
|
35
|
-
|
36
32
|
end
|
37
33
|
|
38
34
|
#:nodoc:
|
@@ -46,8 +42,8 @@ module ActiveRepository
|
|
46
42
|
def has_many(association_id, options = {})
|
47
43
|
define_method(association_id) do
|
48
44
|
options = {
|
49
|
-
:
|
50
|
-
:
|
45
|
+
class_name: association_id.to_s.classify,
|
46
|
+
foreign_key: self.class.to_s.foreign_key
|
51
47
|
}.merge(options)
|
52
48
|
|
53
49
|
klass = options[:class_name].constantize
|
@@ -65,8 +61,8 @@ module ActiveRepository
|
|
65
61
|
def has_one(association_id, options = {})
|
66
62
|
define_method(association_id) do
|
67
63
|
options = {
|
68
|
-
:
|
69
|
-
:
|
64
|
+
class_name: association_id.to_s.classify,
|
65
|
+
foreign_key: self.class.to_s.foreign_key
|
70
66
|
}.merge(options)
|
71
67
|
|
72
68
|
scope = options[:class_name].constantize
|
@@ -74,6 +70,7 @@ module ActiveRepository
|
|
74
70
|
if scope.respond_to?(:scoped) && options[:conditions]
|
75
71
|
scope = scope.scoped(:conditions => options[:conditions])
|
76
72
|
end
|
73
|
+
|
77
74
|
scope.send("find_by_#{options[:foreign_key]}", id)
|
78
75
|
end
|
79
76
|
end
|
@@ -81,8 +78,8 @@ module ActiveRepository
|
|
81
78
|
# Defines "belongs to" type relation between ActiveRepository objects
|
82
79
|
def belongs_to(association_id, options = {})
|
83
80
|
options = {
|
84
|
-
:
|
85
|
-
:
|
81
|
+
class_name: association_id.to_s.classify,
|
82
|
+
foreign_key: association_id.to_s.foreign_key
|
86
83
|
}.merge(options)
|
87
84
|
|
88
85
|
field options[:foreign_key].to_sym
|
@@ -102,9 +99,7 @@ module ActiveRepository
|
|
102
99
|
attributes.delete(association_id.to_sym)
|
103
100
|
send("#{options[:foreign_key]}=", (new_value.try(:id) ? new_value.id : new_value))
|
104
101
|
end
|
105
|
-
|
106
102
|
end
|
107
103
|
end
|
108
|
-
|
109
104
|
end
|
110
105
|
end
|
@@ -51,7 +51,7 @@ module ActiveRepository
|
|
51
51
|
# end
|
52
52
|
#
|
53
53
|
# Author:: Caio Torres (mailto:efreesen@gmail.com)
|
54
|
-
# License::
|
54
|
+
# License:: GPL
|
55
55
|
class Base < ActiveHash::Base
|
56
56
|
extend ActiveModel::Callbacks
|
57
57
|
extend ActiveRepository::Finders
|
@@ -69,8 +69,7 @@ module ActiveRepository
|
|
69
69
|
|
70
70
|
# Returns all persisted objects
|
71
71
|
def self.all
|
72
|
-
(
|
73
|
-
# self == get_model_class ? super : get_model_class.all.map { |object| serialize!(object.attributes) }
|
72
|
+
(repository? ? super : PersistenceAdapter.all(self).map { |object| serialize!(object.attributes) })
|
74
73
|
end
|
75
74
|
|
76
75
|
# Constantize class name
|
@@ -80,21 +79,12 @@ module ActiveRepository
|
|
80
79
|
|
81
80
|
# Deletes all persisted objects
|
82
81
|
def self.delete_all
|
83
|
-
|
82
|
+
repository? ? super : PersistenceAdapter.delete_all(self)
|
84
83
|
end
|
85
84
|
|
86
85
|
# Checks the existence of a persisted object with the specified id
|
87
86
|
def self.exists?(id)
|
88
|
-
|
89
|
-
# if self == get_model_class
|
90
|
-
# !find_by_id(id).nil?
|
91
|
-
# else
|
92
|
-
# if mongoid?
|
93
|
-
# find_by_id(id).present?
|
94
|
-
# else
|
95
|
-
# get_model_class.exists?(id)
|
96
|
-
# end
|
97
|
-
# end
|
87
|
+
repository? ? find_by_id(id).present? : PersistenceAdapter.exists?(self, id)
|
98
88
|
end
|
99
89
|
|
100
90
|
# Returns the Class responsible for persisting the objects
|
@@ -122,7 +112,7 @@ module ActiveRepository
|
|
122
112
|
def self.set_model_class(value)
|
123
113
|
self.model_class = value if model_class.nil?
|
124
114
|
|
125
|
-
self.set_save_in_memory(
|
115
|
+
self.set_save_in_memory(repository?)
|
126
116
|
|
127
117
|
field_names.each do |field_name|
|
128
118
|
define_custom_find_by_field(field_name)
|
@@ -145,21 +135,23 @@ module ActiveRepository
|
|
145
135
|
# * RelatedClass.where("name = 'Peter'")
|
146
136
|
def self.where(*args)
|
147
137
|
raise ArgumentError.new("wrong number of arguments (0 for 1)") if args.empty?
|
148
|
-
if self == get_model_class
|
149
|
-
query = ActiveHash::SQLQueryExecutor.args_to_query(args)
|
150
|
-
super(query)
|
151
|
-
else
|
152
|
-
objects = []
|
153
|
-
args = args.first.is_a?(Hash) ? args.first : (args.first.is_a?(Array) ? args.first : args)
|
154
138
|
|
155
|
-
|
156
|
-
|
139
|
+
if repository?
|
140
|
+
args = args.first if args.try(:first).is_a?(Array)
|
141
|
+
super(ActiveHash::SQLQueryExecutor.args_to_query(args))
|
142
|
+
else
|
143
|
+
objects = PersistenceAdapter.where(self, sanitize_args(args)).map do |object|
|
144
|
+
self.serialize!(object.attributes)
|
157
145
|
end
|
158
146
|
|
159
147
|
objects
|
160
148
|
end
|
161
149
|
end
|
162
150
|
|
151
|
+
def get_model_class
|
152
|
+
self.class.get_model_class
|
153
|
+
end
|
154
|
+
|
163
155
|
# Persists the object using the class defined on the model_class attribute, if none defined it
|
164
156
|
# is saved in memory.
|
165
157
|
def persist
|
@@ -170,24 +162,24 @@ module ActiveRepository
|
|
170
162
|
|
171
163
|
# Gathers the persisted object from database and updates self with it's attributes.
|
172
164
|
def reload
|
173
|
-
object = self.id.present? ?
|
165
|
+
object = self.id.present? ? get_model_class.find(self.id) : self
|
174
166
|
|
175
167
|
serialize! object.attributes
|
176
168
|
end
|
177
169
|
|
178
170
|
def save(force=false)
|
179
|
-
if self.class ==
|
180
|
-
object =
|
171
|
+
if self.class == get_model_class
|
172
|
+
object = get_model_class.find(self.id)
|
181
173
|
|
182
174
|
if force || self.id.nil?
|
183
175
|
self.id = nil if self.id.nil?
|
184
176
|
super
|
185
|
-
|
177
|
+
elsif self.valid?
|
186
178
|
object.attributes = self.attributes
|
187
179
|
object.save(true)
|
188
180
|
end
|
189
181
|
|
190
|
-
|
182
|
+
self.valid?
|
191
183
|
else
|
192
184
|
self.persist
|
193
185
|
end
|
@@ -206,10 +198,10 @@ module ActiveRepository
|
|
206
198
|
# Find related object on the database and updates it with attributes in self, if it didn't
|
207
199
|
# find it on database it creates a new one.
|
208
200
|
def convert(attribute="id")
|
209
|
-
klass =
|
201
|
+
klass = get_model_class
|
210
202
|
object = klass.where(attribute.to_sym => self.send(attribute)).first
|
211
203
|
|
212
|
-
object ||=
|
204
|
+
object ||= get_model_class.new
|
213
205
|
|
214
206
|
attributes = self.attributes
|
215
207
|
|
@@ -224,17 +216,25 @@ module ActiveRepository
|
|
224
216
|
object
|
225
217
|
end
|
226
218
|
|
227
|
-
# Returns the value of the model_class attribute.
|
228
|
-
def model_class
|
229
|
-
self.model_class
|
230
|
-
end
|
231
|
-
|
232
219
|
private
|
220
|
+
|
233
221
|
# Checks if model_class is a Mongoid model
|
234
222
|
def self.mongoid?
|
235
223
|
get_model_class.included_modules.include?(Mongoid::Document)
|
236
224
|
end
|
237
225
|
|
226
|
+
def self.repository?
|
227
|
+
self == get_model_class
|
228
|
+
end
|
229
|
+
|
230
|
+
def self.sanitize_args(args)
|
231
|
+
args.first.is_a?(Hash) ? args.first : (args.first.is_a?(Array) ? args.first : args)
|
232
|
+
end
|
233
|
+
|
234
|
+
def repository?
|
235
|
+
self.class.repository?
|
236
|
+
end
|
237
|
+
|
238
238
|
# Checks if model_class is a Mongoid model
|
239
239
|
def mongoid?
|
240
240
|
self.class.mongoid?
|
@@ -32,7 +32,7 @@ module ActiveRepository #:nodoc:
|
|
32
32
|
# Searches for a object containing the id in #id
|
33
33
|
def find(id)
|
34
34
|
begin
|
35
|
-
if
|
35
|
+
if repository?
|
36
36
|
super(id)
|
37
37
|
else
|
38
38
|
object = (id == :all) ? all : PersistenceAdapter.find(self, id)
|
@@ -53,7 +53,7 @@ module ActiveRepository #:nodoc:
|
|
53
53
|
|
54
54
|
# raise "field: #{field_name}; values: #{args.first.inspect}; all: #{get_model_class.all.inspect}"
|
55
55
|
|
56
|
-
if
|
56
|
+
if repository?
|
57
57
|
objects = self.where(field_name.to_sym => args.first)
|
58
58
|
else
|
59
59
|
objects = PersistenceAdapter.where(self, field_name.to_sym => args.first)
|
@@ -75,7 +75,7 @@ module ActiveRepository #:nodoc:
|
|
75
75
|
|
76
76
|
# Searches for an object that has id with #id value, if none is found returns nil
|
77
77
|
def find_by_id(id)
|
78
|
-
if
|
78
|
+
if repository?
|
79
79
|
object = super(id)
|
80
80
|
|
81
81
|
object.nil? ? nil : object.dup
|
@@ -94,12 +94,12 @@ module ActiveRepository #:nodoc:
|
|
94
94
|
|
95
95
|
# Returns first persisted object
|
96
96
|
def first
|
97
|
-
|
97
|
+
repository? ? super : get(:first)
|
98
98
|
end
|
99
99
|
|
100
100
|
# Returns last persisted object
|
101
101
|
def last
|
102
|
-
|
102
|
+
repository? ? super : get(:last)
|
103
103
|
end
|
104
104
|
|
105
105
|
private
|
@@ -19,7 +19,7 @@ module ActiveHash #:nodoc:
|
|
19
19
|
# Recursive method that divides the query in sub queries, executes each part individually
|
20
20
|
# and finally relates its results as specified in the query.
|
21
21
|
def execute(klass, query)
|
22
|
-
@operator, @sub_query, @objects = process_first(klass, query, query.split(" ")[1])
|
22
|
+
@operator, @sub_query, @objects = process_first(klass, query, query.split(" ")[1].downcase)
|
23
23
|
|
24
24
|
@operator.nil? ? @objects : @objects.send(@operator, execute(klass, @sub_query)).sort_by{ |o| o.id }
|
25
25
|
end
|
@@ -32,7 +32,7 @@ module ActiveHash #:nodoc:
|
|
32
32
|
when "between"
|
33
33
|
array[0..5]
|
34
34
|
when "is"
|
35
|
-
size = array[2]
|
35
|
+
size = array[2] == "not" ? 4 : 3
|
36
36
|
array[0..size]
|
37
37
|
else
|
38
38
|
array[0..3]
|
@@ -43,7 +43,7 @@ module ActiveHash #:nodoc:
|
|
43
43
|
# split into separate components of the query.
|
44
44
|
def convert_attrs(field, *attrs)
|
45
45
|
attrs.each_with_index do |attribute, i|
|
46
|
-
attribute = attribute.gsub("_", " ")
|
46
|
+
attribute = attribute.gsub("_", " ") rescue attribute
|
47
47
|
attrs[i] = field.is_a?(Integer) ? attribute.to_i : attribute
|
48
48
|
end
|
49
49
|
|
@@ -69,7 +69,8 @@ module ActiveHash #:nodoc:
|
|
69
69
|
# Execute SQL between filter
|
70
70
|
def execute_between(klass, sub_query)
|
71
71
|
klass.all.select do |o|
|
72
|
-
field
|
72
|
+
field = sub_query.first.gsub('(', '')
|
73
|
+
field, first_attr, second_attr = convert_attrs(o.send(field), sub_query[2], sub_query[4])
|
73
74
|
|
74
75
|
(field >= first_attr && field <= second_attr)
|
75
76
|
end
|
@@ -87,9 +88,15 @@ module ActiveHash #:nodoc:
|
|
87
88
|
# Executes the #sub_quey defined operator filter
|
88
89
|
def execute_operator(klass, sub_query)
|
89
90
|
klass.all.select do |o|
|
90
|
-
|
91
|
+
query = sub_query.first
|
91
92
|
|
92
|
-
|
93
|
+
if query
|
94
|
+
field, attribute = convert_attrs(o.send(query.gsub(/[\(\)]/, "")), sub_query[2])
|
95
|
+
|
96
|
+
field.blank? ? false : field.send(@operator, attribute)
|
97
|
+
else
|
98
|
+
false
|
99
|
+
end
|
93
100
|
end
|
94
101
|
end
|
95
102
|
|
@@ -109,7 +116,7 @@ module ActiveHash #:nodoc:
|
|
109
116
|
def get_operator(attributes)
|
110
117
|
operator = attributes.size >= 4 ? attributes.last : nil
|
111
118
|
|
112
|
-
case operator
|
119
|
+
case operator.try(:downcase)
|
113
120
|
when "or" then "+"
|
114
121
|
when "and" then "&"
|
115
122
|
else nil
|
@@ -118,7 +125,7 @@ module ActiveHash #:nodoc:
|
|
118
125
|
|
119
126
|
# Processes the first sub query in query
|
120
127
|
def process_first(klass, query, operator)
|
121
|
-
@operator = operator == "=" ? "==" : operator
|
128
|
+
@operator = (operator == "=" ? "==" : (operator == '<>' ? '!=' : operator))
|
122
129
|
@query = sanitize_query(query)
|
123
130
|
sub_query = divide_query
|
124
131
|
|
@@ -126,7 +133,9 @@ module ActiveHash #:nodoc:
|
|
126
133
|
|
127
134
|
objects = execute_sub_query(klass, sub_query)
|
128
135
|
|
129
|
-
|
136
|
+
query_array = query.split(' ')
|
137
|
+
|
138
|
+
sub_query = query_array[sub_query.size..query_array.size].join(' ')
|
130
139
|
|
131
140
|
[binding_operator, sub_query, objects]
|
132
141
|
end
|
@@ -11,14 +11,11 @@ module ActiveModel
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def validate_each(record, attribute, value)
|
14
|
-
|
15
|
-
|
16
|
-
finder_class.all.each do |object|
|
17
|
-
if object.id != record.id && object.send(attribute) == record.send(attribute)
|
18
|
-
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope, :conditions).merge(:value => value))
|
19
|
-
break
|
20
|
-
end
|
14
|
+
duplicate = record.get_model_class.where("id != ?", record.id).select do |object|
|
15
|
+
object.id != record.id && object.send(attribute) == record.send(attribute)
|
21
16
|
end
|
17
|
+
|
18
|
+
record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope, :conditions).merge(:value => value)) if duplicate.any?
|
22
19
|
end
|
23
20
|
|
24
21
|
protected
|
@@ -39,14 +36,8 @@ module ActiveModel
|
|
39
36
|
end
|
40
37
|
|
41
38
|
def build_relation(klass, table, attribute, value) #:nodoc:
|
42
|
-
|
43
|
-
|
44
|
-
column = klass.columns_hash[reflection.foreign_key]
|
45
|
-
attribute = reflection.foreign_key
|
46
|
-
value = value.attributes[reflection.primary_key_column.name]
|
47
|
-
else
|
48
|
-
column = klass.columns_hash[attribute.to_s]
|
49
|
-
end
|
39
|
+
column, attribute, value = get_reflection_attributes(klass)
|
40
|
+
|
50
41
|
value = column.limit ? value.to_s[0, column.limit] : value.to_s if !value.nil? && column.text?
|
51
42
|
|
52
43
|
if !options[:case_sensitive] && value && column.text?
|
@@ -59,6 +50,21 @@ module ActiveModel
|
|
59
50
|
|
60
51
|
relation
|
61
52
|
end
|
53
|
+
|
54
|
+
private
|
55
|
+
def get_reflection_attributes(klass, attribute, value)
|
56
|
+
reflection = klass.reflect_on_association(attribute)
|
57
|
+
column = klass.columns_hash[reflection.foreign_key]
|
58
|
+
|
59
|
+
if reflection
|
60
|
+
attribute = reflection.foreign_key
|
61
|
+
value = value.attributes[reflection.primary_key_column.name]
|
62
|
+
else
|
63
|
+
column = klass.columns_hash[attribute.to_s]
|
64
|
+
end
|
65
|
+
|
66
|
+
[column, attribute, value]
|
67
|
+
end
|
62
68
|
end
|
63
69
|
|
64
70
|
module ClassMethods
|
@@ -94,7 +94,7 @@ module ActiveHash
|
|
94
94
|
end
|
95
95
|
|
96
96
|
def eql?(other)
|
97
|
-
(other.instance_of?(self.class) || other.instance_of?(
|
97
|
+
(other.instance_of?(self.class) || other.instance_of?(get_model_class)) && id.present? && (id == other.id) && (!self.respond_to?(:created_at) || (created_at == other.created_at))
|
98
98
|
end
|
99
99
|
|
100
100
|
alias == eql?
|
@@ -32,11 +32,11 @@ module ActiveRepository
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def find_or_initialize(attributes)
|
35
|
-
|
36
|
-
object
|
35
|
+
attributes = attributes.symbolize_keys if attributes.respond_to?(:symbolize_keys)
|
36
|
+
object = where(attributes).first || self.new(attributes)
|
37
37
|
|
38
38
|
attributes.each do |key, value|
|
39
|
-
object.send("#{key
|
39
|
+
object.send("#{key}=", value)
|
40
40
|
end
|
41
41
|
|
42
42
|
serialize!(object.attributes)
|
@@ -63,35 +63,31 @@ module ActiveRepository
|
|
63
63
|
|
64
64
|
# Updates #key attribute with #value value.
|
65
65
|
def update_attribute(key, value)
|
66
|
-
ret =
|
67
|
-
|
68
|
-
if ret
|
69
|
-
if self.class == self.class.get_model_class
|
70
|
-
object = self.class.find_or_initialize(:id => self.id)
|
71
|
-
|
72
|
-
self.send("#{key}=", value)
|
66
|
+
ret = true
|
67
|
+
key = key.to_sym
|
73
68
|
|
74
|
-
|
75
|
-
|
76
|
-
# key = (key.to_s == 'id' ? '_id' : key.to_s) if mongoid?
|
69
|
+
if self.class == get_model_class
|
70
|
+
object = self.class.find_or_initialize(:id => self.id)
|
77
71
|
|
78
|
-
|
72
|
+
self.send("#{key}=", value)
|
79
73
|
|
80
|
-
|
81
|
-
|
82
|
-
|
74
|
+
ret = self.save
|
75
|
+
else
|
76
|
+
ret, object = PersistenceAdapter.update_attribute(self.class, self.id, key, value)
|
83
77
|
|
84
|
-
|
78
|
+
self.attributes = object.attributes
|
85
79
|
end
|
86
80
|
|
81
|
+
reload
|
82
|
+
|
87
83
|
ret
|
88
84
|
end
|
89
85
|
|
90
86
|
# Updates attributes in self with the attributes in the parameter
|
91
87
|
def update_attributes(attributes)
|
92
|
-
|
88
|
+
attributes = attributes.symbolize_keys if attributes.respond_to?(:symbolize_keys)
|
93
89
|
klass = self.class
|
94
|
-
model_class =
|
90
|
+
model_class = get_model_class
|
95
91
|
|
96
92
|
if klass == model_class
|
97
93
|
attributes.each do |key, value|
|
@@ -103,12 +99,10 @@ module ActiveRepository
|
|
103
99
|
ret, object = PersistenceAdapter.update_attributes(self.class, self.id, attributes)
|
104
100
|
|
105
101
|
self.attributes = object.attributes
|
106
|
-
# object = self.id.nil? ? model_class.new : model_class.find(self.id)
|
107
|
-
|
108
|
-
# ret = object.update_attributes(attributes)
|
109
102
|
end
|
110
103
|
|
111
104
|
reload
|
105
|
+
|
112
106
|
ret
|
113
107
|
end
|
114
108
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -18,6 +18,14 @@ shared_examples ".update_attributes" do
|
|
18
18
|
Country.first.name.should == "Russia"
|
19
19
|
Country.first.id.should_not == 45
|
20
20
|
end
|
21
|
+
|
22
|
+
it "updates records whit string keys" do
|
23
|
+
id = Country.first.id
|
24
|
+
country = Country.find(id)
|
25
|
+
country.update_attributes('name' => "Germany")
|
26
|
+
|
27
|
+
Country.first.name.should == "Germany"
|
28
|
+
end
|
21
29
|
end
|
22
30
|
|
23
31
|
shared_examples ".all" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_repository
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Caio Torres
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-09-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_hash
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ! '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 10.0.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: coveralls
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: sqlite3
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,7 +154,7 @@ files:
|
|
140
154
|
- spec/spec_helper.rb
|
141
155
|
homepage: http://github.com/efreesen/active_repository
|
142
156
|
licenses:
|
143
|
-
-
|
157
|
+
- GPL
|
144
158
|
metadata: {}
|
145
159
|
post_install_message:
|
146
160
|
rdoc_options: []
|