togglefy 1.1.1 → 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 +4 -4
- data/README.md +42 -8
- data/Rakefile +12 -0
- data/app/models/togglefy/feature.rb +7 -5
- data/app/models/togglefy/feature_assignment.rb +3 -1
- data/lib/generators/togglefy/install_generator.rb +3 -1
- data/lib/generators/togglefy/templates/create_feature_assignments.rb +3 -2
- data/lib/togglefy/assignable.rb +13 -10
- data/lib/togglefy/engine.rb +3 -1
- data/lib/togglefy/errors/assignables_not_found.rb +3 -1
- data/lib/togglefy/errors/bulk_toggle_failed.rb +3 -1
- data/lib/togglefy/errors/dependency_missing.rb +3 -1
- data/lib/togglefy/errors/error.rb +3 -1
- data/lib/togglefy/errors/feature_not_found.rb +3 -1
- data/lib/togglefy/errors/invalid_feature_attribute.rb +3 -1
- data/lib/togglefy/exceptions.rb +3 -1
- data/lib/togglefy/feature_assignable_manager.rb +2 -0
- data/lib/togglefy/feature_manager.rb +3 -1
- data/lib/togglefy/feature_query.rb +20 -8
- data/lib/togglefy/featureable.rb +3 -1
- data/lib/togglefy/scoped_bulk_wrapper.rb +3 -1
- data/lib/togglefy/services/bulk_toggler.rb +67 -66
- data/lib/togglefy/version.rb +1 -1
- data/lib/togglefy.rb +13 -13
- data/togglefy.gemspec +10 -4
- metadata +74 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5938d2ca0587fdf06293a3e2da8ad72bb6b7c642eab6a6f12d80f51d963bc3d
|
4
|
+
data.tar.gz: eab43dc22d9a8d0be5566fe2ac81c710d95a6e42972a46073e2e8e390262d894
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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:
|
@@ -458,8 +458,8 @@ You can use either, as long as you respect the rules listed.
|
|
458
458
|
| `without_group` | `without_role` | Can't be used if doing a direct `Togglefy::Feature` |
|
459
459
|
| `for_environment` | `for_env` | Can't be used if doing a direct `Togglefy::Feature` |
|
460
460
|
| `without_environment` | `without_env` | Can't be used if doing a direct `Togglefy::Feature` |
|
461
|
-
| `group`
|
462
|
-
| `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 |
|
463
463
|
| `create` | `create_feature` | None |
|
464
464
|
| `update` | `update_feature` | None |
|
465
465
|
| `toggle` | `toggle_feature` | None |
|
@@ -469,16 +469,50 @@ You can use either, as long as you respect the rules listed.
|
|
469
469
|
|
470
470
|
|
471
471
|
## Development
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
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
|
476
500
|
|
477
501
|
## Contributing
|
478
502
|
|
479
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).
|
480
504
|
|
481
|
-
|
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.
|
482
516
|
|
483
517
|
## License
|
484
518
|
|
data/Rakefile
ADDED
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Togglefy
|
2
4
|
class Feature < ApplicationRecord
|
3
|
-
enum :status, [
|
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 =
|
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(
|
13
|
+
def self.next_migration_number(_path)
|
12
14
|
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
13
15
|
end
|
14
16
|
|
@@ -9,6 +9,7 @@ class CreateTogglefyFeatureAssignments < ActiveRecord::Migration[rails_version]
|
|
9
9
|
t.references :assignable, polymorphic: true, null: false
|
10
10
|
t.timestamps
|
11
11
|
end
|
12
|
-
add_index :togglefy_feature_assignments, [
|
12
|
+
add_index :togglefy_feature_assignments, %i[feature_id assignable_type assignable_id], unique: true,
|
13
|
+
name: "index_togglefy_assignments_uniqueness"
|
13
14
|
end
|
14
|
-
end
|
15
|
+
end
|
data/lib/togglefy/assignable.rb
CHANGED
@@ -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,
|
13
|
+
scope :with_features, lambda { |feature_ids|
|
12
14
|
joins(:feature_assignments)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
.where(feature_assignments: {
|
16
|
+
feature_id: feature_ids
|
17
|
+
})
|
18
|
+
.distinct
|
17
19
|
}
|
18
20
|
|
19
|
-
scope :without_features,
|
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
|
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 =
|
55
|
-
type =
|
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
|
data/lib/togglefy/engine.rb
CHANGED
data/lib/togglefy/exceptions.rb
CHANGED
@@ -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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
.
|
51
|
-
|
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
|
data/lib/togglefy/featureable.rb
CHANGED
@@ -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 =
|
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 =
|
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
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
66
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
data/lib/togglefy/version.rb
CHANGED
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
|
-
|
99
|
-
|
98
|
+
alias for_role for_group
|
99
|
+
alias without_role without_group
|
100
100
|
|
101
|
-
|
102
|
-
|
101
|
+
alias for_env for_environment
|
102
|
+
alias without_env without_environment
|
103
103
|
|
104
104
|
# FeatureManager
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|
-
|
25
|
+
File.basename(__FILE__)
|
26
26
|
spec.files = Dir.glob("lib/**/*") +
|
27
|
-
|
28
|
-
|
29
|
-
|
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.
|
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-
|
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
|