metka 2.0.1 → 2.2.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/Build/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,152 @@ 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
+ #=> []
67
77
 
68
78
  Song.with_all_genres('rock')
69
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
79
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
70
80
  ```
71
81
 
72
82
  ### .with_any_#{column_name}
83
+
73
84
  ```ruby
74
85
  Song.with_any_tags('chill')
75
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
86
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
76
87
 
77
88
  Song.with_any_tags('chill, 1980')
78
- => [#<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']]
79
90
 
80
91
  Song.with_any_tags('')
81
- => []
92
+ #=> []
82
93
 
83
94
  Song.with_any_genres('rock, rap')
84
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
95
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
85
96
  ```
97
+
86
98
  ### .without_all_#{column_name}
99
+
87
100
  ```ruby
88
101
  Song.without_all_tags('top')
89
- => []
102
+ #=> []
90
103
 
91
104
  Song.without_all_tags('top, 1990')
92
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
105
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
93
106
 
94
107
  Song.without_all_tags('')
95
- => []
108
+ #=> []
96
109
 
97
110
  Song.without_all_genres('rock, pop')
98
- => [#<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']]
99
112
 
100
113
  Song.without_all_genres('rock')
101
- => []
114
+ #=> []
102
115
  ```
103
116
 
104
117
  ### .without_any_#{column_name}
118
+
105
119
  ```ruby
106
120
  Song.without_any_tags('top, 1990')
107
- => []
121
+ #=> []
108
122
 
109
123
  Song.without_any_tags('1990, 1980')
110
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
124
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
111
125
 
112
126
  Song.without_any_genres('rock, pop')
113
- => []
127
+ #=> []
114
128
 
115
129
  Song.without_any_genres('')
116
- => []
130
+ #=> []
117
131
  ```
118
132
 
119
133
  ### .tagged_with
134
+
120
135
  ```ruby
121
136
  Song.tagged_with('top')
122
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
137
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
123
138
 
124
139
  Song.tagged_with('top, 1990')
125
- => []
140
+ #=> []
126
141
 
127
142
  Song.tagged_with('')
128
- => []
143
+ #=> []
129
144
 
130
145
  Song.tagged_with('rock')
131
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
146
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
132
147
 
133
148
  Song.tagged_with('rock', join_operator: Metka::And)
134
- => []
149
+ #=> []
135
150
 
136
151
  Song.tagged_with('chill', any: true)
137
- => [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
152
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
138
153
 
139
154
  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']]
155
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
141
156
 
142
157
  Song.tagged_with('', any: true)
143
- => []
158
+ #=> []
144
159
 
145
160
  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']]
161
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
147
162
 
148
163
  Song.without_all_tags('top')
149
- => []
164
+ #=> []
150
165
 
151
166
  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']]
167
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
153
168
 
154
169
  Song.tagged_with('', exclude: true)
155
- => []
170
+ #=> []
156
171
 
157
172
  Song.tagged_with('top, 1990', any: true, exclude: true)
158
- => []
173
+ #=> []
159
174
 
160
175
  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']]
176
+ #=> [#<Song id: 1, title: 'Migrate tags in Rails to PostgreSQL', tags: ['top', 'chill'], genres: ['rock', 'jazz', 'pop']]
162
177
 
163
178
  Song.without_any_genres('rock, pop')
164
- => []
179
+ #=> []
165
180
  ```
166
181
 
167
182
  ## Custom delimiter
183
+
168
184
  By default, a comma is used as a delimiter to create tags from a string.
169
185
  You can make your own custom separator:
186
+
170
187
  ```ruby
171
188
  Metka.config.delimiter = '|'
172
189
  parsed_data = Metka::GenericParser.instance.call('cool, data|I have')
173
190
  parsed_data.to_a
174
- =>['cool, data', 'I have']
191
+ #=>['cool, data', 'I have']
175
192
  ```
176
193
 
177
194
  ## Tags with quote
195
+
178
196
  ```ruby
179
197
  parsed_data = Metka::GenericParser.instance.call("'cool, data', code")
180
198
  parsed_data.to_a
181
- => ['cool, data', 'code']
199
+ #=> ['cool, data', 'code']
182
200
  ```
183
201
 
184
202
  ## Custom parser
203
+
185
204
  By default we use [generic_parser](lib/metka/generic_parser.rb "generic_parser")
186
205
  If you want to use your custom parser you can do:
206
+
187
207
  ```ruby
188
208
  class Song < ActiveRecord::Base
189
209
  include Metka::Model(columns: %w[genres tags], parser: Your::Custom::Parser.instance)
190
210
  end
191
211
  ```
212
+
192
213
  Custom parser must be a singleton class that has a `.call` method that accepts the tag string
193
214
 
194
215
  ## Tag Cloud Strategies
@@ -200,29 +221,30 @@ There are several strategies to get tag statistics
200
221
  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
222
 
202
223
  ```ruby
224
+
203
225
  class Book < ActiveRecord::Base
204
226
  include Metka::Model(column: 'authors')
205
227
  include Metka::Model(column: 'co_authors')
206
228
  end
207
229
 
208
230
  tag_cloud = Book.author_cloud
209
- => [["L.N. Tolstoy", 3], ["F.M. Dostoevsky", 6]]
231
+ #=> [["L.N. Tolstoy", 3], ["F.M. Dostoevsky", 6]]
210
232
  genre_cloud = Book.co_author_cloud
211
- => [["A.P. Chekhov", 5], ["N.V. Gogol", 8], ["L.N. Tolstoy", 2]]
233
+ #=> [["A.P. Chekhov", 5], ["N.V. Gogol", 8], ["L.N. Tolstoy", 2]]
212
234
  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]]
235
+ #=> [["L.N. Tolstoy", 5], ["F.M. Dostoevsky", 6], ["A.P. Chekhov", 5], ["N.V. Gogol", 8]]
214
236
  ```
215
237
 
216
238
  ### View Strategy
217
239
 
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.
240
+ 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
241
 
220
242
  ```bash
221
243
  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
244
  ```
223
245
 
224
246
  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.
247
+ 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
248
  `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
249
 
228
250
  Lets take a look at real example. We have a `notes` table with `tags` column.
@@ -290,7 +312,7 @@ Data about taggings will be aggregated in SQL Materialized View, that would be r
290
312
  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
313
  ```
292
314
 
293
- All of the options for that stategy's generation command are the same as for the View Strategy.
315
+ All of the options for that strategy's generation command are the same as for the View Strategy.
294
316
 
295
317
  The migration template can be seen [here](spec/dummy/db/migrate/06_create_tagged_materialized_view_posts_materialized_view.rb "here")
296
318
 
@@ -308,11 +330,10 @@ And you can also create `TaggedNote` model to work with the view as with a Rails
308
330
 
309
331
  ### Table Strategy with Triggers
310
332
 
311
-
312
-
313
333
  TBD
314
334
 
315
335
  ## Inspired by
336
+
316
337
  1. [ActsAsTaggableOn](https://github.com/mbleigh/acts-as-taggable-on)
317
338
  2. [ActsAsTaggableArrayOn](https://github.com/tmiyamon/acts-as-taggable-array-on)
318
339
  3. [TagColumns](https://github.com/hopsoft/tag_columns)
@@ -447,10 +468,11 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
447
468
 
448
469
  ## Contributing
449
470
 
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.
471
+ 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
472
 
452
473
  ## Credits
453
- ![JetRockets](https://jetrockets.pro/jetrockets-icons-black.png)
474
+
475
+ ![JetRockets](https://media.jetrockets.pro/jetrockets-white.png)
454
476
  Metka is maintained by [JetRockets](http://www.jetrockets.ru).
455
477
 
456
478
  ## License
@@ -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'
4
- gem 'activerecord', '~> 5.2'
3
+ gem 'rails', '~> 5.2'
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: '..'
@@ -1,6 +1,5 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem 'rails', '~>5.1'
4
- gem 'activerecord', '~> 5.1'
3
+ gem 'rails', github: 'rails/rails'
5
4
 
6
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
@@ -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|
@@ -10,11 +10,11 @@ module Metka
10
10
  def call(model, columns, tags, options)
11
11
  strategy = options_to_strategy(options)
12
12
 
13
- query = join(options[:join_operator]) do
13
+ query = join(options[:join_operator]) {
14
14
  columns.map do |column|
15
15
  build_query(strategy, model, column, tags)
16
16
  end
17
- end
17
+ }
18
18
 
19
19
  if options[:exclude].present?
20
20
  Arel::Nodes::Not.new(query)
@@ -25,7 +25,7 @@ module Metka
25
25
 
26
26
  private
27
27
 
28
- def options_to_strategy options
28
+ def options_to_strategy(options)
29
29
  if options[:any].present?
30
30
  AnyTagsQuery
31
31
  else
@@ -43,11 +43,13 @@ module Metka
43
43
  end
44
44
  end
45
45
 
46
- # @param nodes [Array<Arel::Node>, Arel::Node]
47
- # @return [Arel::Node]
46
+ # @param nodes [Array<Arel::Nodes::Node>, Arel::Nodes::Node]
47
+ # @return [Arel::Nodes::Node]
48
48
  def join_or(nodes)
49
+ node_base_klass = defined?(::Arel::Nodes::Node) ? ::Arel::Nodes::Node : ::Arel::Node
50
+
49
51
  case nodes
50
- when ::Arel::Node
52
+ when node_base_klass
51
53
  nodes
52
54
  when Array
53
55
  l, *r = nodes
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'singleton'
3
4
 
4
5
  module Metka
@@ -6,22 +7,42 @@ module Metka
6
7
  include Singleton
7
8
 
8
9
  def call(model, column_name, tag_list)
9
- column_cast = Arel::Nodes::NamedFunction.new(
10
- 'CAST',
11
- [model.arel_table[column_name].as('text[]')]
12
- )
13
-
14
- value = Arel::Nodes::SqlLiteral.new(
15
- # In Rails 5.2 and above Sanitanization moved to public level, but still we have to support 4.2 and 5.0 and 5.1
16
- ActiveRecord::Base.send(:sanitize_sql_for_conditions, ['ARRAY[?]', tag_list.to_a])
17
- )
18
-
19
- value_cast = Arel::Nodes::NamedFunction.new(
20
- 'CAST',
21
- [value.as('text[]')]
22
- )
23
-
24
- Arel::Nodes::InfixOperation.new(infix_operator, column_cast, value_cast)
10
+ tags = tag_list.to_a
11
+
12
+ if tags.one?
13
+ value = Arel::Nodes::SqlLiteral.new(
14
+ ActiveRecord::Base.sanitize_sql_for_conditions(['?', tags.first])
15
+ )
16
+
17
+ column_cast = Arel::Nodes::NamedFunction.new(
18
+ 'ANY',
19
+ [model.arel_table[column_name]]
20
+ )
21
+
22
+ Arel::Nodes::Equality.new(value, column_cast)
23
+ else
24
+ value = Arel::Nodes::SqlLiteral.new(
25
+ ActiveRecord::Base.sanitize_sql_for_conditions(['ARRAY[?]::varchar[]', tags])
26
+ )
27
+
28
+ Arel::Nodes::InfixOperation.new(infix_operator, model.arel_table[column_name], value)
29
+ end
30
+ # column_cast = Arel::Nodes::NamedFunction.new(
31
+ # 'CAST',
32
+ # [model.arel_table[column_name].as('text[]')]
33
+ # )
34
+
35
+ # value = Arel::Nodes::SqlLiteral.new(
36
+ # ActiveRecord::Base.sanitize_sql_for_conditions(['ARRAY[?]::varchar[]', tag_list.to_a])
37
+ # )
38
+
39
+ # value_cast = Arel::Nodes::NamedFunction.new(
40
+ # 'CAST',
41
+ # [value.as('text[]')]
42
+ # )
43
+
44
+ # # Arel::Nodes::InfixOperation.new(infix_operator, column_cast, value_cast)
45
+ # Arel::Nodes::InfixOperation.new(infix_operator, model.arel_table[column_name], value)
25
46
  end
26
47
  end
27
48
  end