active_any 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rubocop.yml +27 -0
  4. data/.travis.yml +5 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +6 -0
  7. data/Guardfile +10 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +92 -0
  10. data/Rakefile +12 -0
  11. data/active_any.gemspec +36 -0
  12. data/bin/console +12 -0
  13. data/bin/setup +8 -0
  14. data/lib/active_any/adapter.rb +13 -0
  15. data/lib/active_any/adapters/abstract_adapter.rb +27 -0
  16. data/lib/active_any/adapters/object_adapter.rb +74 -0
  17. data/lib/active_any/association_relation.rb +18 -0
  18. data/lib/active_any/associations/association.rb +94 -0
  19. data/lib/active_any/associations/association_scope.rb +35 -0
  20. data/lib/active_any/associations/belongs_to_association.rb +21 -0
  21. data/lib/active_any/associations/builder/association.rb +62 -0
  22. data/lib/active_any/associations/builder/belongs_to.rb +13 -0
  23. data/lib/active_any/associations/builder/has_many.rb +17 -0
  24. data/lib/active_any/associations/collection_proxy.rb +66 -0
  25. data/lib/active_any/associations/has_many_association.rb +43 -0
  26. data/lib/active_any/associations.rb +72 -0
  27. data/lib/active_any/attribute_assignment.rb +16 -0
  28. data/lib/active_any/core.rb +26 -0
  29. data/lib/active_any/finders.rb +28 -0
  30. data/lib/active_any/reflection/association_reflection.rb +88 -0
  31. data/lib/active_any/reflection/belongs_to_reflection.rb +29 -0
  32. data/lib/active_any/reflection/has_many_reflection.rb +29 -0
  33. data/lib/active_any/reflection.rb +49 -0
  34. data/lib/active_any/relation/merger.rb +72 -0
  35. data/lib/active_any/relation/order_clause.rb +60 -0
  36. data/lib/active_any/relation/where_clause.rb +73 -0
  37. data/lib/active_any/relation.rb +243 -0
  38. data/lib/active_any/version.rb +5 -0
  39. data/lib/active_any.rb +62 -0
  40. metadata +251 -0
@@ -0,0 +1,243 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_any/relation/merger'
4
+ require 'active_any/relation/where_clause'
5
+ require 'active_any/relation/order_clause'
6
+
7
+ module ActiveAny
8
+ class Relation # rubocop:disable Metrics/ClassLength
9
+ attr_reader :loaded, :klass
10
+
11
+ delegate :each, to: :records
12
+
13
+ include Enumerable
14
+
15
+ class ImmutableRelation < StandardError; end
16
+
17
+ MULTI_VALUE_METHODS = %i[group].freeze
18
+ SINGLE_VALUE_METHODS = %i[limit].freeze
19
+ CLAUSE_METHODS = %i[where order].freeze
20
+ VALUE_METHODS = (MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS).freeze
21
+
22
+ Relation::VALUE_METHODS.each do |name|
23
+ method_name = \
24
+ case name
25
+ when *Relation::MULTI_VALUE_METHODS then "#{name}_values"
26
+ when *Relation::SINGLE_VALUE_METHODS then "#{name}_value"
27
+ when *Relation::CLAUSE_METHODS then "#{name}_clause"
28
+ end
29
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
30
+ def #{method_name} # def includes_values
31
+ get_value(#{name.inspect}) # get_value(:includes)
32
+ end # end
33
+
34
+ def #{method_name}=(value) # def includes_values=(value)
35
+ set_value(#{name.inspect}, value) # set_value(:includes, value)
36
+ end # end
37
+ CODE
38
+ end
39
+
40
+ def self.create(klass, *args)
41
+ new(klass, *args)
42
+ end
43
+
44
+ def initialize(klass)
45
+ @klass = klass
46
+ @records = []
47
+ @loaded = false
48
+ @values = {}
49
+ end
50
+
51
+ def get_value(name)
52
+ @values[name] || default_value_for(name)
53
+ end
54
+
55
+ def set_value(name, value)
56
+ assert_mutability!
57
+ @values[name] = value
58
+ end
59
+
60
+ def to_a
61
+ records.dup
62
+ end
63
+
64
+ def limit(value)
65
+ spawn.limit!(value)
66
+ end
67
+
68
+ def where(condition)
69
+ spawn.where!(condition)
70
+ end
71
+
72
+ def find_by(condition)
73
+ where(condition).take
74
+ end
75
+
76
+ def take(limit = nil)
77
+ limit ? find_take_with_limit(limit) : find_take
78
+ end
79
+
80
+ def first(limit = nil)
81
+ if loaded
82
+ limit ? records.first(limit) : records.first
83
+ else
84
+ limit ? spawn.records.first(limit) : spawn.records.first
85
+ end
86
+ end
87
+
88
+ def last(limit = nil)
89
+ return find_last(limit) if loaded? || limit_value
90
+
91
+ result = limit(limit)
92
+ result.order!(klass.primary_key) if order_clause.empty? && klass.primary_key
93
+ result = result.reverse_order!
94
+ limit ? result.reverse : result.first
95
+ end
96
+
97
+ def reverse_order
98
+ spawn.reverse_order!
99
+ end
100
+
101
+ def reverse_order!
102
+ self.order_clause = order_clause.reverse!
103
+ self
104
+ end
105
+
106
+ def find_last(limit)
107
+ limit ? records.last(limit) : records.last
108
+ end
109
+
110
+ def group(*args)
111
+ spawn.group!(*args)
112
+ end
113
+
114
+ def order(*args)
115
+ spawn.order!(*args)
116
+ end
117
+
118
+ def merge(other)
119
+ if other.is_a?(Array)
120
+ records & other
121
+ elsif other
122
+ spawn.merge!(other)
123
+ else
124
+ raise ArgumentError, "invalid argument: #{other.inspect}."
125
+ end
126
+ end
127
+
128
+ def merge!(other) # :nodoc:
129
+ if other.is_a?(Hash)
130
+ Relation::HashMerger.new(self, other).merge
131
+ elsif other.is_a?(Relation)
132
+ Relation::Merger.new(self, other).merge
133
+ elsif other.respond_to?(:to_proc)
134
+ instance_exec(&other)
135
+ else
136
+ raise ArgumentError, "#{other.inspect} is not an ActiveRecord::Relation"
137
+ end
138
+ end
139
+
140
+ def limit!(value)
141
+ self.limit_value = value
142
+ self
143
+ end
144
+
145
+ def where!(condition)
146
+ self.where_clause += WhereClause.new(condition)
147
+ self
148
+ end
149
+
150
+ def group!(*args)
151
+ args.flatten!
152
+
153
+ self.group_values += args
154
+ self
155
+ end
156
+
157
+ def order!(*args)
158
+ args.flatten!
159
+
160
+ self.order_clause += OrderClause.new(args)
161
+ self
162
+ end
163
+
164
+ def records
165
+ load_unless_loaded
166
+ @records
167
+ end
168
+
169
+ def initialize_copy(*)
170
+ @values = @values.dup
171
+ reset
172
+ super
173
+ end
174
+
175
+ def values
176
+ @values.dup
177
+ end
178
+
179
+ def reset
180
+ @loaded = nil
181
+ @records = [].freeze
182
+ self
183
+ end
184
+
185
+ def loaded?
186
+ @loaded
187
+ end
188
+
189
+ private
190
+
191
+ def load_unless_loaded
192
+ exec_query unless loaded
193
+ self
194
+ end
195
+
196
+ def spawn
197
+ clone
198
+ end
199
+
200
+ def find_take_with_limit(limit)
201
+ if loaded
202
+ records.take(limit)
203
+ else
204
+ limit(limit).to_a
205
+ end
206
+ end
207
+
208
+ def find_take
209
+ if loaded
210
+ records.first
211
+ else
212
+ limit(1).records.first
213
+ end
214
+ end
215
+
216
+ def exec_query
217
+ @records = klass.find_by_query(
218
+ where_clause: where_clause,
219
+ limit_value: limit_value,
220
+ group_values: group_values,
221
+ order_clause: order_clause
222
+ )
223
+ @loaded = true
224
+ end
225
+
226
+ def assert_mutability!
227
+ raise ImmutableRelation if @loaded
228
+ end
229
+
230
+ FROZEN_EMPTY_ARRAY = [].freeze
231
+
232
+ def default_value_for(name)
233
+ case name
234
+ when :where then WhereClause.empty
235
+ when :order then OrderClause.empty
236
+ when *Relation::MULTI_VALUE_METHODS then FROZEN_EMPTY_ARRAY
237
+ when *Relation::SINGLE_VALUE_METHODS then nil
238
+ else
239
+ raise ArgumentError, "unknown relation value #{name.inspect}"
240
+ end
241
+ end
242
+ end
243
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveAny
4
+ VERSION = '0.0.1'
5
+ end
data/lib/active_any.rb ADDED
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'active_support/core_ext'
5
+
6
+ require 'active_any/version'
7
+ require 'active_any/relation'
8
+ require 'active_any/reflection'
9
+ require 'active_any/associations'
10
+ require 'active_any/association_relation'
11
+ require 'active_any/attribute_assignment'
12
+ require 'active_any/finders'
13
+ require 'active_any/core'
14
+ require 'active_any/adapter'
15
+ require 'active_any/adapters/abstract_adapter'
16
+ require 'active_any/adapters/object_adapter'
17
+
18
+ module ActiveAny
19
+ class Base
20
+ include Core
21
+ include Associations
22
+ include AttributeAssignment
23
+ include Finders
24
+ include Reflection
25
+ end
26
+
27
+ class Object < Base
28
+ def self.inherited(child)
29
+ child.abstract_class = false
30
+ end
31
+
32
+ class << self
33
+ attr_accessor :data
34
+
35
+ def adapter
36
+ @adapter ||= ObjectAdapter.new(self)
37
+ end
38
+ end
39
+ end
40
+
41
+ class Hash < Base
42
+ def self.inherited(child)
43
+ child.abstract_class = false
44
+ end
45
+
46
+ class << self
47
+ attr_reader :data
48
+
49
+ def data=(data)
50
+ data.map(&:keys).flatten.each do |method|
51
+ attr_accessor method
52
+ end
53
+
54
+ @data = data.map { |d| new(d) }
55
+ end
56
+
57
+ def adapter
58
+ @adapter ||= ObjectAdapter.new(self)
59
+ end
60
+ end
61
+ end
62
+ end
metadata ADDED
@@ -0,0 +1,251 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_any
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - yuemori
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-07-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.15'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.15'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest-power_assert
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rubocop
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'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-byebug
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: pry-coolline
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: pry-inline
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: pry-state
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ description: A utility for quering interface to any objects like ActiveRecord. This
182
+ gem support for querying, association, enum, and relation.
183
+ email:
184
+ - yuemori@aiming-inc.com
185
+ executables: []
186
+ extensions: []
187
+ extra_rdoc_files: []
188
+ files:
189
+ - ".gitignore"
190
+ - ".rubocop.yml"
191
+ - ".travis.yml"
192
+ - CODE_OF_CONDUCT.md
193
+ - Gemfile
194
+ - Guardfile
195
+ - LICENSE.txt
196
+ - README.md
197
+ - Rakefile
198
+ - active_any.gemspec
199
+ - bin/console
200
+ - bin/setup
201
+ - lib/active_any.rb
202
+ - lib/active_any/adapter.rb
203
+ - lib/active_any/adapters/abstract_adapter.rb
204
+ - lib/active_any/adapters/object_adapter.rb
205
+ - lib/active_any/association_relation.rb
206
+ - lib/active_any/associations.rb
207
+ - lib/active_any/associations/association.rb
208
+ - lib/active_any/associations/association_scope.rb
209
+ - lib/active_any/associations/belongs_to_association.rb
210
+ - lib/active_any/associations/builder/association.rb
211
+ - lib/active_any/associations/builder/belongs_to.rb
212
+ - lib/active_any/associations/builder/has_many.rb
213
+ - lib/active_any/associations/collection_proxy.rb
214
+ - lib/active_any/associations/has_many_association.rb
215
+ - lib/active_any/attribute_assignment.rb
216
+ - lib/active_any/core.rb
217
+ - lib/active_any/finders.rb
218
+ - lib/active_any/reflection.rb
219
+ - lib/active_any/reflection/association_reflection.rb
220
+ - lib/active_any/reflection/belongs_to_reflection.rb
221
+ - lib/active_any/reflection/has_many_reflection.rb
222
+ - lib/active_any/relation.rb
223
+ - lib/active_any/relation/merger.rb
224
+ - lib/active_any/relation/order_clause.rb
225
+ - lib/active_any/relation/where_clause.rb
226
+ - lib/active_any/version.rb
227
+ homepage: https://github.com/yuemori/active_any
228
+ licenses:
229
+ - MIT
230
+ metadata: {}
231
+ post_install_message:
232
+ rdoc_options: []
233
+ require_paths:
234
+ - lib
235
+ required_ruby_version: !ruby/object:Gem::Requirement
236
+ requirements:
237
+ - - ">="
238
+ - !ruby/object:Gem::Version
239
+ version: '0'
240
+ required_rubygems_version: !ruby/object:Gem::Requirement
241
+ requirements:
242
+ - - ">="
243
+ - !ruby/object:Gem::Version
244
+ version: '0'
245
+ requirements: []
246
+ rubyforge_project:
247
+ rubygems_version: 2.6.11
248
+ signing_key:
249
+ specification_version: 4
250
+ summary: A utility for quering interface to any objects like ActiveRecord.
251
+ test_files: []