any_query 0.1.1
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 +7 -0
- data/lib/any_query/adapters/base.rb +173 -0
- data/lib/any_query/adapters/csv.rb +61 -0
- data/lib/any_query/adapters/fixed_length.rb +71 -0
- data/lib/any_query/adapters/http.rb +213 -0
- data/lib/any_query/adapters/sql.rb +100 -0
- data/lib/any_query/adapters.rb +13 -0
- data/lib/any_query/config.rb +12 -0
- data/lib/any_query/field.rb +7 -0
- data/lib/any_query/query.rb +70 -0
- data/lib/any_query/version.rb +5 -0
- data/lib/any_query.rb +58 -0
- data/spec/any_query/csv_spec.rb +44 -0
- data/spec/any_query/fixed_length_spec.rb +47 -0
- data/spec/any_query/http_spec.rb +161 -0
- data/spec/any_query/sql_spec.rb +58 -0
- data/spec/fixtures/sample.csv +3 -0
- data/spec/fixtures/sample.txt +2 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/schema.rb +146 -0
- metadata +137 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyQuery
|
4
|
+
# @api private
|
5
|
+
class Query
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
delegate_missing_to :to_a
|
9
|
+
|
10
|
+
def initialize(model, adapter)
|
11
|
+
@model = model
|
12
|
+
@adapter = adapter
|
13
|
+
end
|
14
|
+
|
15
|
+
def joins(model, primary_key, foreign_key, into:, as: :single, strategy: :default)
|
16
|
+
dup.joins!(model, primary_key, foreign_key, into:, as:, strategy:)
|
17
|
+
end
|
18
|
+
|
19
|
+
def with_single
|
20
|
+
dup.joins!(:show, :id, :id, into: :single, as: :single, strategy: :single)
|
21
|
+
end
|
22
|
+
|
23
|
+
def where(options)
|
24
|
+
dup.where!(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def select(*args)
|
28
|
+
dup.select!(*args)
|
29
|
+
end
|
30
|
+
|
31
|
+
def limit(limit)
|
32
|
+
dup.limit!(limit)
|
33
|
+
end
|
34
|
+
|
35
|
+
def find(id)
|
36
|
+
@adapter.load_single(@model, id, [])
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_a
|
40
|
+
@adapter.load(@model, select: @select, joins: @joins, where: @where, limit: @limit)
|
41
|
+
end
|
42
|
+
|
43
|
+
def each(&block)
|
44
|
+
to_a.each(&block)
|
45
|
+
end
|
46
|
+
|
47
|
+
def joins!(model, primary_key, foreign_key, into:, as: :single, strategy: :default)
|
48
|
+
@joins ||= []
|
49
|
+
@joins << ({ model:, primary_key:, foreign_key:, into:, as:, strategy: })
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
def select!(*args)
|
54
|
+
@select ||= []
|
55
|
+
@select += args
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def where!(options)
|
60
|
+
@where ||= []
|
61
|
+
@where << options
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def limit!(limit)
|
66
|
+
@limit = limit
|
67
|
+
self
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/any_query.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
require 'active_support/all'
|
5
|
+
require 'active_record'
|
6
|
+
require 'active_model'
|
7
|
+
|
8
|
+
# AnyQuery is a library to help you build queries for different data sources
|
9
|
+
module AnyQuery
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
extend ActiveSupport::Autoload
|
12
|
+
|
13
|
+
autoload :Config
|
14
|
+
autoload :Adapters
|
15
|
+
autoload :Query
|
16
|
+
|
17
|
+
included do
|
18
|
+
delegate_missing_to :@attributes
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@attributes = OpenStruct.new
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
def adapter(name, &block)
|
27
|
+
config = "AnyQuery::Adapters::#{name.to_s.classify}::Config".constantize.new(&block)
|
28
|
+
@adapter = "AnyQuery::Adapters::#{name.to_s.classify}".constantize.new(config)
|
29
|
+
end
|
30
|
+
|
31
|
+
delegate_missing_to :all
|
32
|
+
|
33
|
+
# @return [AnyQuery::Adapters::Base]
|
34
|
+
def _adapter
|
35
|
+
@adapter
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param [Symbol] name
|
39
|
+
# @param [Hash] options
|
40
|
+
# @option options [Symbol] :type
|
41
|
+
# @option options [String] :format
|
42
|
+
# @option options [Integer] :length
|
43
|
+
# @option options [Proc] :transform
|
44
|
+
def field(name, options = {})
|
45
|
+
fields[name] = options
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Hash]
|
49
|
+
def fields
|
50
|
+
@fields ||= {}
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [AnyQuery::Query]
|
54
|
+
def all
|
55
|
+
Query.new(self, @adapter)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe ArticleCSV do
|
6
|
+
it 'returns records' do
|
7
|
+
expect(described_class.all.to_a).to have(2).items
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'can be finded' do
|
11
|
+
result = described_class.find(2)
|
12
|
+
expect(result.id).to eq(2)
|
13
|
+
expect(result.user_id).to eq(1)
|
14
|
+
expect(result.title).to eq('the article 2')
|
15
|
+
expect(result.body).to eq('this is the body of your article 2')
|
16
|
+
expect(result.status).to eq(2)
|
17
|
+
expect(result.created_at).to eq('2023-03-10T18:28:02Z'.to_datetime)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'can be filtered' do
|
21
|
+
expect(described_class.where(status: 1).to_a).to have(1).items
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'can be limited' do
|
25
|
+
expect(described_class.limit(1).to_a).to have(1).items
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'can be joined' do
|
29
|
+
expect do
|
30
|
+
described_class.joins(UserSQL, :id, :user_id, into: :user).to_a.first
|
31
|
+
end.to match_query(/SELECT "users".* FROM "users"/)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'can be selected with nested selectors' do
|
35
|
+
results = described_class
|
36
|
+
.joins(UserSQL, :id, :user_id, into: :user, as: :single)
|
37
|
+
.select(:id, :title, %i[user email])
|
38
|
+
.to_a
|
39
|
+
|
40
|
+
expect(results).to eq(
|
41
|
+
[[1, 'the article', 'test@test.com'], [2, 'the article 2', 'test@test.com']]
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe ArticleFL do
|
6
|
+
it 'returns records' do
|
7
|
+
expect(described_class.all.to_a).to have(2).items
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'can be finded' do
|
11
|
+
result = described_class.find(2)
|
12
|
+
expect(result.id).to eq(2)
|
13
|
+
expect(result.user_id).to eq(1)
|
14
|
+
expect(result.title).to eq('this is another sample')
|
15
|
+
expect(result.body).to eq('this is an example of a body for an article that is very long and dirty')
|
16
|
+
expect(result.status).to eq(2)
|
17
|
+
expect(result.created_at).to eq('2023-12-31T19:00:00Z'.to_datetime)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'can be filtered' do
|
21
|
+
expect(described_class.where(status: 1).to_a).to have(1).items
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'can be limited' do
|
25
|
+
expect(described_class.limit(1).to_a).to have(1).items
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'can be joined' do
|
29
|
+
expect do
|
30
|
+
described_class.joins(UserSQL, :id, :user_id, into: :user).to_a.first
|
31
|
+
end.to match_query(/SELECT "users".* FROM "users"/)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'can be selected with nested selectors' do
|
35
|
+
results = described_class
|
36
|
+
.joins(UserSQL, :id, :user_id, into: :user, as: :single)
|
37
|
+
.select(:id, :title, %i[user email])
|
38
|
+
.to_a
|
39
|
+
|
40
|
+
expect(results).to eq(
|
41
|
+
[
|
42
|
+
[1, 'this is a sample', 'test@test.com'],
|
43
|
+
[2, 'this is another sample', 'test@test.com']
|
44
|
+
]
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe ArticleHTTP do
|
6
|
+
before do
|
7
|
+
stub_request(:get, 'http://example.com/articles?page=0&some_query_param=1')
|
8
|
+
.to_return(
|
9
|
+
headers: { content_type: 'application/json' },
|
10
|
+
body: JSON.dump(
|
11
|
+
{
|
12
|
+
items: [
|
13
|
+
{
|
14
|
+
id: 1,
|
15
|
+
user_id: 1,
|
16
|
+
name: 'some article'
|
17
|
+
},
|
18
|
+
{
|
19
|
+
id: 2,
|
20
|
+
user_id: 1,
|
21
|
+
name: 'some article 2'
|
22
|
+
}
|
23
|
+
]
|
24
|
+
}
|
25
|
+
)
|
26
|
+
)
|
27
|
+
|
28
|
+
stub_request(:get, 'http://example.com/articles?page=1&some_query_param=1')
|
29
|
+
.to_return(
|
30
|
+
headers: { content_type: 'application/json' },
|
31
|
+
body: '{ "items": [] }'
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns records' do
|
36
|
+
expect(described_class.all.to_a).to have(2).items
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'can be finded' do
|
40
|
+
stub_request(:get, 'http://example.com/articles/1')
|
41
|
+
.to_return(
|
42
|
+
headers: { content_type: 'application/json' },
|
43
|
+
body: JSON.dump(
|
44
|
+
{
|
45
|
+
id: 1,
|
46
|
+
user_id: 1,
|
47
|
+
title: 'some article'
|
48
|
+
}
|
49
|
+
)
|
50
|
+
)
|
51
|
+
result = described_class.find(1)
|
52
|
+
expect(result.id).to eq(1)
|
53
|
+
expect(result.user_id).to eq(1)
|
54
|
+
expect(result.title).to eq('some article')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'can be filtered' do
|
58
|
+
stub_request(:get, 'http://example.com/articles?page=0&some_query_param=1&status=1')
|
59
|
+
.to_return(
|
60
|
+
headers: { content_type: 'application/json' },
|
61
|
+
body: JSON.dump(
|
62
|
+
{
|
63
|
+
items: [
|
64
|
+
{
|
65
|
+
id: 1,
|
66
|
+
name: 'some article'
|
67
|
+
}
|
68
|
+
]
|
69
|
+
}
|
70
|
+
)
|
71
|
+
)
|
72
|
+
stub_request(:get, 'http://example.com/articles?page=1&some_query_param=1&status=1')
|
73
|
+
.to_return(
|
74
|
+
headers: { content_type: 'application/json' },
|
75
|
+
body: '{ "items": [] }'
|
76
|
+
)
|
77
|
+
|
78
|
+
expect(described_class.where(status: 1).to_a).to have(1).items
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'can be limited' do
|
82
|
+
expect(described_class.limit(1).to_a).to have(1).items
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'can be joined with SQL' do
|
86
|
+
described_class.joins(UserSQL, :id, :user_id, into: :user).to_a.first
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'can be joined with itself using the show endpoint' do
|
90
|
+
stub_request(:get, 'http://example.com/articles/1')
|
91
|
+
.to_return(
|
92
|
+
headers: { content_type: 'application/json' },
|
93
|
+
body: JSON.dump(
|
94
|
+
{
|
95
|
+
id: 1,
|
96
|
+
user_id: 1,
|
97
|
+
title: 'some article',
|
98
|
+
some_additional_field: 'some value'
|
99
|
+
}
|
100
|
+
)
|
101
|
+
)
|
102
|
+
|
103
|
+
stub_request(:get, 'http://example.com/articles/2')
|
104
|
+
.to_return(
|
105
|
+
headers: { content_type: 'application/json' },
|
106
|
+
body: JSON.dump(
|
107
|
+
{
|
108
|
+
id: 2,
|
109
|
+
user_id: 1,
|
110
|
+
title: 'some article 2',
|
111
|
+
some_additional_field: 'some value'
|
112
|
+
}
|
113
|
+
)
|
114
|
+
)
|
115
|
+
|
116
|
+
result = described_class.with_single.to_a.first
|
117
|
+
expect(result.some_additional_field).to eq('some value')
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'can be joined with HTTP(s)' do
|
121
|
+
stub_request(:get, 'http://example.com/users?id%5B%5D=1&some_query_param=true')
|
122
|
+
.to_return(
|
123
|
+
headers: { content_type: 'application/json' },
|
124
|
+
body: JSON.dump(
|
125
|
+
items: [
|
126
|
+
{ "id": 1, "email": 'gianni@gianni.com' }
|
127
|
+
],
|
128
|
+
cursor: '123123123'
|
129
|
+
)
|
130
|
+
)
|
131
|
+
|
132
|
+
stub_request(:get, 'http://example.com/users?id%5B%5D=1&some_query_param=true&cursor=123123123')
|
133
|
+
.to_return(
|
134
|
+
headers: { content_type: 'application/json' },
|
135
|
+
body: JSON.dump(
|
136
|
+
items: [],
|
137
|
+
cursor: '123123123'
|
138
|
+
)
|
139
|
+
)
|
140
|
+
|
141
|
+
result = described_class.joins(UserHTTP, :id, :user_id, into: :user).to_a.first
|
142
|
+
expect(result.user.email).to eq('gianni@gianni.com')
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'can be selected with nested selectors' do
|
146
|
+
results = described_class
|
147
|
+
.joins(UserSQL, :id, :user_id, into: :user, as: :single)
|
148
|
+
.select(:id, :title, %i[user email])
|
149
|
+
.to_a
|
150
|
+
|
151
|
+
expect(results).to have(2).items
|
152
|
+
expect(results[0]).to have(3).items
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'with url params' do
|
156
|
+
it 'can be filtered using query params' do
|
157
|
+
stub_request(:get, 'http://example.com/1/users')
|
158
|
+
ScopedUserHTTP.where(company_id: 1).to_a
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe ArticleSQL do
|
6
|
+
before do
|
7
|
+
ActiveRecord::Base.connection.execute('INSERT INTO articles VALUES (1, 1, "Title 1", "Body 1", 1, "2021-01-01 00:00:00", "2021-01-01 00:00:00")')
|
8
|
+
ActiveRecord::Base.connection.execute('INSERT INTO articles VALUES (2, 1, "Title 2", "Body 2", 2, "2021-01-01 00:00:00", "2021-01-01 00:00:00")')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns records' do
|
12
|
+
expect(described_class.all.to_a).to have(2).items
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'can be finded' do
|
16
|
+
result = described_class.find(2)
|
17
|
+
expect(result.id).to eq(2)
|
18
|
+
expect(result.user_id).to eq(1)
|
19
|
+
expect(result.title).to eq('Title 2')
|
20
|
+
expect(result.body).to eq('Body 2')
|
21
|
+
expect(result.status).to eq(2)
|
22
|
+
expect(result.created_at).to eq('2021-01-01 00:00:00 UTC'.to_datetime)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'can be filtered' do
|
26
|
+
expect(described_class.where(status: 1).to_a).to have(1).items
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can be limited' do
|
30
|
+
expect(described_class.limit(1).to_a).to have(1).items
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'can be joined' do
|
34
|
+
expect do
|
35
|
+
described_class.joins(UserSQL, :id, :user_id, into: :user).to_a.first
|
36
|
+
end.to match_query(/ LEFT OUTER JOIN "users"/)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'can be joined on many' do
|
40
|
+
ActiveRecord::Base.connection.execute('INSERT INTO comments VALUES (1, 1, "content")')
|
41
|
+
ActiveRecord::Base.connection.execute('INSERT INTO comments VALUES (2, 1, "content2")')
|
42
|
+
|
43
|
+
expect do
|
44
|
+
result = described_class.joins(CommentSQL, :id, :article_id, into: :comments, as: :list).to_a.first
|
45
|
+
expect(result.comments).to have(2).items
|
46
|
+
end.to match_query(/ LEFT OUTER JOIN "comments" ON "comments"/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'can be selected with nested selectors' do
|
50
|
+
results = described_class
|
51
|
+
.joins(UserSQL, :id, :user_id, into: :user, as: :single)
|
52
|
+
.select(:id, :title, %i[user email])
|
53
|
+
.to_a
|
54
|
+
|
55
|
+
expect(results).to have(2).items
|
56
|
+
expect(results[0]).to have(3).items
|
57
|
+
end
|
58
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# require 'rails'
|
2
|
+
# require 'action_controller/railtie'
|
3
|
+
# require 'action_mailer/railtie'
|
4
|
+
# require 'action_view/railtie'
|
5
|
+
# require 'rspec/rails'
|
6
|
+
# require 'cancancan'
|
7
|
+
# require 'active_model_serializers'
|
8
|
+
require 'any_query'
|
9
|
+
require 'rspec/collection_matchers'
|
10
|
+
require 'rspec/sql_matcher'
|
11
|
+
require 'webmock/rspec'
|
12
|
+
|
13
|
+
# I18n.enforce_available_locales = false
|
14
|
+
RSpec::Expectations.configuration.warn_about_potential_false_positives = false
|
15
|
+
|
16
|
+
# Rails.application.config.eager_load = false
|
17
|
+
# Rails.application.config.active_record.legacy_connection_handling = false
|
18
|
+
|
19
|
+
Dir[File.expand_path('support/*.rb', __dir__)].each { |f| require f }
|
20
|
+
|
21
|
+
RSpec.configure do |config|
|
22
|
+
config.before(:suite) do
|
23
|
+
Schema.create
|
24
|
+
end
|
25
|
+
|
26
|
+
config.around(:each) do |example|
|
27
|
+
ActiveRecord::Base.transaction do
|
28
|
+
example.run
|
29
|
+
raise ActiveRecord::Rollback
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
# @example
|
6
|
+
class ArticleSQL
|
7
|
+
include AnyQuery
|
8
|
+
|
9
|
+
adapter :sql do
|
10
|
+
url 'sqlite3::memory:'
|
11
|
+
primary_key :id
|
12
|
+
table 'articles'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# @example
|
17
|
+
class UserSQL
|
18
|
+
include AnyQuery
|
19
|
+
|
20
|
+
adapter :sql do
|
21
|
+
url 'sqlite3::memory:'
|
22
|
+
primary_key :id
|
23
|
+
table 'users'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# @example
|
28
|
+
class CommentSQL
|
29
|
+
include AnyQuery
|
30
|
+
|
31
|
+
adapter :sql do
|
32
|
+
url 'sqlite3::memory:'
|
33
|
+
primary_key :id
|
34
|
+
table 'comments'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class ArticleHTTP
|
39
|
+
include AnyQuery
|
40
|
+
|
41
|
+
adapter :http do
|
42
|
+
url 'http://example.com'
|
43
|
+
primary_key :id
|
44
|
+
endpoint :list, :get, "/articles",
|
45
|
+
wrapper: [:items],
|
46
|
+
pagination: { type: :page },
|
47
|
+
default_params: {
|
48
|
+
query: { some_query_param: 1 },
|
49
|
+
headers: { 'Authorization': 'some' }
|
50
|
+
}
|
51
|
+
endpoint :show, :get, "/articles/{id}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class UserHTTP
|
56
|
+
include AnyQuery
|
57
|
+
|
58
|
+
adapter :http do
|
59
|
+
url 'http://example.com'
|
60
|
+
primary_key :id
|
61
|
+
endpoint :list, :get, "/users",
|
62
|
+
wrapper: [:items],
|
63
|
+
pagination: { type: :cursor },
|
64
|
+
default_params: {
|
65
|
+
query: { some_query_param: true },
|
66
|
+
headers: { 'Authorization': 'some' }
|
67
|
+
}
|
68
|
+
endpoint :show, :get, "/users/{id}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class ScopedUserHTTP
|
73
|
+
include AnyQuery
|
74
|
+
|
75
|
+
adapter :http do
|
76
|
+
url 'http://example.com'
|
77
|
+
primary_key :id
|
78
|
+
endpoint :list, :get, "/{company_id}/users",
|
79
|
+
wrapper: [:items],
|
80
|
+
pagination: { type: :none },
|
81
|
+
default_params: {
|
82
|
+
headers: { 'Authorization': 'some' }
|
83
|
+
}
|
84
|
+
endpoint :show, :get, "/{company_id}/users/{id}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class ArticleCSV
|
89
|
+
include AnyQuery
|
90
|
+
|
91
|
+
adapter :csv do
|
92
|
+
url File.join(__dir__, '../fixtures/sample.csv')
|
93
|
+
primary_key :id
|
94
|
+
end
|
95
|
+
|
96
|
+
field :id, type: :integer
|
97
|
+
field :user_id, type: :integer
|
98
|
+
field :title, type: :string
|
99
|
+
field :body, type: :string
|
100
|
+
field :status, type: :integer
|
101
|
+
field :created_at, type: :datetime, format: '%Y-%m-%d %H:%M:%S'
|
102
|
+
end
|
103
|
+
|
104
|
+
class ArticleFL
|
105
|
+
include AnyQuery
|
106
|
+
|
107
|
+
adapter :fixed_length do
|
108
|
+
url File.join(__dir__, '../fixtures/sample.txt')
|
109
|
+
primary_key :id
|
110
|
+
end
|
111
|
+
|
112
|
+
field :id, type: :integer, length: 4
|
113
|
+
field :user_id, type: :integer, length: 4
|
114
|
+
field :title, type: :string, length: 30
|
115
|
+
field :body, type: :string, length: 100
|
116
|
+
field :status, type: :integer, length: 1
|
117
|
+
field :created_at, type: :datetime, format: '%Y%m%d%H%M%S', length: 14
|
118
|
+
end
|
119
|
+
|
120
|
+
module Schema
|
121
|
+
def self.create
|
122
|
+
ActiveRecord::Migration.verbose = false
|
123
|
+
|
124
|
+
ActiveRecord::Schema.define do
|
125
|
+
create_table :users, force: true do |t|
|
126
|
+
t.string :email
|
127
|
+
t.timestamps null: false
|
128
|
+
end
|
129
|
+
|
130
|
+
create_table :articles, force: true do |t|
|
131
|
+
t.integer :user_id
|
132
|
+
t.string :title
|
133
|
+
t.text :body
|
134
|
+
t.integer :status
|
135
|
+
t.timestamps null: false
|
136
|
+
end
|
137
|
+
|
138
|
+
create_table :comments, force: true do |t|
|
139
|
+
t.integer :article_id
|
140
|
+
t.text :body
|
141
|
+
end
|
142
|
+
|
143
|
+
ActiveRecord::Base.connection.execute("INSERT INTO users VALUES (1, 'test@test.com', '2021-01-01 00:00:00', '2021-01-01 00:00:00')")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|