metka 2.0.3 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,11 +1,16 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/metka.svg)](https://badge.fury.io/rb/metka)
2
- [![Build Status](https://travis-ci.org/jetrockets/metka.svg?branch=master)](https://travis-ci.org/jetrockets/metka)
2
+ [![Build Status](https://github.com/jetrockets/metka/workflows/Specs/badge.svg?branch=master)](https://github.com/jetrockets/metka/actions)
3
3
  [![Open Source Helpers](https://www.codetriage.com/jetrockets/metka/badges/users.svg)](https://www.codetriage.com/jetrockets/metka)
4
4
 
5
5
  # Metka
6
6
 
7
7
  Rails gem to manage tags with PostgreSQL array columns.
8
8
 
9
+ :exclamation: Requirements:
10
+
11
+ * Ruby ~> 2.5
12
+ * Rails >= 5.2 (for Rails 5.1 and 5.0 use version <2.1.0)
13
+
9
14
  ## Installation
10
15
 
11
16
  Add this line to your application's Gemfile:
@@ -16,11 +21,15 @@ gem 'metka'
16
21
 
17
22
  And then execute:
18
23
 
19
- $ bundle
24
+ ```bash
25
+ bundle
26
+ ```
20
27
 
21
28
  Or install it yourself as:
22
29
 
23
- $ gem install metka
30
+ ```bash
31
+ gem install metka
32
+ ```
24
33
 
25
34
  ## Tag objects
26
35
 
@@ -32,9 +41,9 @@ rails g migration CreateSongs
32
41
  class CreateSongs < ActiveRecord::Migration[5.0]
33
42
  def change
34
43
  create_table :songs do |t|
35
- t.string :title
36
- t.string :tags, array: true
37
- t.string :genres, array: true
44
+ t.string :title
45
+ t.string :tags, array: true, default: [], index: { using: :gin }
46
+ t.string :genres, array: true, default: [], index: { using: :gin }
38
47
  t.timestamps
39
48
  end
40
49
  end
@@ -55,140 +64,167 @@ end
55
64
  ## Find tagged objects
56
65
 
57
66
  ### .with_all_#{column_name}
67
+
58
68
  ```ruby
59
69
  Song.with_all_tags('top')
60
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
70
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
61
71
 
62
72
  Song.with_all_tags('top, 1990')
63
- => []
73
+ #=> []
64
74
 
65
75
  Song.with_all_tags('')
66
- => []
76
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
77
+
78
+ Song.with_all_tags(nil)
79
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
67
80
 
68
81
  Song.with_all_genres('rock')
69
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
82
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
70
83
  ```
71
84
 
72
85
  ### .with_any_#{column_name}
86
+
73
87
  ```ruby
74
88
  Song.with_any_tags('chill')
75
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
89
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
76
90
 
77
91
  Song.with_any_tags('chill, 1980')
78
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
92
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
79
93
 
80
94
  Song.with_any_tags('')
81
- => []
95
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
96
+
97
+ Song.with_any_tags(nil)
98
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
82
99
 
83
100
  Song.with_any_genres('rock, rap')
84
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
101
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
85
102
  ```
103
+
86
104
  ### .without_all_#{column_name}
105
+
87
106
  ```ruby
88
107
  Song.without_all_tags('top')
89
- => []
108
+ #=> []
90
109
 
91
110
  Song.without_all_tags('top, 1990')
92
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
111
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
93
112
 
94
113
  Song.without_all_tags('')
95
- => []
114
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
115
+
116
+ Song.without_all_tags(nil)
117
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
96
118
 
97
119
  Song.without_all_genres('rock, pop')
98
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
120
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
99
121
 
100
122
  Song.without_all_genres('rock')
101
- => []
123
+ #=> []
102
124
  ```
103
125
 
104
126
  ### .without_any_#{column_name}
127
+
105
128
  ```ruby
106
129
  Song.without_any_tags('top, 1990')
107
- => []
130
+ #=> []
108
131
 
109
132
  Song.without_any_tags('1990, 1980')
110
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
133
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
111
134
 
112
135
  Song.without_any_genres('rock, pop')
113
- => []
136
+ #=> []
114
137
 
115
138
  Song.without_any_genres('')
116
- => []
139
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
140
+
141
+ Song.without_any_genres(nil)
142
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
117
143
  ```
118
144
 
119
145
  ### .tagged_with
146
+
120
147
  ```ruby
121
148
  Song.tagged_with('top')
122
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
149
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
123
150
 
124
151
  Song.tagged_with('top, 1990')
125
- => []
152
+ #=> []
126
153
 
127
154
  Song.tagged_with('')
128
- => []
155
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
156
+
157
+ Song.tagged_with(nil)
158
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
129
159
 
130
160
  Song.tagged_with('rock')
131
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
161
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
132
162
 
133
163
  Song.tagged_with('rock', join_operator: Metka::And)
134
- => []
164
+ #=> []
135
165
 
136
166
  Song.tagged_with('chill', any: true)
137
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
167
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
138
168
 
139
169
  Song.tagged_with('chill, 1980', any: true)
140
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
170
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
141
171
 
142
172
  Song.tagged_with('', any: true)
143
- => []
173
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
144
174
 
145
175
  Song.tagged_with('rock, rap', any: true, on: ['genres'])
146
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
176
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
147
177
 
148
178
  Song.without_all_tags('top')
149
- => []
179
+ #=> []
150
180
 
151
181
  Song.tagged_with('top, 1990', exclude: true)
152
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
182
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
153
183
 
154
184
  Song.tagged_with('', exclude: true)
155
- => []
185
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
156
186
 
157
187
  Song.tagged_with('top, 1990', any: true, exclude: true)
158
- => []
188
+ #=> []
159
189
 
160
190
  Song.tagged_with('1990, 1980', any: true, exclude: true)
161
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
191
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
162
192
 
163
193
  Song.without_any_genres('rock, pop')
164
- => []
194
+ #=> []
165
195
  ```
166
196
 
167
197
  ## Custom delimiter
198
+
168
199
  By default, a comma is used as a delimiter to create tags from a string.
169
200
  You can make your own custom separator:
201
+
170
202
  ```ruby
171
203
  Metka.config.delimiter = '|'
172
204
  parsed_data = Metka::GenericParser.instance.call('cool, data|I have')
173
205
  parsed_data.to_a
174
- =>['cool, data', 'I have']
206
+ #=>['cool, data', 'I have']
175
207
  ```
176
208
 
177
209
  ## Tags with quote
210
+
178
211
  ```ruby
179
212
  parsed_data = Metka::GenericParser.instance.call("'cool, data', code")
180
213
  parsed_data.to_a
181
- => ['cool, data', 'code']
214
+ #=> ['cool, data', 'code']
182
215
  ```
183
216
 
184
217
  ## Custom parser
218
+
185
219
  By default we use [generic_parser](lib/metka/generic_parser.rb "generic_parser")
186
220
  If you want to use your custom parser you can do:
221
+
187
222
  ```ruby
188
223
  class Song < ActiveRecord::Base
189
224
  include Metka::Model(columns: %w[genres tags], parser: Your::Custom::Parser.instance)
190
225
  end
191
226
  ```
227
+
192
228
  Custom parser must be a singleton class that has a `.call` method that accepts the tag string
193
229
 
194
230
  ## Tag Cloud Strategies
@@ -200,29 +236,30 @@ There are several strategies to get tag statistics
200
236
  Data about taggings is accessible via class methods of your model with `Metka::Model` attached. You can calculate a cloud for a single tagged column or multiple columns, the latter case would return to you a sum of taggings from multiple tagged columns, that are provided as arguments, for each tag present. ActiveRecord Strategy is an easiest way to implement, since it wouldn't require any additional code, but it's the slowest one on SELECT.
201
237
 
202
238
  ```ruby
239
+
203
240
  class Book < ActiveRecord::Base
204
241
  include Metka::Model(column: 'authors')
205
242
  include Metka::Model(column: 'co_authors')
206
243
  end
207
244
 
208
245
  tag_cloud = Book.author_cloud
209
- => [["L.N. Tolstoy", 3], ["F.M. Dostoevsky", 6]]
246
+ #=> [["L.N. Tolstoy", 3], ["F.M. Dostoevsky", 6]]
210
247
  genre_cloud = Book.co_author_cloud
211
- => [["A.P. Chekhov", 5], ["N.V. Gogol", 8], ["L.N. Tolstoy", 2]]
248
+ #=> [["A.P. Chekhov", 5], ["N.V. Gogol", 8], ["L.N. Tolstoy", 2]]
212
249
  summary_cloud = Book.metka_cloud('authors', 'co_authors')
213
- => [["L.N. Tolstoy", 5], ["F.M. Dostoevsky", 6], ["A.P. Chekhov", 5], ["N.V. Gogol", 8]]
250
+ #=> [["L.N. Tolstoy", 5], ["F.M. Dostoevsky", 6], ["A.P. Chekhov", 5], ["N.V. Gogol", 8]]
214
251
  ```
215
252
 
216
253
  ### View Strategy
217
254
 
218
- Data about taggings will be agregated in SQL View. Performance-wise that strategy has no benefits over ActiveRecord Strategy, but if you need to store tags aggregations in a distinct model, that's an easiest way to achieve it.
255
+ Data about taggings will be aggregated in SQL View. Performance-wise that strategy has no benefits over ActiveRecord Strategy, but if you need to store tags aggregations in a distinct model, that's an easiest way to achieve it.
219
256
 
220
257
  ```bash
221
258
  rails g metka:strategies:view --source-table-name=NAME_OF_TABLE_WITH_TAGS [--source-columns=NAME_OF_COLUMN_1 NAME_OF_COLUMN_2] [--view-name=NAME_OF_RESULTING_VIEW]
222
259
  ```
223
260
 
224
261
  The code above will generate a migration that creates view with specified `NAME_OF_RESULTING_VIEW`, that would aggregate tags data from specified array of tagged columns [`NAME_OF_COLUMN_1`, `NAME_OF_COLUMN_2`, ...], that are present within specified table `NAME_OF_TABLE_WITH_TAGS`.
225
- If `source-columns` option is not provided, then `tags` column would be used as defaults. If array of multiple values would be provided to the option, then the aggregation would be made with the tags from multiple tagged columns, so if a single tag would be found within multiple tagged columns, the resulting aggregation inside the view would have a single row for that tag with a sum of it's occurences across all stated tagged columns.
262
+ If `source-columns` option is not provided, then `tags` column would be used as defaults. If array of multiple values would be provided to the option, then the aggregation would be made with the tags from multiple tagged columns, so if a single tag would be found within multiple tagged columns, the resulting aggregation inside the view would have a single row for that tag with a sum of it's occurrences across all stated tagged columns.
226
263
  `view-name` option is also optional, it would just force the resulting view's name to the one of your choice. If it's not provided, then view name would be generated automatically, you could check it within generated migration.
227
264
 
228
265
  Lets take a look at real example. We have a `notes` table with `tags` column.
@@ -290,7 +327,7 @@ Data about taggings will be aggregated in SQL Materialized View, that would be r
290
327
  rails g metka:strategies:materialized_view --source-table-name=NAME_OF_TABLE_WITH_TAGS --source-columns=NAME_OF_COLUMN_1 NAME_OF_COLUMN_2 --view-name=NAME_OF_RESULTING_VIEW
291
328
  ```
292
329
 
293
- All of the options for that stategy's generation command are the same as for the View Strategy.
330
+ All of the options for that strategy's generation command are the same as for the View Strategy.
294
331
 
295
332
  The migration template can be seen [here](spec/dummy/db/migrate/06_create_tagged_materialized_view_posts_materialized_view.rb "here")
296
333
 
@@ -308,15 +345,43 @@ And you can also create `TaggedNote` model to work with the view as with a Rails
308
345
 
309
346
  ### Table Strategy with Triggers
310
347
 
311
-
312
-
313
348
  TBD
314
349
 
315
350
  ## Inspired by
351
+
316
352
  1. [ActsAsTaggableOn](https://github.com/mbleigh/acts-as-taggable-on)
317
353
  2. [ActsAsTaggableArrayOn](https://github.com/tmiyamon/acts-as-taggable-array-on)
318
354
  3. [TagColumns](https://github.com/hopsoft/tag_columns)
319
355
 
356
+ ## Migration from ActsAsTaggable
357
+
358
+ To migrate your data from `ActsAsTaggable` can be done with the following migration.
359
+
360
+ ```ruby
361
+ class AddTagsToYourTable < ActiveRecord::Migration[6.0]
362
+ def change
363
+ add_column :your_table, :tags, :string, array: true
364
+ add_index :your_table, :tags, using: 'gin'
365
+
366
+ execute <<~SQL
367
+ UPDATE your_table
368
+ SET tags = tags.names
369
+ FROM (
370
+ SELECT taggings.taggable_id AS your_table_id,
371
+ array_agg(tags.name) as names
372
+ FROM tags
373
+ INNER JOIN taggings
374
+ ON tags.id = taggings.tag_id
375
+ WHERE
376
+ taggings.taggable_type = 'YouTableType'
377
+ GROUP BY taggings.taggable_id
378
+ ) as tags
379
+ WHERE your_table.id = tags.your_table_id
380
+ SQL
381
+ end
382
+ end
383
+ ```
384
+
320
385
  ## Benchmark Comparison
321
386
 
322
387
  There are some results of benchmarking a performance of write, read and find operations for different gems, that provide solution for tagging. Keep in mind, that those results can't be used as a proof, that some solution is better than the others, since each of the benchmarked gems has their unique features. You could run the benchmarks yourself or check, what exact operations has been used for benchmarking, with [MetkaBench application](https://github.com/jetrockets/metka_bench).
@@ -447,9 +512,10 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
447
512
 
448
513
  ## Contributing
449
514
 
450
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/metka. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
515
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/jetrockets/metka](https://github.com/jetrockets/metka). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
451
516
 
452
517
  ## Credits
518
+
453
519
  ![JetRockets](https://media.jetrockets.pro/jetrockets-white.png)
454
520
  Metka is maintained by [JetRockets](http://www.jetrockets.ru).
455
521
 
data/forspell.dict ADDED
@@ -0,0 +1,7 @@
1
+ # Format: one word per line. Empty lines and #-comments are supported too.
2
+ # If you want to add word with its forms, you can write 'word: example' (without quotes) on the line,
3
+ # where 'example' is existing word with the same possible forms (endings) as your word.
4
+ # Example: deduplicate: duplicate
5
+ Metka
6
+ taggings
7
+ benchmarked
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'rails', '~>5.2'
3
+ gem 'rails', '~> 5.2'
4
4
  gem 'activerecord', '~> 5.2.4.3'
5
5
 
6
6
  gemspec path: '..'
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'rails', '~>6.0'
4
- gem 'activerecord', '~> 6.0'
3
+ gem 'rails', '~> 6.0', ' < 6.1'
4
+ gem 'activerecord', '~> 6.0', '< 6.1'
5
5
 
6
6
  gemspec path: '..'
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'rails', '~> 6.1'
4
+ gem 'activerecord', '~> 6.1'
5
+
6
+ gemspec path: '..'
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'rails', github: 'rails/rails', branch: 'main'
4
+
5
+ gemspec path: '..'
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org" do
2
+ gem "rubocop-md", "~> 1.0"
3
+ gem "jetrockets-standard"
4
+ end
@@ -25,7 +25,7 @@ module Metka
25
25
  gsub_quote_pattern!(tag_list, value, double_quote_pattern)
26
26
  gsub_quote_pattern!(tag_list, value, single_quote_pattern)
27
27
 
28
- tag_list.merge value.split(Regexp.new delimiter).map(&:strip).reject(&:empty?)
28
+ tag_list.merge value.split(Regexp.new(delimiter)).map(&:strip).reject(&:empty?)
29
29
  when Enumerable
30
30
  tag_list.merge value.reject(&:empty?)
31
31
  end
@@ -46,7 +46,7 @@ module Metka
46
46
  end
47
47
 
48
48
  def single_quote_pattern
49
- @single_quote_pattern[delimiter] ||= /(\A|#{delimiter})\s*'(.*?)'\s*(?=#{delimiter}\s*|\z)/
49
+ @single_quote_pattern[delimiter] ||= /(\A|#{delimiter})\s*'(.*?)'\s*(?=#{delimiter}\s*|\z)/
50
50
  end
51
51
 
52
52
  def double_quote_pattern
data/lib/metka/model.rb CHANGED
@@ -35,7 +35,7 @@ module Metka
35
35
  cols = options.delete(:on)
36
36
  parsed_tag_list = parser.call(tags)
37
37
 
38
- return model.none if parsed_tag_list.empty?
38
+ return model if parsed_tag_list.empty?
39
39
 
40
40
  request = ::Metka::QueryBuilder.new.call(model, cols, parsed_tag_list, options)
41
41
  model.where(request)
@@ -43,10 +43,10 @@ module Metka
43
43
 
44
44
  base.class_eval do
45
45
  columns.each do |column|
46
- scope "with_all_#{column}", ->(tags) { tagged_with(tags, on: [ column ]) }
47
- scope "with_any_#{column}", ->(tags) { tagged_with(tags, on: [ column ], any: true) }
48
- scope "without_all_#{column}", ->(tags) { tagged_with(tags, on: [ column ], exclude: true) }
49
- scope "without_any_#{column}", ->(tags) { tagged_with(tags, on: [ column ], any: true, exclude: true) }
46
+ scope "with_all_#{column}", ->(tags) { tagged_with(tags, on: [column]) }
47
+ scope "with_any_#{column}", ->(tags) { tagged_with(tags, on: [column], any: true) }
48
+ scope "without_all_#{column}", ->(tags) { tagged_with(tags, on: [column], exclude: true) }
49
+ scope "without_any_#{column}", ->(tags) { tagged_with(tags, on: [column], any: true, exclude: true) }
50
50
  end
51
51
 
52
52
  unless respond_to?(:tagged_with)
@@ -66,7 +66,7 @@ module Metka
66
66
  prepared_unnest = columns.map { |column| "#{table_name}.#{column}" }.join(' || ')
67
67
  subquery = all.select("UNNEST(#{prepared_unnest}) AS tag_name")
68
68
 
69
- unscoped.from(subquery).group(:tag_name).pluck(:tag_name, 'COUNT(*) AS taggings_count')
69
+ unscoped.from(subquery).group(:tag_name).pluck(:tag_name, Arel.sql('COUNT(*) AS taggings_count'))
70
70
  end
71
71
 
72
72
  columns.each do |column|