no_fly_list 0.2.1 → 0.3.0

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: fddc142a9f89b7e7fae0c35c5285ffbdf1a68b0164ffcaf889ea70a572297933
4
- data.tar.gz: 6376fad323f9efbfaee941472ba977460dedc5a3a46e994df7a4bef2a8bb7d64
3
+ metadata.gz: da62f66e9694575999da6c6864650b05036fe0f32ed762255d4552e11fc53ce4
4
+ data.tar.gz: 965687001501fec670c74c1a89d95340776b3b8ffa061517d34c430439471572
5
5
  SHA512:
6
- metadata.gz: ec568b5205e74c5d856d07122d6325585c12416c33f65ee2852207fa17288f1676a09d2f0757c70a6f88a091510e9d9060f0cb7446ca8d493f3397ade1bd5020
7
- data.tar.gz: 76b620b9ce76b112229c770a5a2221bdacb25b9ccc5f85bfb95c77623d26dee7114967323f91dd9b5a4f896355ab0b27cbba948abfbd7effc19f4ed1d1156809
6
+ metadata.gz: 3c347ef635cb9c1adeb14df10b7ce8a6b6220104f93b0fc4b7debccf30c0537da86e232a4b62000fb3498253c8ae5535c5ca9ddb9290371d3afd4dd021c894ab
7
+ data.tar.gz: 3b1685788f672eadfe558f2bbceacdfd287dbcb865b7e2bbd8b718e710cf3870a575900bcae69452ebc9a720f8ca77c4c0f2b4488d56431e6c5a30946f4d630b
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails/generators'
4
- require 'rails/generators/active_record'
5
- require 'rails/generators/named_base'
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+ require "rails/generators/named_base"
6
6
 
7
7
  # Usage:
8
8
  # bin/rails generate no_fly_list:application_tag
@@ -11,15 +11,15 @@ module NoFlyList
11
11
  module Generators
12
12
  class InstallGenerator < Rails::Generators::Base
13
13
  include Rails::Generators::Migration
14
- source_root File.expand_path('templates', __dir__)
14
+ source_root File.expand_path("templates", __dir__)
15
15
 
16
- argument :connection_name, type: :string, desc: 'The name of the database connection', default: 'primary'
16
+ argument :connection_name, type: :string, desc: "The name of the database connection", default: "primary"
17
17
 
18
18
  def copy_application_tag
19
19
  ensure_connection_exists
20
- template 'application_tag.rb.erb', File.join('app/models', 'application_tag.rb')
21
- template 'application_tagging.rb.erb', File.join('app/models', 'application_tagging.rb')
22
- migration_template 'create_application_tagging_table.rb.erb', 'db/migrate/create_application_tagging_table.rb'
20
+ template "application_tag.rb.erb", File.join("app/models", "application_tag.rb")
21
+ template "application_tagging.rb.erb", File.join("app/models", "application_tagging.rb")
22
+ migration_template "create_application_tagging_table.rb.erb", "db/migrate/create_application_tagging_table.rb"
23
23
  end
24
24
 
25
25
  def self.next_migration_number(dirname)
@@ -1,20 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
- require 'rails/generators'
5
- require 'rails/generators/active_record'
6
- require 'rails/generators/named_base'
3
+ require "forwardable"
4
+ require "rails/generators"
5
+ require "rails/generators/active_record"
6
+ require "rails/generators/named_base"
7
7
 
8
8
  module NoFlyList
9
9
  module Generators
10
10
  class ModelsGenerator < Rails::Generators::NamedBase
11
- source_root File.expand_path('templates', __dir__)
11
+ source_root File.expand_path("templates", __dir__)
12
12
 
13
13
  def create_model_files
14
14
  return unless validate_model # Ensure it's an ActiveRecord model
15
15
 
16
- template 'tagging_model.rb.erb', File.join('app/models', class_path, "#{file_name.underscore}/tagging.rb")
17
- template 'tag_model.rb.erb', File.join('app/models', class_path, "#{file_name.underscore}_tag.rb")
16
+ template "tagging_model.rb.erb", File.join("app/models", class_path, "#{file_name.underscore}/tagging.rb")
17
+ template "tag_model.rb.erb", File.join("app/models", class_path, "#{file_name.underscore}_tag.rb")
18
18
  end
19
19
 
20
20
  private
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
- require 'rails/generators'
5
- require 'rails/generators/active_record'
6
- require 'rails/generators/named_base'
3
+ require "forwardable"
4
+ require "rails/generators"
5
+ require "rails/generators/active_record"
6
+ require "rails/generators/named_base"
7
7
 
8
8
  module NoFlyList
9
9
  module Generators
10
10
  class TaggingGenerator < Rails::Generators::NamedBase
11
11
  include ActiveRecord::Generators::Migration
12
12
 
13
- class_option :database, type: :string, default: 'primary',
14
- desc: 'Use different database for migration'
13
+ class_option :database, type: :string, default: "primary",
14
+ desc: "Use different database for migration"
15
15
 
16
16
  def self.default_generator_root
17
17
  File.dirname(__FILE__)
@@ -19,8 +19,8 @@ module NoFlyList
19
19
 
20
20
  def create_migration_file
21
21
  ensure_model_exists
22
- migration_template 'create_tagging_table.rb.erb',
23
- [db_migrate_path, "create_#{migration_name}.rb"].compact.join('/')
22
+ migration_template "create_tagging_table.rb.erb",
23
+ [ db_migrate_path, "create_#{migration_name}.rb" ].compact.join("/")
24
24
  end
25
25
 
26
26
  def self.next_migration_number(dirname)
@@ -18,6 +18,6 @@ module ApplicationTagTransformer
18
18
 
19
19
  # @return [String]
20
20
  def separator
21
- ','
21
+ ","
22
22
  end
23
23
  end
@@ -1,18 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'forwardable'
4
- require 'rails/generators'
5
- require 'rails/generators/active_record'
6
- require 'rails/generators/named_base'
3
+ require "forwardable"
4
+ require "rails/generators"
5
+ require "rails/generators/active_record"
6
+ require "rails/generators/named_base"
7
7
 
8
8
  unless defined?(ApplicationTagTransformer)
9
9
  module NoFlyList
10
10
  module Generators
11
11
  # bin/rails g no_fly_list:transformer
12
12
  class TransformerGenerator < Rails::Generators::Base
13
- source_root File.expand_path('templates', __dir__)
13
+ source_root File.expand_path("templates", __dir__)
14
14
  def create_tag_transformer_file
15
- template 'tag_transformer.rb', File.join('app/transformers', 'application_tag_transformer.rb')
15
+ template "tag_transformer.rb", File.join("app/transformers", "application_tag_transformer.rb")
16
16
  end
17
17
  end
18
18
  end
@@ -1,18 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_record/railtie'
4
- require 'rails'
3
+ require "active_record/railtie"
4
+ require "rails"
5
5
 
6
6
  module NoFlyList
7
7
  class Railtie < Rails::Railtie # :nodoc:
8
8
  config.no_fly_list = ActiveSupport::OrderedOptions.new
9
- config.no_fly_list.tag_class_name = 'ApplicationTag'
10
- config.no_fly_list.tag_table_name = 'application_tags'
11
- config.no_fly_list.tagging_class_name = 'ApplicationTagging'
12
- config.no_fly_list.tagging_table_name = 'application_taggings'
9
+ config.no_fly_list.tag_class_name = "ApplicationTag"
10
+ config.no_fly_list.tag_table_name = "application_tags"
11
+ config.no_fly_list.tagging_class_name = "ApplicationTagging"
12
+ config.no_fly_list.tagging_table_name = "application_taggings"
13
13
 
14
14
  rake_tasks do
15
- load 'no_fly_list/railties/tasks.rake'
15
+ load "no_fly_list/railties/tasks.rake"
16
16
  end
17
17
  end
18
18
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  namespace :no_fly_list do
4
- desc 'List all taggable records'
4
+ desc "List all taggable records"
5
5
  task taggable_records: :environment do
6
6
  Rails.application.eager_load!
7
7
  taggable_classes = ActiveRecord::Base.descendants.select do |klass|
8
- klass.included_modules.any? { |mod| mod.in?([NoFlyList::TaggableRecord]) }
8
+ klass.included_modules.any? { |mod| mod.in?([ NoFlyList::TaggableRecord ]) }
9
9
  end
10
10
 
11
11
  puts "Found #{taggable_classes.size} taggable classes:\n\n"
@@ -15,11 +15,11 @@ namespace :no_fly_list do
15
15
  end
16
16
  end
17
17
 
18
- desc 'List all tag records'
18
+ desc "List all tag records"
19
19
  task tag_records: :environment do
20
20
  Rails.application.eager_load!
21
21
  tag_classes = ActiveRecord::Base.descendants.select do |klass|
22
- klass.included_modules.any? { |mod| mod.in?([NoFlyList::ApplicationTag, NoFlyList::TagRecord]) }
22
+ klass.included_modules.any? { |mod| mod.in?([ NoFlyList::ApplicationTag, NoFlyList::TagRecord ]) }
23
23
  end
24
24
 
25
25
  puts "Found #{tag_classes.size} tag classes:\n\n"
@@ -29,11 +29,11 @@ namespace :no_fly_list do
29
29
  end
30
30
  end
31
31
 
32
- desc 'Check taggable records and their associated tables'
32
+ desc "Check taggable records and their associated tables"
33
33
  task check_taggable_records: :environment do
34
34
  Rails.application.eager_load!
35
35
  taggable_classes = ActiveRecord::Base.descendants.select do |klass|
36
- klass.included_modules.any? { |mod| mod.in?([NoFlyList::TaggableRecord]) }
36
+ klass.included_modules.any? { |mod| mod.in?([ NoFlyList::TaggableRecord ]) }
37
37
  end
38
38
 
39
39
  puts "Checking #{taggable_classes.size} taggable classes:\n\n"
@@ -32,9 +32,9 @@ module NoFlyList
32
32
 
33
33
  def determine_adapter
34
34
  case taggable_class.connection.adapter_name.downcase
35
- when 'postgresql'
35
+ when "postgresql"
36
36
  :postgresql
37
- when 'mysql2'
37
+ when "mysql2"
38
38
  :mysql
39
39
  else
40
40
  :sqlite
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'mutation'
4
- require_relative 'query'
5
- require_relative 'tag_setup'
3
+ require_relative "mutation"
4
+ require_relative "query"
5
+ require_relative "tag_setup"
6
6
 
7
7
  module NoFlyList
8
8
  module TaggableRecord
@@ -90,11 +90,11 @@ module NoFlyList
90
90
  # Add the basic associations
91
91
  belongs_to :tag,
92
92
  class_name: setup.tag_class_name,
93
- foreign_key: 'tag_id'
93
+ foreign_key: "tag_id"
94
94
 
95
95
  belongs_to :taggable,
96
96
  class_name: setup.taggable_klass.name,
97
- foreign_key: 'taggable_id'
97
+ foreign_key: "taggable_id"
98
98
 
99
99
  include NoFlyList::TaggingRecord
100
100
  end
@@ -118,12 +118,12 @@ module NoFlyList
118
118
  # Set up the tag model associations
119
119
  setup.tag_class_name.constantize.class_eval do
120
120
  # Fix: Use 'tagging' for the join association when context is 'tag'
121
- association_name = (singular_name == 'tag' ? :taggings : :"#{singular_name}_taggings")
121
+ association_name = (singular_name == "tag" ? :taggings : :"#{singular_name}_taggings")
122
122
 
123
123
  has_many association_name,
124
124
  -> { where(context: singular_name) },
125
125
  class_name: setup.tagging_class_name,
126
- foreign_key: 'tag_id',
126
+ foreign_key: "tag_id",
127
127
  dependent: :destroy
128
128
 
129
129
  # Fix: Use consistent naming for through association
@@ -137,7 +137,7 @@ module NoFlyList
137
137
  setup.tagging_class_name.constantize.class_eval do
138
138
  belongs_to :tag,
139
139
  class_name: setup.tag_class_name,
140
- foreign_key: 'tag_id'
140
+ foreign_key: "tag_id"
141
141
 
142
142
  belongs_to :taggable,
143
143
  polymorphic: true
@@ -149,7 +149,7 @@ module NoFlyList
149
149
 
150
150
  validates :tag_id, uniqueness: {
151
151
  scope: %i[taggable_type taggable_id context],
152
- message: 'has already been tagged on this record in this context'
152
+ message: "has already been tagged on this record in this context"
153
153
  }
154
154
  end
155
155
  end
@@ -161,7 +161,7 @@ module NoFlyList
161
161
  has_many :"#{singular_name}_taggings",
162
162
  -> { where(context: singular_name) },
163
163
  class_name: setup.tagging_class_name,
164
- foreign_key: 'tag_id',
164
+ foreign_key: "tag_id",
165
165
  dependent: :destroy
166
166
 
167
167
  has_many :"#{singular_name}_taggables",
@@ -173,17 +173,17 @@ module NoFlyList
173
173
  setup.tagging_class_name.constantize.class_eval do
174
174
  belongs_to :tag,
175
175
  class_name: setup.tag_class_name,
176
- foreign_key: 'tag_id'
176
+ foreign_key: "tag_id"
177
177
 
178
178
  # For local tags, we use a simple belongs_to without polymorphic
179
179
  belongs_to :taggable,
180
180
  class_name: setup.taggable_klass.name,
181
- foreign_key: 'taggable_id'
181
+ foreign_key: "taggable_id"
182
182
 
183
183
  validates :tag, :taggable, :context, presence: true
184
184
  validates :tag_id, uniqueness: {
185
185
  scope: %i[taggable_id context],
186
- message: 'has already been tagged on this record in this context'
186
+ message: "has already been tagged on this record in this context"
187
187
  }
188
188
  end
189
189
  end
@@ -196,7 +196,7 @@ module NoFlyList
196
196
  has_many :"#{singular_name}_taggings",
197
197
  -> { where(context: singular_name) },
198
198
  class_name: setup.tagging_class_name,
199
- foreign_key: 'taggable_id',
199
+ foreign_key: "taggable_id",
200
200
  as: :taggable,
201
201
  dependent: :destroy
202
202
 
@@ -217,7 +217,7 @@ module NoFlyList
217
217
  has_many :"#{singular_name}_taggings",
218
218
  -> { where(context: singular_name) },
219
219
  class_name: setup.tagging_class_name,
220
- foreign_key: 'taggable_id',
220
+ foreign_key: "taggable_id",
221
221
  dependent: :destroy
222
222
 
223
223
  has_many setup.context,
@@ -237,9 +237,9 @@ module NoFlyList
237
237
  define_method :create_and_set_proxy do |instance_variable_name, setup|
238
238
  tag_model = if setup.polymorphic
239
239
  setup.tag_class_name.constantize
240
- else
240
+ else
241
241
  self.class.const_get("#{self.class.name}Tag")
242
- end
242
+ end
243
243
 
244
244
  proxy = TaggingProxy.new(
245
245
  self,
@@ -298,9 +298,9 @@ module NoFlyList
298
298
  end
299
299
 
300
300
  def define_constant_in_namespace(const_name)
301
- parts = const_name.split('::')
301
+ parts = const_name.split("::")
302
302
  const_name = parts.pop
303
- namespace = parts.join('::').safe_constantize || Object
303
+ namespace = parts.join("::").safe_constantize || Object
304
304
  return if namespace.const_defined?(const_name, false)
305
305
 
306
306
  namespace.const_set(const_name, yield)
@@ -40,8 +40,8 @@ module NoFlyList
40
40
  return none if tags.empty?
41
41
 
42
42
  count_function = Arel::Nodes::NamedFunction.new(
43
- 'COUNT',
44
- [Arel::Nodes::NamedFunction.new('DISTINCT', [tag_table[:name]])]
43
+ "COUNT",
44
+ [ Arel::Nodes::NamedFunction.new("DISTINCT", [ tag_table[:name] ]) ]
45
45
  )
46
46
 
47
47
  query = Arel::SelectManager.new(self)
@@ -78,11 +78,11 @@ module NoFlyList
78
78
  .where(context: singular_name)
79
79
  .where(taggable_type: name)
80
80
  .select(:taggable_id)
81
- else
81
+ else
82
82
  setup.tagging_class_name.constantize
83
83
  .where(context: singular_name)
84
84
  .select(:taggable_id)
85
- end
85
+ end
86
86
 
87
87
  where("#{table_name}.#{primary_key} NOT IN (?)", subquery)
88
88
  }
@@ -95,8 +95,8 @@ module NoFlyList
95
95
  send("without_#{context}")
96
96
  else
97
97
  Arel::Nodes::NamedFunction.new(
98
- 'COUNT',
99
- [Arel::Nodes::NamedFunction.new('DISTINCT', [tag_table[:id]])]
98
+ "COUNT",
99
+ [ Arel::Nodes::NamedFunction.new("DISTINCT", [ tag_table[:id] ]) ]
100
100
  )
101
101
 
102
102
  # Build the query for records having exactly the tags
@@ -40,8 +40,8 @@ module NoFlyList
40
40
  return none if tags.empty?
41
41
 
42
42
  count_function = Arel::Nodes::NamedFunction.new(
43
- 'COUNT',
44
- [Arel::Nodes::NamedFunction.new('DISTINCT', [tag_table[:name]])]
43
+ "COUNT",
44
+ [ Arel::Nodes::NamedFunction.new("DISTINCT", [ tag_table[:name] ]) ]
45
45
  )
46
46
 
47
47
  query = Arel::SelectManager.new(self)
@@ -78,11 +78,11 @@ module NoFlyList
78
78
  .where(context: singular_name)
79
79
  .where(taggable_type: name)
80
80
  .select(:taggable_id)
81
- else
81
+ else
82
82
  setup.tagging_class_name.constantize
83
83
  .where(context: singular_name)
84
84
  .select(:taggable_id)
85
- end
85
+ end
86
86
 
87
87
  where.not(primary_key => subquery)
88
88
  }
@@ -95,8 +95,8 @@ module NoFlyList
95
95
  send("without_#{context}")
96
96
  else
97
97
  Arel::Nodes::NamedFunction.new(
98
- 'COUNT',
99
- [Arel::Nodes::NamedFunction.new('DISTINCT', [tag_table[:id]])]
98
+ "COUNT",
99
+ [ Arel::Nodes::NamedFunction.new("DISTINCT", [ tag_table[:id] ]) ]
100
100
  )
101
101
 
102
102
  # Build the query for records having exactly the tags
@@ -40,8 +40,8 @@ module NoFlyList
40
40
  return none if tags.empty?
41
41
 
42
42
  count_function = Arel::Nodes::NamedFunction.new(
43
- 'COUNT',
44
- [Arel::Nodes::NamedFunction.new('DISTINCT', [tag_table[:name]])]
43
+ "COUNT",
44
+ [ Arel::Nodes::NamedFunction.new("DISTINCT", [ tag_table[:name] ]) ]
45
45
  )
46
46
 
47
47
  query = Arel::SelectManager.new(self)
@@ -70,7 +70,7 @@ module NoFlyList
70
70
  .pluck("#{table_name}.id")
71
71
 
72
72
  # Handle empty tagged_ids explicitly for SQLite compatibility
73
- where("#{table_name}.id NOT IN (?)", tagged_ids.present? ? tagged_ids : [-1])
73
+ where("#{table_name}.id NOT IN (?)", tagged_ids.present? ? tagged_ids : [ -1 ])
74
74
  }
75
75
 
76
76
  # Find records without any tags
@@ -79,12 +79,12 @@ module NoFlyList
79
79
  setup.tagging_class_name.constantize
80
80
  .where(context: singular_name, taggable_type: name)
81
81
  .select(:taggable_id)
82
- else
82
+ else
83
83
  setup.tagging_class_name.constantize
84
84
  .where(context: singular_name)
85
85
  .select(:taggable_id)
86
- end
87
- where('id NOT IN (?)', subquery)
86
+ end
87
+ where("id NOT IN (?)", subquery)
88
88
  }
89
89
 
90
90
  # Find records with exactly these tags
@@ -95,8 +95,8 @@ module NoFlyList
95
95
  send("without_#{context}")
96
96
  else
97
97
  Arel::Nodes::NamedFunction.new(
98
- 'COUNT',
99
- [Arel::Nodes::NamedFunction.new('DISTINCT', [tag_table[:id]])]
98
+ "COUNT",
99
+ [ Arel::Nodes::NamedFunction.new("DISTINCT", [ tag_table[:id] ]) ]
100
100
  )
101
101
 
102
102
  # Build the query for records having exactly the tags
@@ -130,8 +130,8 @@ module NoFlyList
130
130
  send("without_#{context}")
131
131
  else
132
132
  Arel::Nodes::NamedFunction.new(
133
- 'COUNT',
134
- [Arel::Nodes::NamedFunction.new('DISTINCT', [tag_table[:id]])]
133
+ "COUNT",
134
+ [ Arel::Nodes::NamedFunction.new("DISTINCT", [ tag_table[:id] ]) ]
135
135
  )
136
136
 
137
137
  # Build the query for records having exactly the tags
@@ -23,9 +23,9 @@ module NoFlyList
23
23
 
24
24
  def determine_adapter
25
25
  case ActiveRecord::Base.connection.adapter_name.downcase
26
- when 'postgresql'
26
+ when "postgresql"
27
27
  :postgresql
28
- when 'mysql2'
28
+ when "mysql2"
29
29
  :mysql
30
30
  else
31
31
  :sqlite
@@ -12,6 +12,10 @@ module NoFlyList
12
12
  before_validation :validate_tag_proxies
13
13
  end
14
14
 
15
+ def changed_for_autosave?
16
+ super || tag_proxies_changed?
17
+ end
18
+
15
19
  private
16
20
 
17
21
  def validate_tag_proxies
@@ -66,6 +70,19 @@ module NoFlyList
66
70
  tag_contexts[context.to_sym]
67
71
  end
68
72
 
73
+ def tag_proxies_changed?
74
+ return false if @saving_proxies || @validating_proxies
75
+
76
+ instance_variables.any? do |var|
77
+ next unless var.to_s.match?(/_list_proxy$/)
78
+
79
+ proxy = instance_variable_get(var)
80
+ next if proxy.nil?
81
+
82
+ proxy.changed?
83
+ end
84
+ end
85
+
69
86
  class_methods do
70
87
  def has_tags(*contexts, **options)
71
88
  contexts.each do |context|
@@ -26,6 +26,10 @@ module NoFlyList
26
26
  @pending_changes = []
27
27
  end
28
28
 
29
+ def changed?
30
+ @pending_changes.present? && @pending_changes != current_list_from_database
31
+ end
32
+
29
33
  def method_missing(method_name, *args)
30
34
  if current_list.respond_to?(method_name)
31
35
  current_list.send(method_name, *args)
@@ -47,7 +51,7 @@ module NoFlyList
47
51
  end
48
52
 
49
53
  def coerce(other)
50
- [other, to_a]
54
+ [ other, to_a ]
51
55
  end
52
56
 
53
57
  def to_ary
@@ -65,7 +69,7 @@ module NoFlyList
65
69
  model.class.transaction do
66
70
  # Always save parent first if needed
67
71
  if model.new_record? && !model.save
68
- errors.add(:base, 'Failed to save parent record')
72
+ errors.add(:base, "Failed to save parent record")
69
73
  raise ActiveRecord::Rollback
70
74
  end
71
75
 
@@ -160,7 +164,9 @@ module NoFlyList
160
164
  end
161
165
 
162
166
  def remove(tag)
163
- @pending_changes = current_list - [tag.to_s.strip]
167
+ old_list = current_list.dup
168
+ @pending_changes = current_list - [ tag.to_s.strip ]
169
+ mark_record_dirty if @pending_changes != old_list
164
170
  self
165
171
  end
166
172
 
@@ -170,7 +176,9 @@ module NoFlyList
170
176
  end
171
177
 
172
178
  def clear
179
+ old_list = current_list.dup
173
180
  @pending_changes = []
181
+ mark_record_dirty if @pending_changes != old_list
174
182
  self
175
183
  end
176
184
 
@@ -194,6 +202,19 @@ module NoFlyList
194
202
 
195
203
  private
196
204
 
205
+ def current_list_from_database
206
+ if setup[:polymorphic]
207
+ tagging_table = setup[:tagging_class_name].tableize
208
+ @model.send(@context.to_s)
209
+ .joins("INNER JOIN #{tagging_table} ON #{tagging_table}.tag_id = tags.id")
210
+ .where("#{tagging_table}.taggable_type = ? AND #{tagging_table}.taggable_id = ?",
211
+ @model.class.name, @model.id)
212
+ .pluck(:name)
213
+ else
214
+ @model.send(@context.to_s).pluck(:name)
215
+ end
216
+ end
217
+
197
218
  def set_list(_context, value)
198
219
  @pending_changes = transformer.parse_tags(value)
199
220
  valid? # Just check validity without raising
@@ -221,7 +242,7 @@ module NoFlyList
221
242
 
222
243
  # Transform tags to lowercase for comparison
223
244
  normalized_changes = @pending_changes.map(&:downcase)
224
- existing_tags = @tag_model.where('LOWER(name) IN (?)', normalized_changes).pluck(:name)
245
+ existing_tags = @tag_model.where("LOWER(name) IN (?)", normalized_changes).pluck(:name)
225
246
  missing_tags = @pending_changes - existing_tags
226
247
 
227
248
  return unless missing_tags.any?
@@ -279,20 +300,21 @@ module NoFlyList
279
300
  def current_list
280
301
  if @pending_changes.any?
281
302
  @pending_changes
282
- elsif setup[:polymorphic]
283
- tagging_table = setup[:tagging_class_name].tableize
284
- @model.send(@context.to_s)
285
- .joins("INNER JOIN #{tagging_table} ON #{tagging_table}.tag_id = tags.id")
286
- .where("#{tagging_table}.taggable_type = ? AND #{tagging_table}.taggable_id = ?",
287
- @model.class.name, @model.id)
288
- .pluck(:name)
289
303
  else
290
- @model.send(@context.to_s).pluck(:name)
304
+ current_list_from_database
291
305
  end
292
306
  end
293
307
 
294
308
  def limit_reached?
295
309
  @limit && current_list.size >= @limit
296
310
  end
311
+
312
+ def mark_record_dirty
313
+ return unless model.respond_to?(:changed_attributes)
314
+
315
+ # We use a virtual attribute name based on the context
316
+ # This ensures the record is marked as changed when tags are modified
317
+ model.send(:attribute_will_change!, "#{context}_list")
318
+ end
297
319
  end
298
320
  end
@@ -45,9 +45,9 @@ module NoFlyList
45
45
  def assert_polymorphic_tag_classes_exist(tags_klass, tagging_klass)
46
46
  # Verify they include the correct modules
47
47
  assert tags_klass.include?(NoFlyList::ApplicationTag),
48
- 'Polymorphic Tag should include NoFlyList::ApplicationTag'
48
+ "Polymorphic Tag should include NoFlyList::ApplicationTag"
49
49
  assert tagging_klass.include?(NoFlyList::ApplicationTagging),
50
- 'Polymorphic Tagging should include NoFlyList::ApplicationTagging'
50
+ "Polymorphic Tagging should include NoFlyList::ApplicationTagging"
51
51
  end
52
52
 
53
53
  def assert_local_tag_classes_exist(klass, context)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NoFlyList
4
- VERSION = '0.2.1'
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/no_fly_list.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_record'
4
- require 'active_support'
5
- require 'active_support/rails'
6
- require 'active_support/core_ext/numeric/time'
7
- require_relative 'no_fly_list/version'
8
- require 'no_fly_list/railtie' if defined?(Rails)
3
+ require "active_record"
4
+ require "active_support"
5
+ require "active_support/rails"
6
+ require "active_support/core_ext/numeric/time"
7
+ require_relative "no_fly_list/version"
8
+ require "no_fly_list/railtie" if defined?(Rails)
9
9
 
10
10
  module NoFlyList
11
11
  extend ActiveSupport::Autoload
@@ -16,10 +16,10 @@ module NoFlyList
16
16
  # Common tagging tables
17
17
  autoload :TaggableRecord
18
18
 
19
- autoload_under 'taggable_record' do
19
+ autoload_under "taggable_record" do
20
20
  autoload :Configuration
21
21
  autoload :Config
22
- autoload_under 'taggable_record/query' do
22
+ autoload_under "taggable_record/query" do
23
23
  autoload :SqliteStrategy
24
24
  autoload :MysqlStrategy
25
25
  autoload :PostgresqlStrategy
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: no_fly_list
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih