datasource 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 714357b54441eac8f8eb1c209dad82fa8c588743
4
- data.tar.gz: 90cb1f1ca000d6683b234c6ccff41425b208be2c
3
+ metadata.gz: 2a9fb1c2535e9067063259742826afd3e588a6ed
4
+ data.tar.gz: a99f6cf865ea1075a2e26165c58c03483e45e93c
5
5
  SHA512:
6
- metadata.gz: 0414aa6f0f18bdb882d9f54e558ed5301e4c52d77d417cdfd62d51fad0a51f5ebc5191d9ab86a56b6ee69d6c7c489f0c2395c10082b27381e04bfbc70152d3b9
7
- data.tar.gz: 94f30d58cd6cd8cef946e87f039445910dd924638d00c40a95599d35e473e6eb840a14d4543c4dd405b953633257c3defafb33c777b0581dc2cb724bd05fa4d1
6
+ metadata.gz: 6b5a9a5c5a9b4af51e1115a152a58b1b2187ffcf4adaa912e9921824d3fbbf96c12b21df77461347ca0569eb6943542bea1dc50b7bbfa0cc57f583a5017c431d
7
+ data.tar.gz: 5742b0fe11b8bd4a61accb93ca762b4c42cdd4a95cc7044d76b1d7ee124ccc9df9ed3911b36ac8861ac57343c1757557eaa7ddc3ce03af036287e3c578ce58f8
@@ -20,18 +20,20 @@ module Datasource
20
20
  self
21
21
  end
22
22
 
23
- def to_a
23
+ private
24
+ def exec_queries
24
25
  if @datasource
25
26
  datasource = @datasource.new(self)
26
27
  datasource.select(*Array(@datasource_select))
27
28
  if @datasource_serializer
28
29
  select = []
29
- Datasource::Base.consumer_adapter.to_datasource_select(select, @datasource.orm_klass, @datasource_serializer)
30
+ Datasource::Base.consumer_adapter.to_datasource_select(select, @datasource.orm_klass, @datasource_serializer, nil, datasource.adapter)
30
31
 
31
32
  datasource.select(*select)
32
33
  end
33
34
 
34
- datasource.results
35
+ @loaded = true
36
+ @records = datasource.results
35
37
  else
36
38
  super
37
39
  end
@@ -74,7 +76,8 @@ module Datasource
74
76
  end
75
77
  end
76
78
 
77
- def self.association_reflection(klass, name)
79
+ module_function
80
+ def association_reflection(klass, name)
78
81
  if reflection = klass.reflections[name]
79
82
  {
80
83
  klass: reflection.klass,
@@ -84,19 +87,23 @@ module Datasource
84
87
  end
85
88
  end
86
89
 
87
- def self.get_table_name(klass)
90
+ def get_table_name(klass)
88
91
  klass.table_name.to_sym
89
92
  end
90
93
 
91
- def self.is_scope?(obj)
94
+ def is_scope?(obj)
92
95
  obj.kind_of?(::ActiveRecord::Relation)
93
96
  end
94
97
 
95
- def self.scope_to_class(scope)
98
+ def scope_to_class(scope)
96
99
  scope.klass
97
100
  end
98
101
 
99
- def self.association_klass(reflection)
102
+ def scope_loaded?(scope)
103
+ scope.loaded?
104
+ end
105
+
106
+ def association_klass(reflection)
100
107
  if reflection.macro == :belongs_to && reflection.options[:polymorphic]
101
108
  fail Datasource::Error, "polymorphic belongs_to not supported, write custom loader"
102
109
  else
@@ -104,7 +111,7 @@ module Datasource
104
111
  end
105
112
  end
106
113
 
107
- def self.preload_association(records, name)
114
+ def preload_association(records, name)
108
115
  return if records.empty?
109
116
  return if records.first.association(name.to_sym).loaded?
110
117
  klass = records.first.class
@@ -144,43 +151,43 @@ module Datasource
144
151
  end
145
152
  end
146
153
 
147
- def to_query
154
+ def to_query(ds)
148
155
  ::ActiveRecord::Base.uncached do
149
- @scope.select(*get_select_values).to_sql
156
+ ds.scope.select(*ds.get_select_values).to_sql
150
157
  end
151
158
  end
152
159
 
153
- def select_scope
154
- @scope.select(*get_select_values)
160
+ def select_scope(ds)
161
+ ds.scope.select(*ds.get_select_values)
155
162
  end
156
163
 
157
- def get_rows
164
+ def get_rows(ds)
158
165
  append_select = []
159
- @expose_associations.each_pair do |assoc_name, assoc_select|
160
- if reflection = Adapters::ActiveRecord.association_reflection(self.class.orm_klass, assoc_name.to_sym)
166
+ ds.expose_associations.each_pair do |assoc_name, assoc_select|
167
+ if reflection = Adapters::ActiveRecord.association_reflection(ds.class.orm_klass, assoc_name.to_sym)
161
168
  Datasource::Base.reflection_select(reflection, append_select, [])
162
169
  end
163
170
  end
164
- select(*append_select)
171
+ ds.select(*append_select)
165
172
 
166
- scope = select_scope
173
+ scope = select_scope(ds)
167
174
  if scope.respond_to?(:use_datasource)
168
175
  scope = scope.spawn.use_datasource(nil)
169
176
  end
170
177
  scope.includes_values = []
171
178
  scope.to_a.tap do |records|
172
- @expose_associations.each_pair do |assoc_name, assoc_select|
179
+ ds.expose_associations.each_pair do |assoc_name, assoc_select|
173
180
  Adapters::ActiveRecord.preload_association(records, assoc_name)
174
181
  end
175
182
  end
176
183
  end
177
184
 
178
- def primary_scope_table(scope)
179
- scope.klass.table_name
185
+ def primary_scope_table(ds)
186
+ ds.scope.klass.table_name
180
187
  end
181
188
 
182
- def ensure_table_join!(name, att)
183
- join_value = @scope.joins_values.find do |value|
189
+ def ensure_table_join!(ds, name, att)
190
+ join_value = ds.scope.joins_values.find do |value|
184
191
  if value.is_a?(Symbol)
185
192
  value.to_s == att[:name]
186
193
  elsif value.is_a?(String)
@@ -203,6 +210,10 @@ module Datasource
203
210
  klass
204
211
  end
205
212
 
213
+ define_singleton_method(:default_adapter) do
214
+ Datasource::Adapters::ActiveRecord
215
+ end
216
+
206
217
  define_method(:primary_key) do
207
218
  klass.primary_key.to_sym
208
219
  end
@@ -25,7 +25,7 @@ module Datasource
25
25
  datasource.select(*Array(@datasource_select))
26
26
  if @datasource_serializer
27
27
  select = []
28
- Datasource::Base.consumer_adapter.to_datasource_select(select, @datasource.orm_klass, @datasource_serializer)
28
+ Datasource::Base.consumer_adapter.to_datasource_select(select, @datasource.orm_klass, @datasource_serializer, nil, datasource.adapter)
29
29
 
30
30
  datasource.select(*select)
31
31
  end
@@ -75,7 +75,8 @@ module Datasource
75
75
  end
76
76
  end
77
77
 
78
- def self.association_reflection(klass, name)
78
+ module_function
79
+ def association_reflection(klass, name)
79
80
  reflection = klass.association_reflections[name]
80
81
 
81
82
  macro = case reflection[:type]
@@ -92,15 +93,15 @@ module Datasource
92
93
  }
93
94
  end
94
95
 
95
- def self.get_table_name(klass)
96
+ def get_table_name(klass)
96
97
  klass.table_name
97
98
  end
98
99
 
99
- def self.is_scope?(obj)
100
+ def is_scope?(obj)
100
101
  obj.kind_of?(::Sequel::Dataset)
101
102
  end
102
103
 
103
- def self.scope_to_class(scope)
104
+ def scope_to_class(scope)
104
105
  if scope.row_proc && scope.row_proc.ancestors.include?(::Sequel::Model)
105
106
  scope.row_proc
106
107
  else
@@ -108,29 +109,8 @@ module Datasource
108
109
  end
109
110
  end
110
111
 
111
- def to_query(scope)
112
- scope.sql
113
- end
114
-
115
- def select_scope
116
- @scope.select(*get_sequel_select_values)
117
- end
118
-
119
- def get_rows
120
- eager = {}
121
- append_select = []
122
- @expose_associations.each_pair do |assoc_name, assoc_select|
123
- eager.merge!(
124
- get_assoc_eager_options(self.class.orm_klass, assoc_name.to_sym, assoc_select, append_select))
125
- end
126
- # TODO: remove/disable datasource on scope if present
127
- scope = select_scope
128
- if scope.respond_to?(:use_datasource)
129
- scope = scope.clone.use_datasource(nil)
130
- end
131
- scope
132
- .select_append(*get_sequel_select_values(append_select.map { |v| primary_scope_table(@scope) + ".#{v}" }))
133
- .eager(eager).all
112
+ def scope_loaded?(scope)
113
+ false
134
114
  end
135
115
 
136
116
  def get_assoc_eager_options(klass, name, assoc_select, append_select)
@@ -153,15 +133,40 @@ module Datasource
153
133
  end
154
134
 
155
135
  def get_sequel_select_values(values = nil)
156
- (values || get_select_values).map { |str| ::Sequel.lit(str) }
136
+ values.map { |str| ::Sequel.lit(str) }
137
+ end
138
+
139
+ def to_query(ds)
140
+ ds.scope.sql
157
141
  end
158
142
 
159
- def primary_scope_table(scope)
160
- scope.first_source_alias.to_s
143
+ def select_scope(ds)
144
+ ds.scope.select(*get_sequel_select_values(ds.get_select_values))
161
145
  end
162
146
 
163
- def ensure_table_join!(name, att)
164
- join_value = Hash(@scope.opts[:join]).find do |value|
147
+ def get_rows(ds)
148
+ eager = {}
149
+ append_select = []
150
+ ds.expose_associations.each_pair do |assoc_name, assoc_select|
151
+ eager.merge!(
152
+ get_assoc_eager_options(ds.class.orm_klass, assoc_name.to_sym, assoc_select, append_select))
153
+ end
154
+ # TODO: remove/disable datasource on scope if present
155
+ scope = select_scope(ds)
156
+ if scope.respond_to?(:use_datasource)
157
+ scope = scope.clone.use_datasource(nil)
158
+ end
159
+ scope
160
+ .select_append(*get_sequel_select_values(append_select.map { |v| primary_scope_table(ds) + ".#{v}" }))
161
+ .eager(eager).all
162
+ end
163
+
164
+ def primary_scope_table(ds)
165
+ ds.scope.first_source_alias.to_s
166
+ end
167
+
168
+ def ensure_table_join!(ds, name, att)
169
+ join_value = Hash(ds.scope.opts[:join]).find do |value|
165
170
  (value.table_alias || value.table).to_s == att[:name]
166
171
  end
167
172
  fail Datasource::Error, "given scope does not join on #{name}, but it is required by #{att[:name]}" unless join_value
@@ -178,6 +183,10 @@ module Datasource
178
183
  klass
179
184
  end
180
185
 
186
+ define_singleton_method(:default_adapter) do
187
+ Datasource::Adapters::Sequel
188
+ end
189
+
181
190
  define_method(:primary_key) do
182
191
  klass.primary_key
183
192
  end
@@ -8,10 +8,9 @@ module Datasource
8
8
  base._attributes = (_attributes || {}).dup
9
9
  base._associations = (_associations || {}).dup
10
10
  base._loaders = (_loaders || {}).dup
11
- self.send :include, adapter
12
11
  end
13
12
 
14
- def adapter
13
+ def default_adapter
15
14
  @adapter ||= begin
16
15
  Datasource::Adapters.const_get(Datasource::Adapters.constants.first)
17
16
  end
@@ -68,7 +67,10 @@ module Datasource
68
67
  end
69
68
  end
70
69
 
71
- def initialize(scope)
70
+ attr_reader :scope, :expose_attributes, :expose_associations, :adapter
71
+
72
+ def initialize(scope, adapter = nil)
73
+ @adapter = adapter || self.class.default_adapter
72
74
  @scope =
73
75
  if self.class._update_scope
74
76
  self.class._update_scope.call(scope)
@@ -115,7 +117,7 @@ module Datasource
115
117
  end
116
118
 
117
119
  def get_select_values
118
- scope_table = primary_scope_table(@scope)
120
+ scope_table = adapter.primary_scope_table(self)
119
121
  select_values = Set.new
120
122
  select_values.add("#{scope_table}.#{primary_key}")
121
123
 
@@ -127,7 +129,7 @@ module Datasource
127
129
  att[:klass]._depends.keys.map(&:to_s).each do |name|
128
130
  next if name == scope_table
129
131
  next if name == "loaders"
130
- ensure_table_join!(name, att)
132
+ adapter.ensure_table_join!(self, name, att)
131
133
  end
132
134
  att[:klass]._depends.each_pair do |table, names|
133
135
  next if table.to_sym == :loaders
@@ -140,7 +142,7 @@ module Datasource
140
142
  select_values.add("(#{att[:klass].select_value}) as #{att[:name]}")
141
143
  att[:klass]._depends.each do |name|
142
144
  next if name == scope_table
143
- ensure_table_join!(name, att)
145
+ adapter.ensure_table_join!(self, name, att)
144
146
  end
145
147
  end
146
148
  end
@@ -153,11 +155,11 @@ module Datasource
153
155
  end
154
156
 
155
157
  def results(rows = nil)
156
- rows ||= get_rows
158
+ rows ||= adapter.get_rows(self)
157
159
 
158
160
  @expose_attributes.each do |name|
159
161
  att = self.class._attributes[name]
160
- fail Datasource::Error, "attribute #{name} doesn't exist for #{self.class.orm_klass.name}, did you forget to call \"computed :#{name}, <dependencies>\" in your datasource_module?" unless att
162
+ fail Datasource::Error, "attribute #{name} doesn't exist for #{self.class.orm_klass.name}, did you forget to call \"computed :#{name}, :db_column_dependency\" in your datasource_module? See https://github.com/mrbrdo/datasource#model-methods--virtual-attributes" unless att
161
163
  klass = att[:klass]
162
164
  next unless klass
163
165
 
@@ -3,25 +3,20 @@ require "active_model/serializer"
3
3
  module Datasource
4
4
  module ConsumerAdapters
5
5
  module ActiveModelSerializers
6
- superclass = if defined?(ActiveModel::Serializer::ArraySerializer)
7
- ActiveModel::Serializer::ArraySerializer
8
- else
9
- ActiveModel::ArraySerializer
10
- end
11
- class ArraySerializer < superclass
12
- def initialize(objects, options = {})
6
+ module ArraySerializer
7
+ def initialize_with_datasource(objects, options = {})
13
8
  datasource_class = options.delete(:datasource)
14
- adapter = Datasource::Base.adapter
15
- if adapter.is_scope?(objects)
9
+ adapter = Datasource.orm_adapters.find { |a| a.is_scope?(objects) }
10
+ if adapter && !adapter.scope_loaded?(objects)
16
11
  datasource_class ||= adapter.scope_to_class(objects).default_datasource
17
12
 
18
13
  records = objects
19
14
  .with_datasource(datasource_class)
20
15
  .for_serializer(options[:serializer]).all.to_a # all needed for Sequel eager loading
21
16
 
22
- super(records, options)
17
+ initialize_without_datasource(records, options)
23
18
  else
24
- super
19
+ initialize_without_datasource(objects, options)
25
20
  end
26
21
  end
27
22
  end
@@ -38,7 +33,8 @@ module Datasource
38
33
  serializer || "#{klass.name}Serializer".constantize
39
34
  end
40
35
 
41
- def to_datasource_select(result, klass, serializer = nil, serializer_assoc = nil)
36
+ def to_datasource_select(result, klass, serializer = nil, serializer_assoc = nil, adapter = nil)
37
+ adapter ||= Datasource::Base.default_adapter
42
38
  serializer ||= get_serializer_for(klass, serializer_assoc)
43
39
  result.concat(serializer._attributes)
44
40
  result_assocs = {}
@@ -46,12 +42,12 @@ module Datasource
46
42
 
47
43
  serializer._associations.each_pair do |name, serializer_assoc|
48
44
  # TODO: what if assoc is renamed in serializer?
49
- reflection = Datasource::Base.adapter.association_reflection(klass, name.to_sym)
45
+ reflection = adapter.association_reflection(klass, name.to_sym)
50
46
  assoc_class = reflection[:klass]
51
47
 
52
48
  name = name.to_s
53
49
  result_assocs[name] = []
54
- to_datasource_select(result_assocs[name], assoc_class, nil, serializer_assoc)
50
+ to_datasource_select(result_assocs[name], assoc_class, nil, serializer_assoc, adapter)
55
51
  end
56
52
  rescue Exception => ex
57
53
  if ex.is_a?(SystemStackError) || ex.is_a?(Datasource::RecursionError)
@@ -62,5 +58,18 @@ module Datasource
62
58
  end
63
59
  end
64
60
  end
65
- ArrayAMS = ConsumerAdapters::ActiveModelSerializers::ArraySerializer
61
+ end
62
+
63
+ array_serializer_class = if defined?(ActiveModel::Serializer::ArraySerializer)
64
+ ActiveModel::Serializer::ArraySerializer
65
+ else
66
+ ActiveModel::ArraySerializer
67
+ end
68
+
69
+ array_serializer_class.class_exec do
70
+ alias_method :initialize_without_datasource, :initialize
71
+ include Datasource::ConsumerAdapters::ActiveModelSerializers::ArraySerializer
72
+ def initialize(*args)
73
+ initialize_with_datasource(*args)
74
+ end
66
75
  end
data/lib/datasource.rb CHANGED
@@ -2,18 +2,39 @@ module Datasource
2
2
  Error = Class.new(StandardError)
3
3
  RecursionError = Class.new(StandardError)
4
4
 
5
- def self.load(adapter = nil)
6
- unless adapter
7
- adapter = if defined? ActiveRecord
8
- :activerecord
5
+ AdapterPaths = {
6
+ activerecord: 'datasource/adapters/active_record',
7
+ active_record: :activerecord,
8
+ sequel: 'datasource/adapters/sequel',
9
+ ams: 'datasource/consumer_adapters/active_model_serializers',
10
+ active_model_serializers: :ams
11
+ }
12
+
13
+ module_function
14
+ def load(*adapters)
15
+ if adapters.empty?
16
+ adapters = []
17
+ if defined? ActiveRecord
18
+ adapters.push(:activerecord)
9
19
  elsif defined? Sequel
10
- :sequel
20
+ adapters.push(:sequel)
21
+ end
22
+ if defined? ActiveModel::Serializer
23
+ adapters.push(:ams)
11
24
  end
12
25
  end
13
26
 
14
- require 'datasource/adapters/active_record' if [:activerecord, :active_record].include?(adapter)
15
- require 'datasource/adapters/sequel' if adapter == :sequel
16
- require 'datasource/consumer_adapters/active_model_serializers' if defined? ActiveModel::Serializer
27
+ adapters.each do |adapter|
28
+ adapter = AdapterPaths[adapter]
29
+ adapter = AdapterPaths[adapter] if adapter.is_a?(Symbol)
30
+ require adapter
31
+ end
32
+ end
33
+
34
+ def orm_adapters
35
+ @orm_adapters ||= begin
36
+ Datasource::Adapters.constants.map { |name| Datasource::Adapters.const_get(name) }
37
+ end
17
38
  end
18
39
  end
19
40
 
@@ -1,11 +1 @@
1
- Datasource.load(:activerecord)
2
-
3
- if defined? ActiveModel::Serializer
4
- if ActiveModel::Serializer.respond_to?(:config)
5
- ActiveModel::Serializer.config.array_serializer = Datasource::ArrayAMS
6
- else
7
- ActiveModel::Serializer.setup do |config|
8
- config.array_serializer = Datasource::ArrayAMS
9
- end
10
- end
11
- end
1
+ Datasource.load(:activerecord, :active_model_serializers)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datasource
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Berdajs
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-09 00:00:00.000000000 Z
11
+ date: 2014-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: activerecord
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +94,34 @@ dependencies:
66
94
  - - "~>"
67
95
  - !ruby/object:Gem::Version
68
96
  version: '4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sequel
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '4.17'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '4.17'
111
+ - !ruby/object:Gem::Dependency
112
+ name: database_cleaner
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '1.3'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '1.3'
69
125
  description:
70
126
  email:
71
127
  - mrbrdo@gmail.com
@@ -87,12 +143,6 @@ files:
87
143
  - lib/datasource/serializer.rb
88
144
  - lib/generators/datasource/install_generator.rb
89
145
  - lib/generators/datasource/templates/initializer.rb
90
- - test/active_record_helper.rb
91
- - test/schema.rb
92
- - test/test_helper.rb
93
- - test/test_loader.rb
94
- - test/test_scope.rb
95
- - test/test_serializer.rb
96
146
  homepage: https://github.com/mrbrdo/datasource
97
147
  licenses:
98
148
  - MIT
@@ -116,12 +166,5 @@ rubyforge_project:
116
166
  rubygems_version: 2.2.2
117
167
  signing_key:
118
168
  specification_version: 4
119
- summary: Ruby library for creating data source objects from database data
120
- test_files:
121
- - test/active_record_helper.rb
122
- - test/schema.rb
123
- - test/test_helper.rb
124
- - test/test_loader.rb
125
- - test/test_scope.rb
126
- - test/test_serializer.rb
127
- has_rdoc:
169
+ summary: Ruby library to automatically preload records for your serializers
170
+ test_files: []
@@ -1,23 +0,0 @@
1
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
2
- ActiveRecord::Migration.verbose = false
3
- load "schema.rb"
4
-
5
- def clean_db
6
- ActiveRecord::Base.connection.execute("DELETE FROM comments")
7
- ActiveRecord::Base.connection.execute("DELETE FROM posts")
8
- ActiveRecord::Base.connection.execute("DELETE FROM blogs")
9
- ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence")
10
- end
11
-
12
- def assert_query_count(count)
13
- old_logger = ActiveRecord::Base.logger
14
- logger = StringIO.new
15
- ActiveRecord::Base.logger = Logger.new(logger)
16
- begin
17
- yield
18
- ensure
19
- ActiveRecord::Base.logger = old_logger
20
- # puts logger.string
21
- end
22
- assert_equal count, logger.string.lines.count
23
- end
data/test/schema.rb DELETED
@@ -1,19 +0,0 @@
1
- ActiveRecord::Schema.define(:version => 0) do
2
- create_table :blogs, :force => true do |t|
3
- t.string :title
4
- end
5
-
6
- create_table :posts, :force => true do |t|
7
- t.integer :blog_id
8
- t.string :title
9
- t.string :author_first_name
10
- t.string :author_last_name
11
- end
12
-
13
- create_table :comments, :force => true do |t|
14
- t.integer :post_id
15
- t.text :comment
16
- end
17
- end
18
-
19
- ActiveRecord::Base.send :include, Datasource::Adapters::ActiveRecord::Model
data/test/test_helper.rb DELETED
@@ -1,14 +0,0 @@
1
- # Configure Rails Environment
2
- ENV["RAILS_ENV"] = "test"
3
-
4
- require 'minitest/autorun'
5
- require 'active_support/all'
6
- require 'active_record'
7
- require 'datasource'
8
- require 'active_model_serializers'
9
- require 'pry'
10
-
11
- Datasource.load(:activerecord)
12
-
13
- # Load support files
14
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
data/test/test_loader.rb DELETED
@@ -1,79 +0,0 @@
1
- require 'test_helper'
2
- require 'active_record_helper'
3
-
4
- class LoaderTest < ActiveSupport::TestCase
5
- class Comment < ActiveRecord::Base
6
- self.table_name = "comments"
7
- belongs_to :post
8
- end
9
-
10
- class Post < ActiveRecord::Base
11
- self.table_name = "posts"
12
- has_many :comments
13
-
14
- datasource_module do
15
- loader :newest_comment, group_by: :post_id, one: true do |post_ids|
16
- Comment.for_serializer.where(post_id: post_ids)
17
- .group("post_id")
18
- .having("id = MAX(id)")
19
- .datasource_select(:post_id)
20
- end
21
-
22
- loader :newest_comment_text, array_to_hash: true do |post_ids|
23
- Comment.where(post_id: post_ids)
24
- .group("post_id")
25
- .having("id = MAX(id)")
26
- .pluck("post_id, comment")
27
- end
28
-
29
- loader :ordered_comments, group_by: :post_id do |post_ids|
30
- Comment.for_serializer(CommentSerializer).where(post_id: post_ids)
31
- .order("post_id, id desc")
32
- .datasource_select(:post_id)
33
- end
34
-
35
- computed :newest_comment, loaders: :newest_comment
36
- computed :newest_comment_text, loaders: :newest_comment_text
37
- computed :ordered_comments, loaders: :ordered_comments
38
- end
39
-
40
- def name_initials
41
- return unless author_first_name && author_last_name
42
- author_first_name[0].upcase + author_last_name[0].upcase
43
- end
44
- end
45
-
46
- class CommentSerializer < ActiveModel::Serializer
47
- attributes :id, :comment
48
- end
49
-
50
- class PostSerializer < ActiveModel::Serializer
51
- attributes :id, :title, :newest_comment, :newest_comment_text, :ordered_comments
52
-
53
- def newest_comment
54
- CommentSerializer.new(object.loaded_values[:newest_comment]).as_json
55
- end
56
-
57
- def newest_comment_text
58
- object.loaded_values[:newest_comment_text]
59
- end
60
-
61
- def ordered_comments
62
- Datasource::ArrayAMS.new(object.loaded_values[:ordered_comments]).as_json
63
- end
64
- end
65
-
66
- def test_loader
67
- post = Post.create! title: "First Post"
68
- 2.times { |i| post.comments.create! comment: "Comment #{i+1}" }
69
-
70
- assert_query_count(4) do
71
- assert_equal Datasource::ArrayAMS.new(Post.all).as_json,
72
- [{:id=>1, :title=>"First Post", :newest_comment=>{"comment"=>{:id=>2, :comment=>"Comment 2"}}, :newest_comment_text=>"Comment 2", :ordered_comments=>[{:id=>2, :comment=>"Comment 2"}, {:id=>1, :comment=>"Comment 1"}]}]
73
- end
74
- end
75
-
76
- def teardown
77
- clean_db
78
- end
79
- end
data/test/test_scope.rb DELETED
@@ -1,50 +0,0 @@
1
- require 'test_helper'
2
- require 'active_record_helper'
3
-
4
- class ScopeTest < ActiveSupport::TestCase
5
- class Post < ActiveRecord::Base
6
- belongs_to :blog
7
-
8
- datasource_module do
9
- query :author_name do
10
- "posts.author_first_name || ' ' || posts.author_last_name"
11
- end
12
- end
13
- end
14
-
15
- class PostSerializer < ActiveModel::Serializer
16
- attributes :id, :title, :author_name
17
- end
18
-
19
- def test_first
20
- Post.create! title: "The Post", author_first_name: "John", author_last_name: "Doe", blog_id: 10
21
- post = Post.for_serializer.first
22
-
23
- assert_equal("The Post", post.title)
24
- assert_equal("John Doe", post.author_name)
25
- assert_raises(ActiveModel::MissingAttributeError) { post.blog_id }
26
- end
27
-
28
- def test_find
29
- post = Post.create! title: "The Post", author_first_name: "John", author_last_name: "Doe", blog_id: 10
30
- post = Post.for_serializer.find(post.id)
31
-
32
- assert_equal("The Post", post.title)
33
- assert_equal("John Doe", post.author_name)
34
- assert_raises(ActiveModel::MissingAttributeError) { post.blog_id }
35
- end
36
-
37
- def test_each
38
- post = Post.create! title: "The Post", author_first_name: "John", author_last_name: "Doe", blog_id: 10
39
-
40
- Post.for_serializer.each do |post|
41
- assert_equal("The Post", post.title)
42
- assert_equal("John Doe", post.author_name)
43
- assert_raises(ActiveModel::MissingAttributeError) { post.blog_id }
44
- end
45
- end
46
-
47
- def teardown
48
- clean_db
49
- end
50
- end
@@ -1,52 +0,0 @@
1
- require 'test_helper'
2
- require 'active_record_helper'
3
-
4
- class SerializerTest < ActiveSupport::TestCase
5
- class Post < ActiveRecord::Base
6
- belongs_to :blog
7
-
8
- datasource_module do
9
- query :author_name do
10
- "posts.author_first_name || ' ' || posts.author_last_name"
11
- end
12
- end
13
- end
14
-
15
- class Blog < ActiveRecord::Base
16
- has_many :posts
17
- end
18
-
19
- class BlogSerializer < ActiveModel::Serializer
20
- attributes :id, :title
21
-
22
- has_many :posts
23
- end
24
-
25
- class PostSerializer < ActiveModel::Serializer
26
- attributes :id, :title, :author_name
27
- end
28
-
29
- def test_blogs_and_posts_serializer
30
- blog = Blog.create! title: "Blog 1"
31
- blog.posts.create! title: "Post 1", author_first_name: "John", author_last_name: "Doe"
32
- blog.posts.create! title: "Post 2", author_first_name: "Maria", author_last_name: "Doe"
33
- blog = Blog.create! title: "Blog 2"
34
-
35
- expected_result = [
36
- {:id =>1, :title =>"Blog 1", :posts =>[
37
- {:id =>1, :title =>"Post 1", :author_name =>"John Doe"},
38
- {:id =>2, :title =>"Post 2", :author_name =>"Maria Doe"}
39
- ]},
40
- {:id =>2, :title =>"Blog 2", :posts =>[]}
41
- ]
42
-
43
- assert_query_count(2) do
44
- serializer = Datasource::ArrayAMS.new(Blog.all)
45
- assert_equal(expected_result, serializer.as_json)
46
- end
47
- end
48
-
49
- def teardown
50
- clean_db
51
- end
52
- end