top_n_loader 1.0.0 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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