togglefy 1.1.0 → 1.2.0

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: 2419d9b30bf9193f8262fb0437f128510be4b00a0556a0fb244cf6b316299bb5
4
- data.tar.gz: 8e1b0f85f9aedd05eb5880277f6657eee36e1c570a768f3a037b9a1a4137852c
3
+ metadata.gz: a5938d2ca0587fdf06293a3e2da8ad72bb6b7c642eab6a6f12d80f51d963bc3d
4
+ data.tar.gz: eab43dc22d9a8d0be5566fe2ac81c710d95a6e42972a46073e2e8e390262d894
5
5
  SHA512:
6
- metadata.gz: c40f79f61887796ac7e646c0db064fc4a90862e3eea7260597d10eb6cad57543378e7ed6ca4ef0fd8e51efdc8539147035501419de7007bc07d47c63da755d3d
7
- data.tar.gz: 9cb7c91cc395acc224d1fa19533e86d9c899b15e61c56f05e608f0dc74d2d9f1392e3f1bf78a9d92790d67440e0b001411a2309f983134ddfe555f6ad6e5d2a1
6
+ metadata.gz: 62cfb19a3d90fa016d451f5fa784a5ce549f8500e43bbd75eb59fa184c3dfb999f65c82eedc41b543830772a7a116287f8a8521b04c775d9f1cea93e66938b99
7
+ data.tar.gz: cdafbc45941cb93063cad62a4491fd87dc4714da4f71949b686bec1a850246a0d50a0680a4dbd5644c59f001924e01d917bc499a06063c753327121b00a94e26
data/README.md CHANGED
@@ -12,7 +12,7 @@ Togglefy is free, open source and you are welcome to help build it.
12
12
  Add the gem manually to your Gemfile:
13
13
 
14
14
  ```gemfile
15
- gem 'togglefy', '~> 1.0', '>= 1.1.0'
15
+ gem 'togglefy', '~> 1.0', '>= 1.1.1'
16
16
  ```
17
17
 
18
18
  Or install it and add to the application's Gemfile by executing:
@@ -37,7 +37,37 @@ After adding the gem to your project, you need to run the generate command to ad
37
37
  rails generate togglefy:install
38
38
  ```
39
39
 
40
- This command will create the migrations to create the tables inside your project. Please, don't remove/change anything that's there or Togglefy may not work as expected.
40
+ This command will create the migrations to create the tables inside your project.
41
+
42
+ If you use an older version of Rails (< 5), then the migration files don't need you to specify the version.
43
+
44
+ To fix this, you will have to manually go to the two migration files of Togglefy: `create_feature` and `create_feature_assignments` and do the following:
45
+
46
+ Change these lines from this:
47
+
48
+ ```ruby
49
+ rails_version = "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
50
+
51
+ class CreateTogglefyFeatures < ActiveRecord::Migration[rails_version]
52
+ ```
53
+
54
+ ```ruby
55
+ rails_version = "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
56
+
57
+ class CreateTogglefyFeatureAssignments < ActiveRecord::Migration[rails_version]
58
+ ```
59
+
60
+ To this:
61
+
62
+ ```ruby
63
+ class CreateTogglefyFeatures < ActiveRecord::Migration
64
+ ```
65
+
66
+ ```ruby
67
+ class CreateTogglefyFeatureAssignments < ActiveRecord::Migration
68
+ ```
69
+
70
+ Please, don't remove/change anything else that's there or Togglefy may not work as expected.
41
71
 
42
72
  Run the migration to create these in your datase:
43
73
  ```bash
@@ -428,8 +458,8 @@ You can use either, as long as you respect the rules listed.
428
458
  | `without_group` | `without_role` | Can't be used if doing a direct `Togglefy::Feature` |
429
459
  | `for_environment` | `for_env` | Can't be used if doing a direct `Togglefy::Feature` |
430
460
  | `without_environment` | `without_env` | Can't be used if doing a direct `Togglefy::Feature` |
431
- | `group` | `role` | Used inside methods that receives filters |
432
- | `environment` | `env` | Used inside methods that receives filters |
461
+ | `group` | `role` | Used inside methods that receives filters |
462
+ | `environment` | `env` | Used inside methods that receives filters |
433
463
  | `create` | `create_feature` | None |
434
464
  | `update` | `update_feature` | None |
435
465
  | `toggle` | `toggle_feature` | None |
@@ -439,16 +469,50 @@ You can use either, as long as you respect the rules listed.
439
469
 
440
470
 
441
471
  ## Development
442
-
443
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
444
-
445
- To install this gem onto your local machine, run `bundle exec rake install`.
472
+ ### Setup the environment
473
+ 1. Clone the repository
474
+ 2. Run `bin/setup` on the Gem's root directory to install dependencies and run the dummy Rails app migrations used for tests
475
+ 3. Create your branch and checkout to it
476
+
477
+ ### Running the tests
478
+ 1. Make sure that the dummy Rails app db and migrations were ran
479
+ 2. Run `bundle exec rspec` on the Gem's root directory to run all the tests
480
+ 3. If you want to specify a single file to run the tests: `bundle exec rspec path/to/spec/file.rb`
481
+ 4. If you want to specify a single test of a single file to run: `bundle exec spec path/to/spec/file.rb:42` where 42 represents the number of the line
482
+
483
+ ### Running RuboCop
484
+ 1. Make sure you're at the Gem's root directory
485
+ 2. Run `bundle exec rubocop` to run RuboCop on all files not ignored by the `.rubocop.yml` file
486
+ 3. Run `bundle exec rubocop app spec lib/something.rb` to run RuboCop on specific directories/files
487
+ 4. Run `bundle exec rubocop -a` to fix all the auto-correctable offenses listed by RuboCop
488
+
489
+ ### Other
490
+ 1. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
491
+
492
+ ### Use local Togglefy Gem with a Rails application
493
+ 1. Open the Gemfile of your Rails application
494
+ 2. Add the following: `gem "togglefy", path: "path/to/togglefy/directory"`
495
+ 3. Now you can test everything inside of your Rails application
496
+
497
+ #### If you make a change to the Togglefy's code and want to test it, make sure to:
498
+ 1. If you're running a Rails server: restart
499
+ 2. If you're running a Rails console: `reload!` or restart
446
500
 
447
501
  ## Contributing
448
502
 
449
503
  Bug reports and pull requests are welcome on GitHub at https://github.com/azeveco/togglefy. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/azeveco/togglefy/blob/master/CODE_OF_CONDUCT.md).
450
504
 
451
- There's a PR Template. Its use is highly encouraged.
505
+ * Where can I check for planned features but not started?
506
+ * You can check Togglefy's project here: https://github.com/users/azeveco/projects/2 to see the priorities, status and more
507
+ * Or you can check the issues: https://github.com/azeveco/Togglefy/issues
508
+ * I have an idea of a feature! What do I do?
509
+ * First things first, check if there's an issue about it first. If it does, put your comments there. If it doesn't, do the following:
510
+ * Are you a developer that wants to develop it? Create a new issue, select the New Feature 🚀 template and fill out everything
511
+ * Are you a developer or just an user that would like to request a new feature? Create a new issue, select the Feature Request 💡 template and fill out everything
512
+ * I have a bug report. Where can I... report it?
513
+ * Create an issue, select the Bug Report 🪲 template and fill out everything
514
+
515
+ There's a PR and Issues Templates. We recommend you to follow these strictly to help everyone.
452
516
 
453
517
  ## License
454
518
 
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new(:rubocop)
11
+
12
+ # task default: %i[spec rubocop]
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class Feature < ApplicationRecord
3
- enum :status, [ :inactive, :active ]
4
-
5
+ enum :status, %i[inactive active]
6
+
5
7
  has_many :feature_assignments, dependent: :destroy
6
8
  has_many :assignables, through: :feature_assignments, source: :assignable
7
9
 
8
- before_validation :build_identifier
10
+ before_validation :build_identifier, if: proc { |f| f.name.present? && f.identifier.blank? }
9
11
 
10
12
  scope :identifier, ->(identifier) { where(identifier:) }
11
13
 
@@ -27,7 +29,7 @@ module Togglefy
27
29
  private
28
30
 
29
31
  def build_identifier
30
- self.identifier = self.name.underscore.parameterize(separator: '_')
32
+ self.identifier = name.underscore.parameterize(separator: "_")
31
33
  end
32
34
  end
33
- end
35
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class FeatureAssignment < ApplicationRecord
3
5
  belongs_to :feature, class_name: "Togglefy::Feature"
@@ -5,4 +7,4 @@ module Togglefy
5
7
 
6
8
  scope :for_type, ->(klass) { where(assignable_type: klass.to_s) }
7
9
  end
8
- end
10
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "rails/generators"
2
4
  require "rails/generators/migration"
3
5
 
@@ -8,7 +10,7 @@ module Togglefy
8
10
 
9
11
  source_root File.expand_path("templates", __dir__)
10
12
 
11
- def self.next_migration_number(path)
13
+ def self.next_migration_number(_path)
12
14
  Time.now.utc.strftime("%Y%m%d%H%M%S")
13
15
  end
14
16
 
@@ -1,10 +1,15 @@
1
- class CreateTogglefyFeatureAssignments < ActiveRecord::Migration[8.0]
1
+ # frozen_string_literal: true
2
+
3
+ rails_version = "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
4
+
5
+ class CreateTogglefyFeatureAssignments < ActiveRecord::Migration[rails_version]
2
6
  def change
3
7
  create_table :togglefy_feature_assignments do |t|
4
8
  t.references :feature, null: false, foreign_key: { to_table: :togglefy_features }
5
9
  t.references :assignable, polymorphic: true, null: false
6
10
  t.timestamps
7
11
  end
8
- add_index :togglefy_feature_assignments, [:feature_id, :assignable_type, :assignable_id], unique: true, name: "index_togglefy_assignments_uniqueness"
12
+ add_index :togglefy_feature_assignments, %i[feature_id assignable_type assignable_id], unique: true,
13
+ name: "index_togglefy_assignments_uniqueness"
9
14
  end
10
- end
15
+ end
@@ -1,4 +1,8 @@
1
- class CreateTogglefyFeatures < ActiveRecord::Migration[8.0]
1
+ # frozen_string_literal: true
2
+
3
+ rails_version = "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
4
+
5
+ class CreateTogglefyFeatures < ActiveRecord::Migration[rails_version]
2
6
  def change
3
7
  create_table :togglefy_features do |t|
4
8
  t.string :name, null: false
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/concern"
2
4
 
3
5
  module Togglefy
@@ -8,24 +10,25 @@ module Togglefy
8
10
  has_many :feature_assignments, as: :assignable, class_name: "Togglefy::FeatureAssignment"
9
11
  has_many :features, through: :feature_assignments, class_name: "Togglefy::Feature"
10
12
 
11
- scope :with_features, ->(feature_ids) {
13
+ scope :with_features, lambda { |feature_ids|
12
14
  joins(:feature_assignments)
13
- .where(feature_assignments: {
14
- feature_id: feature_ids
15
- })
16
- .distinct
15
+ .where(feature_assignments: {
16
+ feature_id: feature_ids
17
+ })
18
+ .distinct
17
19
  }
18
20
 
19
- scope :without_features, ->(feature_ids) {
21
+ scope :without_features, lambda { |feature_ids|
20
22
  joins(left_join_on_features(feature_ids))
21
23
  .where("fa.id IS NULL")
22
24
  .distinct
23
25
  }
24
26
  end
25
27
 
26
- def has_feature?(identifier)
28
+ def feature?(identifier)
27
29
  features.exists?(identifier: identifier.to_s)
28
30
  end
31
+ alias has_feature? feature?
29
32
 
30
33
  def add_feature(feature)
31
34
  feature = find_feature!(feature)
@@ -51,8 +54,8 @@ module Togglefy
51
54
 
52
55
  class_methods do
53
56
  def left_join_on_features(feature_ids)
54
- table = self.table_name
55
- type = self.name
57
+ table = table_name
58
+ type = name
56
59
 
57
60
  <<~SQL.squish
58
61
  LEFT JOIN togglefy_feature_assignments fa
@@ -63,4 +66,4 @@ module Togglefy
63
66
  end
64
67
  end
65
68
  end
66
- end
69
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class Engine < ::Rails::Engine
3
5
  isolate_namespace Togglefy
4
6
  end
5
- end
7
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class AssignablesNotFound < Togglefy::Error
3
5
  def initialize(klass)
4
6
  super("No #{klass.name} found matching features and filters sent")
5
7
  end
6
8
  end
7
- end
9
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class BulkToggleFailed < Togglefy::Error
3
5
  def initialize(message = "Bulk toggle operation failed", cause = nil)
@@ -8,4 +10,4 @@ module Togglefy
8
10
 
9
11
  attr_reader :cause
10
12
  end
11
- end
13
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class DependencyMissing < Togglefy::Error
3
5
  def initialize(feature, required)
4
6
  super("Feature '#{feature}' is missing dependency: '#{required}'")
5
7
  end
6
8
  end
7
- end
9
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class Error < StandardError; end
3
- end
5
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class FeatureNotFound < Togglefy::Error
3
5
  def initialize
4
6
  super("No features found matching features and/or filters sent")
5
7
  end
6
8
  end
7
- end
9
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class InvalidFeatureAttribute < Togglefy::Error
3
5
  def initialize(attr)
4
6
  super("The attribute '#{attr}' is not valid for Togglefy::Feature.")
5
7
  end
6
8
  end
7
- end
9
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "togglefy/errors/error"
2
4
 
3
5
  require "togglefy/errors/feature_not_found"
4
6
  require "togglefy/errors/assignables_not_found"
5
- require "togglefy/errors/bulk_toggle_failed"
7
+ require "togglefy/errors/bulk_toggle_failed"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class FeatureAssignableManager
3
5
  def initialize(assignable)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class FeatureManager
3
5
  def initialize(identifier = nil)
@@ -38,4 +40,4 @@ module Togglefy
38
40
  Togglefy::Feature.find_by!(identifier:)
39
41
  end
40
42
  end
41
- end
43
+ end
@@ -1,5 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class FeatureQuery
5
+ FILTERS = {
6
+ identifier: :identifier,
7
+ group: :for_group,
8
+ role: :for_group,
9
+ environment: :for_environment,
10
+ env: :for_environment,
11
+ tenant_id: :for_tenant,
12
+ status: :with_status
13
+ }.freeze
14
+
3
15
  def features
4
16
  Togglefy::Feature.all
5
17
  end
@@ -43,14 +55,14 @@ module Togglefy
43
55
  end
44
56
 
45
57
  def for_filters(filters)
46
- Togglefy::Feature
47
- .then { |q| safe_chain(q, :identifier, filters[:identifier], apply_if: filters.key?(:identifier)) }
48
- .then { |q| safe_chain(q, :for_group, filters[:group] || filters[:role], apply_if: filters.key?(:group) || filters.key?(:role)) }
49
- .then { |q| safe_chain(q, :for_environment, filters[:environment] || filters[:env], apply_if: filters.key?(:environment) || filters.key?(:env)) }
50
- .then { |q| safe_chain(q, :for_tenant, filters[:tenant_id], apply_if: filters.key?(:tenant_id)) }
51
- .then { |q| safe_chain(q, :with_status, filters[:status], apply_if: filters.key?(:status)) }
58
+ FILTERS.reduce(Togglefy::Feature) do |query, (key, scope)|
59
+ value = filters[key]
60
+ next query unless filters.key?(key) && nil_or_not_blank?(value)
61
+
62
+ query.public_send(scope, value)
63
+ end
52
64
  end
53
-
65
+
54
66
  private
55
67
 
56
68
  def safe_chain(query, method, value, apply_if: true)
@@ -61,4 +73,4 @@ module Togglefy
61
73
  value.nil? || !value.blank?
62
74
  end
63
75
  end
64
- end
76
+ end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "togglefy/assignable"
2
4
 
3
5
  module Togglefy
4
6
  Featureable = Assignable
5
7
  warn "[DEPRECATION] `Togglefy::Featureable` is deprecated. Use `Togglefy::Assignable` instead."
6
- end
8
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "togglefy/services/bulk_toggler"
2
4
 
3
5
  module Togglefy
@@ -10,4 +12,4 @@ module Togglefy
10
12
  BulkToggler.new(@klass)
11
13
  end
12
14
  end
13
- end
15
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Togglefy
2
4
  class BulkToggler
3
5
  ALLOWED_ASSIGNABLE_FILTERS = %i[group role environment env tenant_id].freeze
@@ -20,80 +22,33 @@ module Togglefy
20
22
 
21
23
  def toggle(action, identifiers, filters)
22
24
  identifiers = Array(identifiers)
23
- features = Togglefy.for_filters(
24
- filters: {identifier: identifiers}.merge(build_scope_filters(filters))
25
- ).to_a
26
-
27
- raise Togglefy::FeatureNotFound if features.empty?
25
+ features = get_features(identifiers, filters)
28
26
 
29
27
  feature_ids = features.map(&:id)
30
28
 
31
- assignables = if action == :enable
32
- klass.without_features(feature_ids)
33
- else
34
- klass.with_features(feature_ids)
35
- end
29
+ assignables = get_assignables(action, feature_ids)
36
30
 
37
- raise Togglefy::AssignablesNotFound.new(klass, identifiers, filters) if assignables.empty?
38
-
39
31
  assignables = sample_assignables(assignables, filters[:percentage]) if filters[:percentage]
40
32
 
41
- existing_assignments = Togglefy::FeatureAssignment.where(
42
- assignable_id: assignables.map(&:id),
43
- assignable_type: klass.name,
44
- feature_id: features.map(&:id)
45
- ).pluck(:assignable_id, :feature_id)
46
-
47
- existing_lookup = Set.new(existing_assignments)
48
-
49
- if action == :enable
50
- rows = []
51
-
52
- assignables.each do |assignable|
53
- features.each do |feature|
54
- key = [assignable.id, feature.id]
55
- next if existing_lookup.include?(key)
56
-
57
- rows << {
58
- assignable_id: assignable.id,
59
- assignable_type: assignable.class.name,
60
- feature_id: feature.id
61
- }
62
- end
63
- end
33
+ enable_flow(assignables, features, identifiers) if action == :enable
34
+ disable_flow(assignables, features, identifiers) if action == :disable
35
+ end
64
36
 
65
- begin
66
- Togglefy::FeatureAssignment.insert_all(rows) if rows.any?
67
- rescue => error
68
- raise Togglefy::BulkToggleFailed.new(
69
- "Bulk toggle enable failed for #{klass.name} with identifiers #{identifiers.inspect}",
70
- error
71
- )
72
- end
73
- elsif action == :disable
74
- ids_to_remove = []
75
- assignables.each do |assignable|
76
- features.each do |feature|
77
- key = [assignable.id, feature.id]
78
- ids_to_remove << key if existing_lookup.include?(key)
79
- end
80
- end
37
+ def get_features(identifiers, filters)
38
+ features = Togglefy.for_filters(filters: { identifier: identifiers }.merge(build_scope_filters(filters))).to_a
81
39
 
82
- begin
83
- if ids_to_remove.any?
84
- Togglefy::FeatureAssignment.where(
85
- assignable_id: ids_to_remove.map(&:first),
86
- assignable_type: klass.name,
87
- feature_id: ids_to_remove.map(&:last)
88
- ).delete_all
89
- end
90
- rescue => error
91
- raise Togglefy::BulkToggleFailed.new(
92
- "Bulk toggle disable failed for #{klass.name} with identifiers #{identifiers.inspect}",
93
- error
94
- )
95
- end
96
- end
40
+ raise Togglefy::FeatureNotFound if features.empty?
41
+
42
+ features
43
+ end
44
+
45
+ def get_assignables(action, feature_ids)
46
+ assignables = klass.without_features(feature_ids) if action == :enable
47
+ assignables = klass.with_features(feature_ids) if action == :disable
48
+
49
+ raise Togglefy::AssignablesNotFound, klass if assignables.empty?
50
+
51
+ assignables
97
52
  end
98
53
 
99
54
  def build_scope_filters(filters)
@@ -104,5 +59,51 @@ module Togglefy
104
59
  count = (assignables.size * percentage.to_f / 100).round
105
60
  assignables.sample(count)
106
61
  end
62
+
63
+ def enable_flow(assignables, features, identifiers)
64
+ rows = []
65
+
66
+ assignables.each do |assignable|
67
+ features.each do |feature|
68
+ rows << { assignable_id: assignable.id, assignable_type: assignable.class.name, feature_id: feature.id }
69
+ end
70
+ end
71
+
72
+ mass_insert(rows, identifiers)
73
+ end
74
+
75
+ def mass_insert(rows, identifiers)
76
+ Togglefy::FeatureAssignment.insert_all(rows) if rows.any?
77
+ rescue Togglefy::Error => e
78
+ raise Togglefy::BulkToggleFailed.new(
79
+ "Bulk toggle enable failed for #{klass.name} with identifiers #{identifiers.inspect}",
80
+ e
81
+ )
82
+ end
83
+
84
+ def disable_flow(assignables, features, identifiers)
85
+ ids_to_remove = []
86
+
87
+ assignables.each do |assignable|
88
+ features.each do |feature|
89
+ ids_to_remove << [assignable.id, feature.id]
90
+ end
91
+ end
92
+
93
+ mass_delete(ids_to_remove, identifiers)
94
+ end
95
+
96
+ def mass_delete(ids_to_remove, identifiers)
97
+ if ids_to_remove.any?
98
+ Togglefy::FeatureAssignment.where(
99
+ assignable_id: ids_to_remove.map(&:first), assignable_type: klass.name, feature_id: ids_to_remove.map(&:last)
100
+ ).delete_all
101
+ end
102
+ rescue Togglefy::Error => e
103
+ raise Togglefy::BulkToggleFailed.new(
104
+ "Bulk toggle disable failed for #{klass.name} with identifiers #{identifiers.inspect}",
105
+ e
106
+ )
107
+ end
107
108
  end
108
109
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Togglefy
4
- VERSION = "1.1.0"
4
+ VERSION = "1.2.0"
5
5
  end
data/lib/togglefy.rb CHANGED
@@ -21,11 +21,11 @@ module Togglefy
21
21
  def self.feature(identifier)
22
22
  FeatureQuery.new.feature(identifier)
23
23
  end
24
-
24
+
25
25
  def self.for_type(klass)
26
26
  FeatureQuery.new.for_type(klass)
27
27
  end
28
-
28
+
29
29
  def self.for_group(group)
30
30
  FeatureQuery.new.for_group(group)
31
31
  end
@@ -93,20 +93,20 @@ module Togglefy
93
93
  Togglefy::ScopedBulkWrapper.new(klass)
94
94
  end
95
95
 
96
- class <<self
96
+ class << self
97
97
  # FeatureQuery
98
- alias_method :for_role, :for_group
99
- alias_method :without_role, :without_group
98
+ alias for_role for_group
99
+ alias without_role without_group
100
100
 
101
- alias_method :for_env, :for_environment
102
- alias_method :without_env, :without_environment
101
+ alias for_env for_environment
102
+ alias without_env without_environment
103
103
 
104
104
  # FeatureManager
105
- alias_method :create_feature, :create
106
- alias_method :update_feature, :update
107
- alias_method :toggle_feature, :toggle
108
- alias_method :activate_feature, :active!
109
- alias_method :inactivate_feature, :inactive!
110
- alias_method :destroy_feature, :destroy
105
+ alias create_feature create
106
+ alias update_feature update
107
+ alias toggle_feature toggle
108
+ alias activate_feature active!
109
+ alias inactivate_feature inactive!
110
+ alias destroy_feature destroy
111
111
  end
112
112
  end
data/togglefy.gemspec CHANGED
@@ -22,13 +22,19 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  # Specify which files should be added to the gem when it is released.
24
24
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
- gemspec = File.basename(__FILE__)
25
+ File.basename(__FILE__)
26
26
  spec.files = Dir.glob("lib/**/*") +
27
- Dir.glob("app/**/*") +
28
- Dir.glob("config/**/*") +
29
- %w[LICENSE.txt README.md togglefy.gemspec]
27
+ Dir.glob("app/**/*") +
28
+ Dir.glob("config/**/*") +
29
+ %w[LICENSE.txt README.md Rakefile togglefy.gemspec]
30
30
 
31
31
  spec.bindir = "exe"
32
32
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
33
33
  spec.require_paths = ["lib"]
34
+
35
+ spec.add_development_dependency "bootsnap", "~> 1.17"
36
+ spec.add_development_dependency "database_cleaner-active_record", "~> 2.1"
37
+ spec.add_development_dependency "rails", "~> 8.0.2"
38
+ spec.add_development_dependency "rspec-rails", "~> 7.1.1"
39
+ spec.add_development_dependency "sqlite3", "~> 2.1"
34
40
  end
metadata CHANGED
@@ -1,14 +1,84 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: togglefy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Azevedo
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-16 00:00:00.000000000 Z
11
- dependencies: []
10
+ date: 2025-04-29 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: bootsnap
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.17'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.17'
26
+ - !ruby/object:Gem::Dependency
27
+ name: database_cleaner-active_record
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.1'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.1'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rails
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 8.0.2
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 8.0.2
54
+ - !ruby/object:Gem::Dependency
55
+ name: rspec-rails
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 7.1.1
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 7.1.1
68
+ - !ruby/object:Gem::Dependency
69
+ name: sqlite3
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.1'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '2.1'
12
82
  description: Togglefy is a feature management Rails gem to help you control which
13
83
  features an user or a group has access to.
14
84
  email:
@@ -19,6 +89,7 @@ extra_rdoc_files: []
19
89
  files:
20
90
  - LICENSE.txt
21
91
  - README.md
92
+ - Rakefile
22
93
  - app/models/togglefy/feature.rb
23
94
  - app/models/togglefy/feature_assignment.rb
24
95
  - lib/generators/togglefy/install_generator.rb