top_n_loader 1.0.0 → 1.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
  SHA256:
3
- metadata.gz: cd29e09d74f26981a3772f7ac8871d7fe00bbaa736588f2de733acea20ad7bc5
4
- data.tar.gz: 19a89bc3aaf851949e203fd0c29402f0c99fa6d3b3ce40227b4c7faa39c95370
3
+ metadata.gz: d905751360ae053d80faa6332daad7e5fce710c2b44031483d71018e15d67c1a
4
+ data.tar.gz: dc175dd9e135880cb26c1c81c2784500e8ee0950dda9b03a39799af6d0b98710
5
5
  SHA512:
6
- metadata.gz: 42e80f413a55f32365bcc68425ae2d070f56a708387db2b91f867018604b1b20076e303ce07212369cb04cc86eb66632aa70fde0f932608199c6bfc31c363c8f
7
- data.tar.gz: bbbbe954a980640ad53014604198fed10ff1047e09e1850ae18b7cb304e38240029ce9e583cdbb634923ac2f99819789cc9eec7a06680a1e32f2bcf861e42402
6
+ metadata.gz: fb24707fdea8d9162a87b6960cce21ee38d5f9c5ab8cadee549a97518e0da9c1f1fea5e2c6ae50b0b1db0171d868ec5cb2c5f3c058b8e1cefba14491b058d2ec
7
+ data.tar.gz: a69198a3697ebc97e49c5c36d71103b9c8afb837b1416a7668e0190323042b3af51af3cd14bd1e22351646f271b825e385db53a80bb8090f3baf34e6e47626d4
@@ -0,0 +1,22 @@
1
+ name: Test
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ fail-fast: false
7
+ matrix:
8
+ ruby: [ '2.7', '3.0', '3.1' ]
9
+ gemfiles:
10
+ - gemfiles/Gemfile-rails-6.0
11
+ - gemfiles/Gemfile-rails-7.0
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v2
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: ${{ matrix.ruby }}
18
+ - run: |
19
+ sudo apt-get update
20
+ sudo apt-get install -y libsqlite3-dev
21
+ - run: bundle install --gemfile ${{ matrix.gemfiles }} --jobs 4 --retry 3
22
+ - run: bundle exec --gemfile ${{ matrix.gemfiles }} rake
data/.rubocop.yml ADDED
@@ -0,0 +1,16 @@
1
+ require:
2
+ - rubocop-rubycw
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.7
6
+ DisabledByDefault: true
7
+
8
+ Rubycw/Rubycw:
9
+ Enabled: true
10
+ Exclude:
11
+ - 'test/**/*_test.rb'
12
+
13
+ Lint/DuplicateMethods:
14
+ Enabled: true
15
+ Include:
16
+ - 'test/**/*_test.rb'
data/Gemfile.lock CHANGED
@@ -1,45 +1,59 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- top_n_loader (1.0.0)
4
+ top_n_loader (1.0.3)
5
5
  activerecord
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (5.2.3)
11
- activesupport (= 5.2.3)
12
- activerecord (5.2.3)
13
- activemodel (= 5.2.3)
14
- activesupport (= 5.2.3)
15
- arel (>= 9.0)
16
- activesupport (5.2.3)
10
+ activemodel (7.0.3)
11
+ activesupport (= 7.0.3)
12
+ activerecord (7.0.3)
13
+ activemodel (= 7.0.3)
14
+ activesupport (= 7.0.3)
15
+ activesupport (7.0.3)
17
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
18
- i18n (>= 0.7, < 2)
19
- minitest (~> 5.1)
20
- tzinfo (~> 1.1)
21
- arel (9.0.0)
22
- coderay (1.1.2)
23
- concurrent-ruby (1.1.5)
24
- docile (1.1.5)
25
- i18n (1.6.0)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ ast (2.4.2)
21
+ concurrent-ruby (1.1.10)
22
+ docile (1.4.0)
23
+ i18n (1.10.0)
26
24
  concurrent-ruby (~> 1.0)
27
- json (2.1.0)
28
- method_source (0.9.0)
29
- minitest (5.11.3)
30
- pry (0.11.3)
31
- coderay (~> 1.1.0)
32
- method_source (~> 0.9.0)
33
- rake (10.5.0)
34
- simplecov (0.15.1)
35
- docile (~> 1.1.0)
36
- json (>= 1.8, < 3)
37
- simplecov-html (~> 0.10.0)
38
- simplecov-html (0.10.2)
39
- sqlite3 (1.3.13)
40
- thread_safe (0.3.6)
41
- tzinfo (1.2.5)
42
- thread_safe (~> 0.1)
25
+ minitest (5.16.1)
26
+ parallel (1.22.1)
27
+ parser (3.1.2.0)
28
+ ast (~> 2.4.1)
29
+ rainbow (3.1.1)
30
+ rake (13.0.6)
31
+ regexp_parser (2.5.0)
32
+ rexml (3.2.5)
33
+ rubocop (1.31.0)
34
+ parallel (~> 1.10)
35
+ parser (>= 3.1.0.0)
36
+ rainbow (>= 2.2.2, < 4.0)
37
+ regexp_parser (>= 1.8, < 3.0)
38
+ rexml (>= 3.2.5, < 4.0)
39
+ rubocop-ast (>= 1.18.0, < 2.0)
40
+ ruby-progressbar (~> 1.7)
41
+ unicode-display_width (>= 1.4.0, < 3.0)
42
+ rubocop-ast (1.18.0)
43
+ parser (>= 3.1.1.0)
44
+ rubocop-rubycw (0.1.6)
45
+ rubocop (~> 1.0)
46
+ ruby-progressbar (1.11.0)
47
+ simplecov (0.21.2)
48
+ docile (~> 1.1)
49
+ simplecov-html (~> 0.11)
50
+ simplecov_json_formatter (~> 0.1)
51
+ simplecov-html (0.12.3)
52
+ simplecov_json_formatter (0.1.4)
53
+ sqlite3 (1.4.4)
54
+ tzinfo (2.0.4)
55
+ concurrent-ruby (~> 1.0)
56
+ unicode-display_width (2.2.0)
43
57
 
44
58
  PLATFORMS
45
59
  ruby
@@ -47,11 +61,12 @@ PLATFORMS
47
61
  DEPENDENCIES
48
62
  bundler
49
63
  minitest
50
- pry
51
64
  rake
65
+ rubocop
66
+ rubocop-rubycw
52
67
  simplecov
53
68
  sqlite3
54
69
  top_n_loader!
55
70
 
56
71
  BUNDLED WITH
57
- 1.17.2
72
+ 2.1.4
data/README.md CHANGED
@@ -35,7 +35,7 @@ end
35
35
 
36
36
  ```ruby
37
37
  # Gemfile
38
- gem 'top_n_loader', github: 'tompng/top_n_loader'
38
+ gem 'top_n_loader'
39
39
  ```
40
40
 
41
41
  ```ruby
data/Rakefile CHANGED
@@ -7,4 +7,9 @@ Rake::TestTask.new(:test) do |t|
7
7
  t.test_files = FileList["test/**/*_test.rb"]
8
8
  end
9
9
 
10
- task :default => :test
10
+ desc "Run rubocop"
11
+ task :rubocop do
12
+ sh 'bundle exec rubocop'
13
+ end
14
+
15
+ task default: [:rubocop, :test]
data/bin/console CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'top_n_loader'
5
- require 'pry'
6
5
  require_relative '../test/db'
7
6
 
8
- Pry.start
7
+ DB.connect DB::DATABASE_CONFIG_SQLITE3
8
+ binding.irb
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in top_n_loader.gemspec
6
+ gemspec path: ".."
7
+
8
+ gem "activerecord", "~> 6.0.0"
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in top_n_loader.gemspec
6
+ gemspec path: ".."
7
+
8
+ gem "activerecord", "~> 7.0.0"
@@ -9,71 +9,92 @@ module TopNLoader::SQLBuilder
9
9
  end
10
10
 
11
11
  def self.top_n_association_sql(klass, target_klass, relation, limit:, order_mode:, order_key:)
12
+ limit = limit.to_i
12
13
  parent_table = klass.table_name
13
14
  joins = klass.joins relation.to_sym
14
15
  target_table = target_klass.table_name
16
+ nullable = nullable_column? target_klass, order_key
15
17
  if target_table == klass.table_name
16
18
  target_table = "#{joins.joins_values.first.to_s.pluralize}_#{target_table}"
17
19
  end
18
20
  join_sql = joins.to_sql.match(/FROM.+/)[0]
19
- %(
21
+ parent_primary_key = "#{qt parent_table}.#{q klass.primary_key}"
22
+ target_order_key = "#{qt target_table}.#{q order_key}"
23
+ target_primary_key = "#{qt target_table}.#{q target_klass.primary_key}"
24
+ top_n_key, top_n_alias, t_join_cond = limit == 1 ? [
25
+ target_primary_key, :top_n_primary_key, "#{target_primary_key} = top_n_primary_key"
26
+ ] : [
27
+ target_order_key, :top_n_order_key, compare_cond(target_order_key, order_mode, includes_nil: nullable)
28
+ ]
29
+ order_columns = limit == 1 ? [target_order_key, target_primary_key].uniq : [target_order_key]
30
+ order_cond = order_columns.map {|column| "#{column} #{order_mode.to_s.upcase}"}.join(', ')
31
+ <<~SQL.squish
20
32
  SELECT #{qt target_table}.*, top_n_group_key
21
33
  #{join_sql}
22
34
  INNER JOIN
23
35
  (
24
- SELECT T.#{q klass.primary_key} as top_n_group_key,
36
+ SELECT T.#{q klass.primary_key} AS top_n_group_key,
25
37
  (
26
- SELECT #{qt target_table}.#{q order_key}
38
+ SELECT #{top_n_key}
27
39
  #{join_sql}
28
- WHERE #{qt parent_table}.#{q klass.primary_key} = T.#{q klass.primary_key}
29
- ORDER BY #{qt target_table}.#{q order_key} #{order_mode.upcase}
30
- LIMIT 1 OFFSET #{limit.to_i - 1}
31
- ) AS last_value
32
- FROM #{qt parent_table} as T where T.#{q klass.primary_key} in (?)
40
+ WHERE #{parent_primary_key} = T.#{q klass.primary_key}
41
+ ORDER BY #{order_cond}
42
+ LIMIT 1#{" OFFSET #{limit - 1}" if limit != 1}
43
+ ) AS #{top_n_alias}
44
+ FROM #{qt parent_table} AS T WHERE T.#{q klass.primary_key} IN (?)
33
45
  ) T
34
- ON #{qt parent_table}.#{q klass.primary_key} = T.top_n_group_key
35
- AND (
36
- T.last_value IS NULL
37
- OR #{qt target_table}.#{q order_key} #{{ asc: :<=, desc: :>= }[order_mode]} T.last_value
38
- OR #{qt target_table}.#{q order_key} is NULL
39
- )
40
- )
46
+ ON #{parent_primary_key} = T.top_n_group_key AND #{t_join_cond}
47
+ SQL
41
48
  end
42
49
 
43
-
44
50
  def self.top_n_group_sql(klass:, group_column:, group_keys:, condition:, limit:, order_mode:, order_key:)
45
- order_op = order_mode == :asc ? :<= : :>=
46
- group_key_table = value_table(:T, :top_n_group_key, group_keys)
51
+ limit = limit.to_i
47
52
  table_name = klass.table_name
48
53
  sql = condition_sql klass, condition
49
- join_cond = %(#{qt table_name}.#{q group_column} = T.top_n_group_key)
50
- if group_keys.include? nil
51
- nil_join_cond = %((#{qt table_name}.#{q group_column} IS NULL AND T.top_n_group_key IS NULL))
52
- join_cond = %((#{join_cond} OR #{nil_join_cond}))
53
- end
54
- %(
54
+ group_key_nullable = group_keys.include?(nil) && nullable_column?(klass, group_column)
55
+ order_key_nullable = nullable_column? klass, order_key
56
+ group_key_table = value_table :T, :top_n_group_key, group_keys
57
+ table_order_key = "#{qt table_name}.#{q order_key}"
58
+ join_cond = equals_cond "#{qt table_name}.#{q group_column}", includes_nil: group_key_nullable
59
+ table_primary_key = "#{qt table_name}.#{q klass.primary_key}"
60
+ top_n_key, top_n_alias, t_join_cond = limit == 1 ? [
61
+ table_primary_key, :top_n_primary_key, "#{table_primary_key} = top_n_primary_key"
62
+ ] : [
63
+ table_order_key, :top_n_order_key,
64
+ "#{compare_cond table_order_key, order_mode, includes_nil: order_key_nullable}#{" WHERE #{sql}" if sql}"
65
+ ]
66
+ order_columns = limit == 1 ? [table_order_key, table_primary_key].uniq : [table_order_key]
67
+ order_cond = order_columns.map {|column| "#{column} #{order_mode.to_s.upcase}"}.join(', ')
68
+ <<~SQL.squish
55
69
  SELECT #{qt table_name}.*, top_n_group_key
56
70
  FROM #{qt table_name}
57
71
  INNER JOIN
58
72
  (
59
73
  SELECT top_n_group_key,
60
74
  (
61
- SELECT #{qt table_name}.#{q order_key} FROM #{qt table_name}
62
- WHERE #{join_cond}
63
- #{"AND #{sql}" if sql}
64
- ORDER BY #{qt table_name}.#{q order_key} #{order_mode.to_s.upcase}
65
- LIMIT 1 OFFSET #{limit.to_i - 1}
66
- ) AS last_value
75
+ SELECT #{top_n_key} FROM #{qt table_name}
76
+ WHERE #{join_cond}#{" AND #{sql}" if sql}
77
+ ORDER BY #{order_cond}
78
+ LIMIT 1#{" OFFSET #{limit - 1}" if limit != 1}
79
+ ) AS #{top_n_alias}
67
80
  FROM #{group_key_table}
68
81
  ) T
69
- ON #{join_cond}
70
- AND (
71
- T.last_value IS NULL
72
- OR #{qt table_name}.#{q order_key} #{order_op} T.last_value
73
- OR #{qt table_name}.#{q order_key} is NULL
74
- )
75
- #{"WHERE #{sql}" if sql}
76
- )
82
+ ON #{join_cond} AND #{t_join_cond}
83
+ SQL
84
+ end
85
+
86
+ def self.equals_cond(column, includes_nil:, t_column: 'T.top_n_group_key')
87
+ cond = "#{column} = #{t_column}"
88
+ includes_nil ? "(#{cond} OR (#{column} IS NULL AND #{t_column} IS NULL))" : cond
89
+ end
90
+
91
+ def self.compare_cond(column, order_mode, includes_nil:, t_column: 'T.top_n_order_key')
92
+ op = order_mode == :asc ? '<=' : '>='
93
+ if includes_nil && (nil_first? ? order_mode == :asc : order_mode == :desc)
94
+ "(#{column} #{op} #{t_column} OR #{column} IS NULL OR #{t_column} IS NULL)"
95
+ else
96
+ "(#{column} #{op} #{t_column} OR #{t_column} IS NULL)"
97
+ end
77
98
  end
78
99
 
79
100
  def self.q(name)
@@ -84,24 +105,56 @@ module TopNLoader::SQLBuilder
84
105
  ActiveRecord::Base.connection.quote_table_name name
85
106
  end
86
107
 
108
+ def self.nullable_column?(klass, column)
109
+ klass.column_for_attribute(column).null
110
+ end
111
+
112
+ def self.type_values(values)
113
+ return [nil, values] if sqlite?
114
+ groups = values.group_by { _1.is_a?(Time) || _1.is_a?(DateTime) ? 0 : _1.is_a?(Date) ? 1 : 2 }
115
+ type = groups[0] ? :TIMESTAMP : groups[1] ? :DATE : nil
116
+ [type, groups.sort.flat_map(&:last)]
117
+ end
118
+
87
119
  def self.value_table(table, column, values)
88
- if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
89
- values_value_table(table, column, values)
120
+ type, values = type_values values
121
+ if postgres?
122
+ values_value_table table, column, values, type
90
123
  else
91
- union_value_table(table, column, values)
124
+ union_value_table table, column, values, type
92
125
  end
93
126
  end
94
127
 
95
- def self.union_value_table(table, column, values)
128
+ def self.values_table_batch_size
129
+ sqlite? ? 200 : 1000
130
+ end
131
+
132
+ def self.nil_first?
133
+ !postgres?
134
+ end
135
+
136
+ def self.adapter_name
137
+ ActiveRecord::Base.connection.adapter_name
138
+ end
139
+
140
+ def self.postgres?
141
+ adapter_name == 'PostgreSQL'
142
+ end
143
+
144
+ def self.sqlite?
145
+ adapter_name == 'SQLite'
146
+ end
147
+
148
+ def self.union_value_table(table, column, values, type)
96
149
  sanitize_sql_array [
97
- "(SELECT ? AS #{column}#{' UNION SELECT ?' * (values.size - 1)}) AS #{table}",
150
+ "(SELECT #{"#{type} " if type}? AS #{column}#{' UNION SELECT ?' * (values.size - 1)}) AS #{table}",
98
151
  *values
99
152
  ]
100
153
  end
101
154
 
102
- def self.values_value_table(table, column, values)
155
+ def self.values_value_table(table, column, values, type)
103
156
  sanitize_sql_array [
104
- "(VALUES #{(['(?)'] * values.size).join(',')}) AS #{table} (#{column})",
157
+ "(VALUES (#{"#{type} " if type}?) #{', (?)' * (values.size - 1)}) AS #{table} (#{column})",
105
158
  *values
106
159
  ]
107
160
  end
@@ -122,12 +175,12 @@ module TopNLoader::SQLBuilder
122
175
  sql_binds = begin
123
176
  case value
124
177
  when NilClass
125
- %(#{q key} IS NULL)
178
+ "#{q key} IS NULL"
126
179
  when Range
127
180
  if value.exclude_end?
128
- [%(#{q key} >= ? AND #{q key} < ?), value.begin, value.end]
181
+ ["#{q key} >= ? AND #{q key} < ?", value.begin, value.end]
129
182
  else
130
- [%(#{q key} BETWEEN ? AND ?), value.begin, value.end]
183
+ ["#{q key} BETWEEN ? AND ?", value.begin, value.end]
131
184
  end
132
185
  when Hash
133
186
  raise ArgumentError, '' unless value.keys == [:not]
@@ -135,12 +188,12 @@ module TopNLoader::SQLBuilder
135
188
  when Enumerable
136
189
  array = value.to_a
137
190
  if array.include? nil
138
- [%((#{q key} IS NULL OR #{q key} IN (?))), array.reject(&:nil?)]
191
+ ["(#{q key} IS NULL OR #{q key} IN (?))", array.reject(&:nil?)]
139
192
  else
140
- [%(#{q key} IN (?)), array]
193
+ ["#{q key} IN (?)", array]
141
194
  end
142
195
  else
143
- [%(#{q key} = ?), value]
196
+ ["#{q key} = ?", value]
144
197
  end
145
198
  end
146
199
  sanitize_sql_array sql_binds
@@ -1,3 +1,3 @@
1
1
  module TopNLoader
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.3'
3
3
  end
data/lib/top_n_loader.rb CHANGED
@@ -10,7 +10,7 @@ module TopNLoader
10
10
  return Hash.new { [] } if ids.empty? || limit.zero?
11
11
  klass = base_klass.reflect_on_association(relation.to_sym).klass
12
12
  order_option = { limit: limit, **parse_order(klass, order) }
13
- sql = SQLBuilder.top_n_association_sql base_klass, klass, relation, order_option
13
+ sql = SQLBuilder.top_n_association_sql base_klass, klass, relation, **order_option
14
14
  records = klass.find_by_sql([sql, ids])
15
15
  format_result(records, klass: klass, **order_option)
16
16
  end
@@ -25,14 +25,18 @@ module TopNLoader
25
25
  limit: limit,
26
26
  **parse_order(klass, order)
27
27
  }
28
- records = klass.find_by_sql(
29
- SQLBuilder.top_n_group_sql(
30
- group_keys: keys,
31
- condition: condition,
32
- **options
28
+ keys = keys.uniq
29
+ batch_size = keys.size.fdiv(keys.size.fdiv(SQLBuilder.values_table_batch_size).ceil).ceil
30
+ records = keys.each_slice(batch_size).flat_map do |batch_keys|
31
+ klass.find_by_sql(
32
+ SQLBuilder.top_n_group_sql(
33
+ group_keys: batch_keys,
34
+ condition: condition,
35
+ **options
36
+ )
33
37
  )
34
- )
35
- format_result records, options
38
+ end
39
+ format_result records, **options
36
40
  end
37
41
 
38
42
  private
@@ -74,7 +78,7 @@ module TopNLoader
74
78
  existings, blanks = grouped_records.partition { |o| o[order_key] }
75
79
  existings.sort_by! { |o| [o[order_key], o[primary_key]] }
76
80
  blanks.sort_by! { |o| o[primary_key] }
77
- ordered = blanks + existings
81
+ ordered = SQLBuilder.nil_first? ? blanks + existings : existings + blanks
78
82
  ordered.reverse! if order_mode == :desc
79
83
  ordered.take limit
80
84
  end
data/top_n_loader.gemspec CHANGED
@@ -10,6 +10,7 @@ Gem::Specification.new do |spec|
10
10
 
11
11
  spec.summary = %q{load top n records for each group}
12
12
  spec.description = %q{load top n records for each group}
13
+ spec.homepage = "https://github.com/tompng/#{spec.name}"
13
14
  spec.license = "MIT"
14
15
 
15
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -21,7 +22,7 @@ Gem::Specification.new do |spec|
21
22
 
22
23
  spec.add_dependency "activerecord"
23
24
 
24
- %w[bundler rake minitest sqlite3 pry simplecov].each do |gem_name|
25
+ %w[bundler rake minitest sqlite3 simplecov rubocop rubocop-rubycw].each do |gem_name|
25
26
  spec.add_development_dependency gem_name
26
27
  end
27
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: top_n_loader
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - tompng
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-05-11 00:00:00.000000000 Z
11
+ date: 2022-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -81,7 +81,7 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: pry
84
+ name: simplecov
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
@@ -95,7 +95,21 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: simplecov
98
+ name: 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-rubycw
99
113
  requirement: !ruby/object:Gem::Requirement
100
114
  requirements:
101
115
  - - ">="
@@ -115,8 +129,9 @@ executables: []
115
129
  extensions: []
116
130
  extra_rdoc_files: []
117
131
  files:
132
+ - ".github/workflows/test.yml"
118
133
  - ".gitignore"
119
- - ".travis.yml"
134
+ - ".rubocop.yml"
120
135
  - Gemfile
121
136
  - Gemfile.lock
122
137
  - LICENSE.txt
@@ -124,15 +139,17 @@ files:
124
139
  - Rakefile
125
140
  - bin/console
126
141
  - bin/setup
142
+ - gemfiles/Gemfile-rails-6.0
143
+ - gemfiles/Gemfile-rails-7.0
127
144
  - lib/top_n_loader.rb
128
145
  - lib/top_n_loader/sql_builder.rb
129
146
  - lib/top_n_loader/version.rb
130
147
  - top_n_loader.gemspec
131
- homepage:
148
+ homepage: https://github.com/tompng/top_n_loader
132
149
  licenses:
133
150
  - MIT
134
151
  metadata: {}
135
- post_install_message:
152
+ post_install_message:
136
153
  rdoc_options: []
137
154
  require_paths:
138
155
  - lib
@@ -147,8 +164,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
164
  - !ruby/object:Gem::Version
148
165
  version: '0'
149
166
  requirements: []
150
- rubygems_version: 3.0.1
151
- signing_key:
167
+ rubygems_version: 3.3.3
168
+ signing_key:
152
169
  specification_version: 4
153
170
  summary: load top n records for each group
154
171
  test_files: []
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.0
5
- before_install: gem install bundler -v 1.16.1