active_repository 0.2.7 → 0.3.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 605ad373409e52ed436bd85e89904760fe97e049
4
+ data.tar.gz: 39716333dfbdaa9d447bb8be5f384148d8815b4d
5
+ SHA512:
6
+ metadata.gz: 2841548917d159c2ac40c46fc2aaea7d724cd3479a4842b6e71ce53b7ed076e3781539a5a2e54391b83cc9bae310267450ac179b9340057a767de655944e7b14
7
+ data.tar.gz: cd3890fb5aa63a1cbcd90c533121710eb2b68a9839b92dcbdd0b4db0d267d7c0dce11e2e6eb625b6193faf50e64c03bb6213deac7c924fff2175cd4d8cac9381
@@ -24,16 +24,18 @@ Gem::Specification.new do |gem|
24
24
  "Gemfile",
25
25
  "spec/active_repository/base_spec.rb",
26
26
  "spec/active_repository/associations_spec.rb",
27
+ "spec/active_repository/result_set_spec.rb",
27
28
  "spec/support/shared_examples.rb",
28
29
  "spec/spec_helper.rb"
29
30
  ]
30
31
 
31
- gem.add_runtime_dependency(%q<active_hash>, [">= 0.9.12"])
32
- gem.add_runtime_dependency(%q<activemodel>, [">= 3.2.6"])
33
- gem.add_runtime_dependency(%q<sql_query_executor>, [">= 0.0.1"])
32
+ gem.add_runtime_dependency(%q<active_hash>, [">= 1.2.3"])
33
+ gem.add_runtime_dependency(%q<activemodel>, [">= 3.2"])
34
+ gem.add_runtime_dependency(%q<sql_query_executor>, [">= 0.3.1"])
35
+ gem.add_development_dependency(%q<pry>)
34
36
  gem.add_development_dependency(%q<rspec>, [">= 2.2.0"])
35
- gem.add_development_dependency(%q<activerecord>, [">= 3.2.6"])
36
- gem.add_development_dependency(%q<mongoid>, [">= 3.0.11"])
37
+ gem.add_development_dependency(%q<activerecord>, [">= 3.2"])
38
+ gem.add_development_dependency(%q<mongoid>, [">= 3.1"])
37
39
  gem.add_development_dependency('rake', [">= 10.0.0"])
38
40
  gem.add_development_dependency('coveralls')
39
41
  gem.add_development_dependency(%q<sqlite3>) unless RUBY_PLATFORM == 'java'
@@ -5,7 +5,7 @@ class DefaultAdapter
5
5
  end
6
6
 
7
7
  def delete(klass, id)
8
- object = klass.get_model_class.find_by_id(id)
8
+ object = klass.get_model_class.where(id: id).first
9
9
  object.delete if object
10
10
  end
11
11
 
@@ -18,6 +18,8 @@ class DefaultAdapter
18
18
  end
19
19
 
20
20
  def find(klass, id)
21
+ id = normalize_id(id) if id
22
+
21
23
  klass.get_model_class.find(id)
22
24
  end
23
25
 
@@ -49,9 +51,21 @@ class DefaultAdapter
49
51
  [ret, object]
50
52
  end
51
53
 
52
- def where(klass, args)
53
- # raise args.inspect
54
- klass.get_model_class.where(args)
54
+ def where(klass, query)
55
+ klass.get_model_class.where(query.to_sql)
56
+ end
57
+
58
+ private
59
+ def normalize_id(args)
60
+ return args if args.is_a?(Array)
61
+
62
+ id = (args.is_a?(Hash) ? args[:id] : args)
63
+
64
+ convertable?(id) ? id.to_i : id
65
+ end
66
+
67
+ def convertable?(id)
68
+ id.respond_to?(:to_i) && id.to_s == id.to_i.to_s
55
69
  end
56
70
  end
57
71
  end
@@ -46,8 +46,8 @@ class MongoidAdapter < DefaultAdapter
46
46
  # [ret, object]
47
47
  # end
48
48
 
49
- # def where(klass, args)
50
- # klass.where(args)
51
- # end
49
+ def where(klass, query)
50
+ klass.get_model_class.where(query.selector)
51
+ end
52
52
  end
53
53
  end
@@ -1,4 +1,3 @@
1
- require 'active_repository/adapters/active_hash_adapter'
2
1
  require 'active_repository/adapters/default_adapter'
3
2
  require 'active_repository/adapters/mongoid_adapter'
4
3
 
@@ -8,10 +7,6 @@ class PersistenceAdapter
8
7
  modules = klass.get_model_class.included_modules.map(&:to_s)
9
8
  if modules.include?("Mongoid::Document")
10
9
  MongoidAdapter
11
- elsif modules.map(&:to_s).include?("DataMapper::Resource")
12
- DataMapperAdapter
13
- # elsif modules.map(&:to_s).include?("MongoMapper::Document")
14
- # MongoMapperAdapter
15
10
  else
16
11
  DefaultAdapter
17
12
  end
@@ -1,42 +1,14 @@
1
- # Defines the relations between ActiveRepository objects and/or ActiveRecord Models.
1
+ # Defines the relations between ActiveRepository objects.
2
2
  #
3
3
  # Author:: Caio Torres (mailto:efreesen@gmail.com)
4
4
  # License:: GPL
5
5
 
6
6
  module ActiveRepository
7
7
  module Associations
8
- #:nodoc:
9
- module ActiveRecordExtensions
10
- # Defines belongs to type relation between ActiveRepository objects and ActivRecord Models.
11
- def belongs_to_active_repository(association_id, options = {})
12
- options = {
13
- class_name: association_id.to_s.classify,
14
- foreign_key: association_id.to_s.foreign_key
15
- }.merge(options)
16
-
17
- define_method(association_id) do
18
- options[:class_name].constantize.find_by_id(send(options[:foreign_key]))
19
- end
20
-
21
- define_method("#{association_id}=") do |new_value|
22
- send "#{options[:foreign_key]}=", new_value ? new_value.id : nil
23
- end
24
-
25
- create_reflection(
26
- :belongs_to,
27
- association_id.to_sym,
28
- options,
29
- options[:class_name].constantize
30
- )
31
- end
32
- end
33
-
34
- #:nodoc:
35
8
  def self.included(base)
36
9
  base.extend Methods
37
10
  end
38
11
 
39
- #:nodoc:
40
12
  module Methods
41
13
  # Defines "has many" type relation between ActiveRepository objects
42
14
  def has_many(association_id, options = {})
@@ -49,11 +21,7 @@ module ActiveRepository
49
21
  klass = options[:class_name].constantize
50
22
  objects = []
51
23
 
52
- if klass.respond_to?(:scoped)
53
- objects = klass.scoped(:conditions => {options[:foreign_key] => id})
54
- else
55
- objects = klass.send("find_all_by_#{options[:foreign_key]}", id)
56
- end
24
+ klass.where(options[:foreign_key] => id)
57
25
  end
58
26
  end
59
27
 
@@ -67,11 +35,11 @@ module ActiveRepository
67
35
 
68
36
  scope = options[:class_name].constantize
69
37
 
70
- if scope.respond_to?(:scoped) && options[:conditions]
71
- scope = scope.scoped(:conditions => options[:conditions])
72
- end
73
-
74
- scope.send("find_by_#{options[:foreign_key]}", id)
38
+ scope = scope.where(options[:conditions]) if options[:conditions]
39
+
40
+ send_params = scope.respond_to?(:find_by) ? ["find_by", id: id] : ["find_by_id", id]
41
+
42
+ scope.send(*send_params)
75
43
  end
76
44
  end
77
45
 
@@ -89,7 +57,7 @@ module ActiveRepository
89
57
  id = send(options[:foreign_key])
90
58
 
91
59
  if id.present?
92
- object = klass.find_by_id(id)
60
+ object = klass.respond_to?(:find_by) ? klass.find_by(id: id) : klass.find_by_id(id)
93
61
  else
94
62
  nil
95
63
  end
@@ -5,6 +5,7 @@ require 'sql_query_executor'
5
5
  require 'active_repository/finders'
6
6
  require 'active_repository/writers'
7
7
  require 'active_repository/adapters/persistence_adapter'
8
+ require 'active_repository/result_set'
8
9
 
9
10
  begin
10
11
  klass = Module.const_get(Mongoid::Document)
@@ -84,7 +85,7 @@ module ActiveRepository
84
85
 
85
86
  # Checks the existence of a persisted object with the specified id
86
87
  def self.exists?(id)
87
- repository? ? find_by_id(id).present? : PersistenceAdapter.exists?(self, id)
88
+ repository? ? find_by(id: id).present? : PersistenceAdapter.exists?(self, id)
88
89
  end
89
90
 
90
91
  # Returns the Class responsible for persisting the objects
@@ -93,12 +94,29 @@ module ActiveRepository
93
94
  save_in_memory? ? self : self.model_class
94
95
  end
95
96
 
97
+ # Searches all objects that matches #field_name field with the #args value(s)
98
+ def self.find_by(args)
99
+ raise ArgumentError("Argument must be a Hash") unless args.is_a?(Hash)
100
+
101
+ objects = where(args)
102
+
103
+ objects.first
104
+ end
105
+
106
+ # Searches all objects that matches #field_name field with the #args value(s)
107
+ def self.find_by!(args)
108
+ object = find_by(args)
109
+
110
+ raise ActiveHash::RecordNotFound unless object
111
+ object
112
+ end
113
+
96
114
  # Converts Persisted object(s) to it's ActiveRepository counterpart
97
115
  def self.serialize!(other)
98
116
  case other.class.to_s
99
117
  when "Hash", "ActiveSupport::HashWithIndifferentAccess" then self.new.serialize!(other)
100
118
  when "Array" then other.map { |o| serialize!(o.attributes) }
101
- when "Moped::BSON::Document" then self.new.serialize!(other)
119
+ when "Moped::BSON::Document", "BSON::Document" then self.new.serialize!(other)
102
120
  else self.new.serialize!(other.attributes)
103
121
  end
104
122
  end
@@ -113,11 +131,6 @@ module ActiveRepository
113
131
  self.model_class = value if model_class.nil?
114
132
 
115
133
  self.set_save_in_memory(repository?)
116
-
117
- field_names.each do |field_name|
118
- define_custom_find_by_field(field_name)
119
- define_custom_find_all_by_field(field_name)
120
- end
121
134
  end
122
135
 
123
136
  # Sets the class attribute save_in_memory, set it to true to ignore model_class attribute
@@ -134,19 +147,25 @@ module ActiveRepository
134
147
  # * RelatedClass.where(:name => "Peter")
135
148
  # * RelatedClass.where("name = 'Peter'")
136
149
  def self.where(*args)
137
- raise ArgumentError.new("wrong number of arguments (0 for 1)") if args.empty?
150
+ raise ArgumentError.new("must pass at least one argument") if args.empty?
138
151
 
139
- if repository?
140
- args = args.first if args.try(:first).is_a?(Array)
141
- query_executor = SqlQueryExecutor::Base.new(all)
142
- query_executor.where(args)
143
- else
144
- objects = PersistenceAdapter.where(self, sanitize_args(args)).map do |object|
145
- self.serialize!(object.attributes)
146
- end
152
+ result_set = ActiveRepository::ResultSet.new(self)
147
153
 
148
- objects
149
- end
154
+ # binding.pry
155
+
156
+ result_set.where(args)
157
+
158
+ # if repository?
159
+ # args = args.first if args.respond_to?(:size) && args.size == 1
160
+ # query_executor = SqlQueryExecutor::Base.new(all)
161
+ # query_executor.where(args)
162
+ # else
163
+ # objects = PersistenceAdapter.where(self, sanitize_args(args)).map do |object|
164
+ # self.serialize!(object.attributes)
165
+ # end
166
+
167
+ # objects
168
+ # end
150
169
  end
151
170
 
152
171
  def get_model_class
@@ -163,14 +182,16 @@ module ActiveRepository
163
182
 
164
183
  # Gathers the persisted object from database and updates self with it's attributes.
165
184
  def reload
166
- object = self.id.present? ? get_model_class.find(self.id) : self
185
+ object = self.id.present? ?
186
+ get_model_class.where(id: self.id).first_or_initialize :
187
+ self
167
188
 
168
189
  serialize! object.attributes
169
190
  end
170
191
 
171
192
  def save(force=false)
172
193
  if self.class == get_model_class
173
- object = get_model_class.find(self.id)
194
+ object = get_model_class.where(id: self.id).first_or_initialize
174
195
 
175
196
  if force || self.id.nil?
176
197
  self.id = nil if self.id.nil?
@@ -221,29 +242,10 @@ module ActiveRepository
221
242
  end
222
243
 
223
244
  private
224
-
225
- # Checks if model_class is a Mongoid model
226
- def self.mongoid?
227
- get_model_class.included_modules.include?(Mongoid::Document)
228
- end
229
-
230
245
  def self.repository?
231
246
  self == get_model_class
232
247
  end
233
248
 
234
- def self.sanitize_args(args)
235
- args.first.is_a?(Hash) ? args.first : (args.first.is_a?(Array) ? args.first : args)
236
- end
237
-
238
- def repository?
239
- self.class.repository?
240
- end
241
-
242
- # Checks if model_class is a Mongoid model
243
- def mongoid?
244
- self.class.mongoid?
245
- end
246
-
247
249
  # Updates created_at and updated_at
248
250
  def set_timestamps
249
251
  if self.errors.empty?
@@ -1,43 +1,13 @@
1
1
  # Module containing methods responsible for searching ActiveRepository objects
2
2
  module ActiveRepository #:nodoc:
3
3
  module Finders #:nodoc:
4
- # Defines fiend_by_field methods for the Class
5
- def define_custom_find_by_field(field_name)
6
- method_name = :"find_by_#{field_name}"
7
- the_meta_class.instance_eval do
8
- define_method(method_name) do |*args|
9
- object = nil
10
-
11
- object = self.where(field_name.to_sym => args).first
12
-
13
- object.nil? ? nil : serialize!(object.attributes)
14
- end
15
- end
16
- end
17
-
18
- # Defines fiend_all_by_field methods for the Class
19
- def define_custom_find_all_by_field(field_name)
20
- method_name = :"find_all_by_#{field_name}"
21
- the_meta_class.instance_eval do
22
- define_method(method_name) do |*args|
23
- objects = []
24
-
25
- objects = self.find_all_by_field(field_name.to_sym, args)
26
-
27
- objects.empty? ? [] : objects.map{ |object| serialize!(object.attributes) }
28
- end
29
- end
30
- end
31
-
32
4
  # Searches for a object containing the id in #id
33
5
  def find(id)
34
6
  begin
35
7
  if repository?
36
8
  super(id)
37
9
  else
38
- object = (id == :all) ? all : PersistenceAdapter.find(self, id)
39
-
40
- serialize!(object)
10
+ serialize!(PersistenceAdapter.find(self, id))
41
11
  end
42
12
  rescue Exception => e
43
13
  message = "Couldn't find #{self} with ID=#{id}"
@@ -47,51 +17,6 @@ module ActiveRepository #:nodoc:
47
17
  end
48
18
  end
49
19
 
50
- # Searches all objects that matches #field_name field with the #args value(s)
51
- def find_all_by_field(field_name, args)
52
- objects = []
53
-
54
- # raise "field: #{field_name}; values: #{args.first.inspect}; all: #{get_model_class.all.inspect}"
55
-
56
- if repository?
57
- objects = self.where(field_name.to_sym => args.first)
58
- else
59
- objects = PersistenceAdapter.where(self, field_name.to_sym => args.first)
60
- # if mongoid?
61
- # objects = get_model_class.where(field_name.to_sym => args.first)
62
- # else
63
- # method_name = :"find_all_by_#{field_name}"
64
- # objects = get_model_class.send(method_name, args)
65
- # end
66
- end
67
-
68
- objects
69
- end
70
-
71
- # Searches first object that matches #field_name field with the #args value(s)
72
- # def find_by_field(field_name, args)
73
- # self.find_all_by_field(field_name, args).first.dup
74
- # end
75
-
76
- # Searches for an object that has id with #id value, if none is found returns nil
77
- def find_by_id(id)
78
- if repository?
79
- object = super(id)
80
-
81
- object.nil? ? nil : object.dup
82
- else
83
- object = PersistenceAdapter.where(self, :id => id).first
84
-
85
- # if mongoid?
86
- # object = get_model_class.where(:id => id).entries.first
87
- # else
88
- # object = get_model_class.find_by_id(id)
89
- # end
90
-
91
- object.nil? ? nil : serialize!(object.attributes)
92
- end
93
- end
94
-
95
20
  # Returns first persisted object
96
21
  def first
97
22
  repository? ? super : get(:first)
@@ -0,0 +1,76 @@
1
+ class ActiveRepository::ResultSet
2
+ def initialize(klass, query={}, attributes={})
3
+ @klass = klass
4
+ convert_query(query)
5
+ @attributes = query.is_a?(Hash) ? attributes.merge(query) : attributes
6
+ end
7
+
8
+ def all
9
+ @query ? get_result(@query) : @klass.all
10
+ end
11
+
12
+ def count
13
+ all.size
14
+ end
15
+
16
+ def first
17
+ @query ? all.first : @klass.all.first
18
+ end
19
+
20
+ def first_or_initialize
21
+ object = all.first
22
+
23
+ object ? object : @klass.new(@attributes)
24
+ end
25
+
26
+ def first_or_create
27
+ object = first_or_initialize
28
+
29
+ object.new_record? ? object.save : object
30
+
31
+ object.reload
32
+ end
33
+
34
+ def last
35
+ @query ? all.last : @klass.all.last
36
+ end
37
+
38
+ def where(query)
39
+ @attributes = @attributes.merge(query) if query.is_a?(Hash)
40
+ query = join_query(query, 'and')
41
+
42
+ ActiveRepository::ResultSet.new(@klass, query, @attributes)
43
+ end
44
+ alias_method :and, :where
45
+
46
+ def or(query)
47
+ query = join_query(query, 'or')
48
+
49
+ ActiveRepository::ResultSet.new(@klass, query, @attributes)
50
+ end
51
+
52
+ private
53
+ def convert_query(query)
54
+ @query = SqlQueryExecutor::Query::QueryNormalizer.clean_query(query)
55
+ end
56
+
57
+ def get_result(args)
58
+ if @klass.repository?
59
+ args = args.first if args.is_a?(Array) && args.size == 1
60
+ query_executor = SqlQueryExecutor::Base.new(@klass.all, args)
61
+ query_executor.execute!
62
+ else
63
+ query = SqlQueryExecutor::Base.new([], args)
64
+ objects = PersistenceAdapter.where(@klass, query).map do |object|
65
+ @klass.serialize!(object.attributes)
66
+ end
67
+
68
+ objects
69
+ end
70
+ end
71
+
72
+ def join_query(query, separator)
73
+ query = SqlQueryExecutor::Query::QueryNormalizer.clean_query(query)
74
+ query.blank? ? @query : (@query.blank? ? query : "(#{@query}) #{separator} (#{query})")
75
+ end
76
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveRepository
2
- VERSION = "0.2.7"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -40,32 +40,17 @@ module ActiveHash
40
40
  end
41
41
  end
42
42
 
43
- def self.where(query)
44
- if query.is_a?(String)
45
- return ActiveHash::SQLQueryExecutor.execute(self, query)
46
- else
47
- (@records || []).select do |record|
48
- query.all? { |col, match| record[col] == match }
49
- end
50
- end
51
- end
52
-
53
43
  def self.validate_unique_id(record)
54
44
  raise IdError.new("Duplicate Id found for record #{record.attributes}") if record_index.has_key?(record.id.to_s)
55
45
  end
56
46
 
57
- def update_attribute(key, value)
58
- self.send("#{key}=", value)
59
- self.save(:validate => false)
60
- end
61
-
62
47
  def readonly?
63
48
  false
64
49
  end
65
50
 
66
51
  def save(*args)
67
52
  if self.valid?
68
- record = self.class.find_by_id(self.id)
53
+ record = self.class.find_by(id: self.id)
69
54
 
70
55
  self.class.insert(self) if record.nil? && record != self
71
56
 
@@ -77,11 +62,11 @@ module ActiveHash
77
62
  end
78
63
 
79
64
  def delete
80
- record = self.class.find_by_id(self.id)
65
+ record = self.class.find_by(id: self.id)
81
66
 
82
67
  self.class.remove(self)
83
68
 
84
- self.class.find_by_id(self.id).nil?
69
+ self.class.find_by(id: self.id).nil?
85
70
  end
86
71
 
87
72
  def to_param
@@ -89,7 +74,7 @@ module ActiveHash
89
74
  end
90
75
 
91
76
  def persisted?
92
- other = self.class.find_by_id(id)
77
+ other = self.class.find_by(id: id)
93
78
  other.present?
94
79
  end
95
80
 
@@ -23,25 +23,6 @@ module ActiveRepository
23
23
  new_object
24
24
  end
25
25
 
26
- # Searches for an object that matches the attributes on the parameter, if none is found
27
- # it creates one with the defined attributes.
28
- def find_or_create(attributes)
29
- object = where(attributes).first
30
-
31
- object.nil? ? create(attributes) : object
32
- end
33
-
34
- def find_or_initialize(attributes)
35
- attributes = attributes.symbolize_keys if attributes.respond_to?(:symbolize_keys)
36
- object = where(attributes).first || self.new(attributes)
37
-
38
- attributes.each do |key, value|
39
- object.send("#{key}=", value)
40
- end
41
-
42
- serialize!(object.attributes)
43
- end
44
-
45
26
  #:nodoc:
46
27
  module InstanceMethods
47
28
  # Assigns new_attributes parameter to the attributes in self.
@@ -67,7 +48,7 @@ module ActiveRepository
67
48
  key = key.to_sym
68
49
 
69
50
  if self.class == get_model_class
70
- object = self.class.find_or_initialize(:id => self.id)
51
+ object = self.class.where(:id => self.id).first_or_initialize
71
52
 
72
53
  self.send("#{key}=", value)
73
54