cancannible 1.0.1 → 2.0.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
- SHA1:
3
- metadata.gz: c3d98cb08469d65e2ba20fb5d9d88d8d31f8bf8f
4
- data.tar.gz: e17d80f79eefe6a9ff5253a94534b1f250b89cdd
2
+ SHA256:
3
+ metadata.gz: 8ba63fd7b6b80a32a3bc93fbbe43845439c1eaffa9661e35510dbeff487af673
4
+ data.tar.gz: fdf8f225705b0e0fa9ea469674d62ce22b5340f48cb23fb94a2b8501112417cf
5
5
  SHA512:
6
- metadata.gz: 56c0011cd4ac973a6bf8d0eb9be3b910da3d52f4b27a0a4dd65e9405eafb435ac0b56b278dc88a0b3f07b98d227b2578e606135755d2245cf6b39059f27ff13e
7
- data.tar.gz: 342a7f8ea40329ab9e66390b504487e22cdee4fd50678b2af92a6407bc7e2439d6d3c70fa4b4f1cea34fb7c8317a3fd7f40332636d426e824b3e9005ff2045d5
6
+ metadata.gz: f9068c6dce19852c747512ddafa0a29461586128d67408bc5c53f07e029e8273d0cb343acb4400dcfd180afd6596202837fac699838f62d6e252a56dd35f99df
7
+ data.tar.gz: e5ec5d5accb0e40139dbeee9b6bc211d3652688c7ffb17c1788c86cea455c626914b233d4eb52de2786993989df8018d38ddfb07bef5bedb2f04484d43f62054
@@ -0,0 +1,34 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ '*' ]
13
+ pull_request:
14
+ branches: [ main ]
15
+
16
+ jobs:
17
+ test:
18
+
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ ruby-version: ['2.7', '3.0']
23
+
24
+ steps:
25
+ - uses: actions/checkout@v2
26
+ - name: Set up Ruby
27
+ uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
28
+ with:
29
+ ruby-version: ${{ matrix.ruby-version }}
30
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
31
+ - name: Install dependencies
32
+ run: bundle install
33
+ - name: Run tests
34
+ run: bundle exec rake
data/Guardfile CHANGED
@@ -1,18 +1,8 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
3
 
4
- # Note: The cmd option is now required due to the increasing number of ways
5
- # rspec may be run, below are examples of the most common uses.
6
- # * bundler: 'bundle exec rspec'
7
- # * bundler binstubs: 'bin/rspec'
8
- # * spring: 'bin/rsspec' (This will use spring if running and you have
9
- # installed the spring binstubs per the docs)
10
- # * zeus: 'zeus rspec' (requires the server to be started separetly)
11
- # * 'just' rspec: 'rspec'
12
- guard :rspec, cmd: 'bundle exec rspec' do
4
+ guard :rspec, cmd: 'bundle exec rspec', all_on_start: false, all_after_pass: false do
13
5
  watch(%r{^spec/.+_spec\.rb$})
14
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
6
+ watch(%r{^lib/cancannible/(.+)\.rb$}) { |m| "spec/unit/#{m[1]}_spec.rb" }
15
7
  watch('spec/spec_helper.rb') { "spec" }
16
-
17
8
  end
18
-
data/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # Cancannible
2
- [![Build Status](https://travis-ci.org/evendis/cancannible.svg?branch=master)](https://travis-ci.org/evendis/cancannible)
3
2
 
4
- Cancannible is a gem that extends [CanCan](https://rubygems.org/gems/cancan) with a range of capabilities:
3
+ Cancannible is a gem that extends [CanCanCan](https://github.com/CanCanCommunity/cancancan) with a range of capabilities:
5
4
 
6
5
  * database-persisted permissions
7
6
  * export CanCan methods to the model layer (so that permissions can be applied in model methods, and easily set in a test case)
@@ -16,13 +15,14 @@ Two demo applications are available (with source) that show cancannible in actio
16
15
  * [cancannibledemo4.evendis.com](http://cancannibledemo4.evendis.com) uses Rails 4.2.x
17
16
 
18
17
  ## Limitations
18
+
19
19
  Cancannible's origin was in a web application that's been in production for over 4 years.
20
20
  This gem is an initial refactoring as a separate component. It continues to be used in production, but
21
21
  there are some limitations and constraints that will ideally be removed or changed over time:
22
22
 
23
23
  * It only supports ActiveRecord for permissions storage (specifically, it has been tested with PostgreSQL and SQLite)
24
24
  * It currently assumes permissions are stored in a Permission model with a specific structure
25
- * It works with the [CanCan](https://github.com/ryanb/cancan) gem. It has not yet been tested with the new [CanCanCan](https://github.com/CanCanCommunity/cancancan) gem.
25
+ * It works with the [CanCanCan](https://github.com/CanCanCommunity/cancancan) gem.
26
26
  * It assumes your CanCan rules are setup with the default `Ability` class
27
27
 
28
28
 
data/Rakefile CHANGED
@@ -1,6 +1,5 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
- require 'appraisal'
4
3
 
5
4
  RSpec::Core::RakeTask.new(:spec)
6
5
 
data/cancannible.gemspec CHANGED
@@ -18,20 +18,17 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_runtime_dependency "activesupport", ">= 3.2.1", "< 5.0"
22
- spec.add_runtime_dependency "activemodel", ">= 3.2.1", "< 5.0"
23
- spec.add_runtime_dependency "cancan", "~> 1.6"
21
+ spec.add_runtime_dependency "activesupport", "~> 6.1"
22
+ spec.add_runtime_dependency "activemodel", "~> 6.1"
23
+ spec.add_runtime_dependency "cancancan"
24
24
 
25
- spec.add_development_dependency "activerecord", ">= 3.2.1", "< 5.0"
26
- spec.add_development_dependency "sqlite3", "~> 1.3"
27
- spec.add_development_dependency "bundler", "~> 1.6"
28
- spec.add_development_dependency "rake", "~> 10.0"
29
- spec.add_development_dependency "rspec", "~> 3.2"
30
- spec.add_development_dependency "appraisal"
25
+ spec.add_development_dependency "activerecord", "~> 6.1"
26
+ spec.add_development_dependency "sqlite3", ">= 1.3.2"
31
27
 
32
- # guard versions are pegged to avoid issue with ruby_dep requires Ruby version >= 2.2.5, ~> 2.2.
33
- spec.add_development_dependency "guard-rspec", "4.6.4"
34
- spec.add_development_dependency "rb-fsevent", "0.9.6"
35
- spec.add_development_dependency "rb-inotify", "0.9.5"
36
- spec.add_development_dependency "pry-coolline", "0.2.5" # avoid readline dependency
28
+ spec.add_development_dependency "bundler"
29
+ spec.add_development_dependency "rake"
30
+ spec.add_development_dependency "rdoc"
31
+ spec.add_development_dependency "rspec"
32
+ spec.add_development_dependency "guard-rspec"
33
+ spec.add_development_dependency "rb-fsevent"
37
34
  end
@@ -1,5 +1,4 @@
1
1
  module Cancannible
2
-
3
2
  mattr_accessor :refinements
4
3
  mattr_accessor :get_cached_abilities
5
4
  mattr_accessor :store_cached_abilities
@@ -24,5 +23,4 @@ module Cancannible
24
23
  self.refinements[stage] ||= []
25
24
  self.refinements[stage] << refinement
26
25
  end
27
-
28
- end
26
+ end
@@ -35,16 +35,13 @@ module Cancannible::Grantee
35
35
  permission
36
36
  end
37
37
  end
38
-
39
38
  end
40
39
 
41
40
  module ClassMethods
42
-
43
41
  # Command: configures the set of associations (array of symbols) from which permissions should be inherited
44
42
  def inherit_permissions_from(*relations)
45
43
  self.inheritable_permissions = relations
46
44
  end
47
-
48
45
  end
49
46
 
50
47
  # Returns the Ability set for the owner.
@@ -53,7 +50,13 @@ module Cancannible::Grantee
53
50
  @abilities = if refresh
54
51
  nil
55
52
  elsif Cancannible.get_cached_abilities.respond_to?(:call)
56
- Cancannible.get_cached_abilities.call(self)
53
+ result = Cancannible.get_cached_abilities.call(self)
54
+ if result
55
+ # performs a crude compatibility check
56
+ rules_size = result.send(:rules).size rescue nil
57
+ rules_index_size = (result.instance_variable_get(:@rules_index) || []).size
58
+ result if !rules_size.nil? && rules_index_size == rules_size
59
+ end
57
60
  end
58
61
  return @abilities if @abilities
59
62
 
@@ -64,7 +67,7 @@ module Cancannible::Grantee
64
67
  ability_class.new(self)
65
68
  end
66
69
 
67
- Cancannible.store_cached_abilities.call(self,@abilities) if Cancannible.store_cached_abilities.respond_to?(:call)
70
+ Cancannible.store_cached_abilities.call(self, @abilities) if Cancannible.store_cached_abilities.respond_to?(:call)
68
71
  @abilities
69
72
  end
70
73
 
@@ -98,10 +101,8 @@ module Cancannible::Grantee
98
101
  def cannot(ability, resource)
99
102
  permissions << [ability, resource, false]
100
103
  end
101
-
102
104
  end
103
105
 
104
-
105
106
  module Cancannible
106
107
  # This module is automatically included into all controllers.
107
108
  # It overrides some CanCan ControllerAdditions
@@ -116,7 +117,6 @@ module Cancannible
116
117
  end
117
118
  end
118
119
 
119
-
120
120
  if defined? ActionController::Base
121
121
  ActionController::Base.class_eval do
122
122
  include Cancannible::ControllerAdditions
@@ -2,14 +2,11 @@ module Cancannible::PreloadAdapter
2
2
  extend ActiveSupport::Concern
3
3
 
4
4
  included do
5
-
6
5
  # Tap Ability.new to first preload permissions via Cancannible
7
6
  alias_method :cancan_initialize, :initialize
8
7
  def initialize(user)
9
- Cancannible::Preloader.preload_abilities!(user,self)
8
+ Cancannible::Preloader.preload_abilities!(user, self)
10
9
  cancan_initialize(user)
11
10
  end
12
-
13
11
  end
14
-
15
- end
12
+ end
@@ -1,19 +1,19 @@
1
1
  class Cancannible::Preloader
2
-
3
- def self.preload_abilities!(grantee,cancan_ability_object)
4
- new(grantee,cancan_ability_object).preload!
2
+ def self.preload_abilities!(grantee, cancan_ability_object)
3
+ new(grantee, cancan_ability_object).preload!
5
4
  end
6
5
 
7
6
  attr_accessor :grantee
8
7
  attr_accessor :cancan_ability_object
9
8
 
10
- def initialize(grantee,cancan_ability_object)
9
+ def initialize(grantee, cancan_ability_object)
11
10
  self.grantee = grantee
12
11
  self.cancan_ability_object = cancan_ability_object
13
12
  end
14
13
 
15
14
  def preload!
16
15
  return unless grantee.respond_to?(:inherited_permissions)
16
+
17
17
  # load inherited permissions to CanCan Abilities
18
18
  preload_abilities_from_permissions(grantee.inherited_permissions)
19
19
  # load user-based permissions from database to CanCan Abilities
@@ -39,17 +39,15 @@ class Cancannible::Preloader
39
39
  end
40
40
 
41
41
  if permission.resource_id.nil?
42
-
43
42
  if action == :cannot
44
43
  # apply generic unrestricted permission to the class
45
- cancan_ability_object.send( action, ability, resource_type )
44
+ cancan_ability_object.send(action, ability, resource_type)
46
45
  else
47
-
48
46
  refinements = resolve_resource_refinements(ability,model_resource)
49
47
 
50
48
  if refinements.empty?
51
49
  # apply generic unrestricted permission to the class
52
- cancan_ability_object.send( action, ability, resource_type )
50
+ cancan_ability_object.send(action, ability, resource_type)
53
51
  else
54
52
  secondary_refinements = resolve_resource_refinements(ability,model_resource,2).presence || [{}]
55
53
  refinements.each do |refinement|
@@ -58,25 +56,22 @@ class Cancannible::Preloader
58
56
  end
59
57
  end
60
58
  end
61
-
62
59
  end
63
-
64
60
  elsif resource_type.find_by_id(permission.resource_id)
65
61
  cancan_ability_object.send( action, ability, resource_type, id: permission.resource_id)
66
62
  end
67
-
68
63
  end
69
64
  end
70
65
 
71
66
  def resolve_resource_type(given_resource_type)
72
67
  model_resource = nil
73
68
  resource_type = given_resource_type
74
- resource_type = resource_type==resource_type.downcase ? resource_type.to_sym : resource_type.constantize rescue nil
69
+ resource_type = resource_type == resource_type.downcase ? resource_type.to_sym : resource_type.constantize rescue nil
75
70
  model_resource = resource_type.respond_to?(:new) ? resource_type.new : resource_type rescue nil
76
71
  [resource_type,model_resource]
77
72
  end
78
73
 
79
- def resolve_resource_refinements(ability,model_resource,stage=1)
74
+ def resolve_resource_refinements(ability, model_resource, stage=1)
80
75
  Array(Cancannible.refinements[stage-1]).each_with_object([]) do |refinement,memo|
81
76
  refinement_attributes = refinement.dup
82
77
 
@@ -111,5 +106,4 @@ class Cancannible::Preloader
111
106
  memo.push(restriction) if restriction.present?
112
107
  end
113
108
  end
114
-
115
- end
109
+ end
@@ -1,3 +1,3 @@
1
1
  module Cancannible
2
- VERSION = "1.0.1"
2
+ VERSION = '2.0.0'
3
3
  end
data/lib/cancannible.rb CHANGED
@@ -2,8 +2,8 @@ require 'active_support'
2
2
  require 'active_support/core_ext'
3
3
  require 'cancan'
4
4
 
5
- require "cancannible/version"
6
- require "cancannible/config"
7
- require "cancannible/preload_adapter"
8
- require "cancannible/preloader"
9
- require "cancannible/grantee"
5
+ require 'cancannible/version'
6
+ require 'cancannible/config'
7
+ require 'cancannible/preload_adapter'
8
+ require 'cancannible/preloader'
9
+ require 'cancannible/grantee'
@@ -34,6 +34,5 @@ module Cancannible
34
34
  end
35
35
  end
36
36
  end
37
-
38
37
  end
39
38
  end
@@ -1,5 +1,4 @@
1
1
  Cancannible.setup do |config|
2
-
3
2
  # ABILITY CACHING
4
3
  # ===============
5
4
  # Cancannible supports optional ability caching. This can provide a significant performance
@@ -100,5 +99,4 @@ Cancannible.setup do |config|
100
99
  #
101
100
  # By default, access refinements are "stage 1" i.e. applied directly to the permissions being loaded.
102
101
  # By specifying stage 2, this refinement is applied on top of all stage 1 refinements (if possible / applicable)
103
-
104
102
  end
@@ -1,4 +1,4 @@
1
- class CreateCancanniblePermissions < ActiveRecord::Migration
1
+ class CreateCancanniblePermissions < ActiveRecord::Migration[6.1]
2
2
  def change
3
3
  create_table :permissions, force: true do |table|
4
4
  table.integer :permissible_id
@@ -1,13 +1,12 @@
1
1
  # The Permission class stores permissions managed by CanCan and Cancannible
2
2
  class Permission < ActiveRecord::Base
3
3
  belongs_to :permissible, polymorphic: true
4
- belongs_to :resource, polymorphic: true
4
+ belongs_to :resource, polymorphic: true, optional: true
5
+
6
+ validates :ability, uniqueness: { scope: [:resource_id, :resource_type, :permissible_id, :permissible_type] }
5
7
 
6
8
  # Note: for Rails 3 you may need to declare attr_accessible as follows, depending on your whitelist_attributes setting.
7
9
  # A future version of cancannible should make this unnecessary.
8
10
  #
9
11
  # attr_accessible :asserted, :ability, :resource_id, :resource_type
10
-
11
- validates_uniqueness_of :ability, scope: [:resource_id, :resource_type, :permissible_id, :permissible_type]
12
-
13
- end
12
+ end
data/spec/spec_helper.rb CHANGED
@@ -13,4 +13,4 @@ RSpec.configure do |config|
13
13
  Cancannible.reset!
14
14
  run_migrations
15
15
  end
16
- end
16
+ end
@@ -1,5 +1,4 @@
1
1
  module MigrationsHelper
2
-
3
2
  def run_migrations
4
3
  ActiveRecord::Base.establish_connection({
5
4
  adapter: 'sqlite3',
@@ -8,7 +7,6 @@ module MigrationsHelper
8
7
 
9
8
  ActiveRecord::Migration.suppress_messages do
10
9
  ActiveRecord::Schema.define(:version => 0) do
11
-
12
10
  create_table "members", :force => true do |t|
13
11
  t.string "name"
14
12
  t.string "email"
@@ -49,13 +47,11 @@ module MigrationsHelper
49
47
  t.string "name"
50
48
  t.integer "category_id"
51
49
  end
52
-
53
50
  end
54
51
  end
55
52
  end
56
-
57
53
  end
58
54
 
59
55
  RSpec.configure do |conf|
60
56
  conf.include MigrationsHelper
61
- end
57
+ end
@@ -1,13 +1,10 @@
1
1
  # These model definitions are just used for the test scenarios
2
2
 
3
- # The Permission class stores permissions maanged by CanCan and Cancannible
4
3
  class Permission < ActiveRecord::Base
5
4
  belongs_to :permissible, polymorphic: true
6
- belongs_to :resource, polymorphic: true
5
+ belongs_to :resource, polymorphic: true, optional: true
7
6
 
8
- validates_uniqueness_of :ability,
9
- :scope => [:resource_id, :resource_type,
10
- :permissible_id, :permissible_type]
7
+ validates :ability, uniqueness: { scope: [:resource_id, :resource_type, :permissible_id, :permissible_type] }
11
8
  end
12
9
 
13
10
  class Member < ActiveRecord::Base
@@ -3,29 +3,46 @@ require 'spec_helper'
3
3
  describe Cancannible do
4
4
  let(:grantee_class) { Member }
5
5
  let(:grantee) { grantee_class.create! }
6
+ let(:cached_object) do
7
+ abilities = Ability.new(grantee)
8
+ abilities.can :read, :all
9
+ abilities
10
+ end
6
11
 
7
12
  describe "#abilities" do
8
13
  subject { grantee.abilities }
9
14
 
10
15
  context "when get_cached_abilities provided" do
11
16
  before do
12
- Cancannible.get_cached_abilities = proc{|grantee| "get_cached_abilities for #{grantee.id}" }
17
+ Cancannible.get_cached_abilities = proc { |grantee| cached_object }
18
+ end
19
+
20
+ it "returns the cached object" do
21
+ expect(cached_object.instance_variable_defined?(:@rules_index)).to eql(true)
22
+ expect(subject).to eql(cached_object)
13
23
  end
14
- it "should returned the cached object" do
15
- should eql("get_cached_abilities for #{grantee.id}")
24
+ context 'when incompatible cached_object' do
25
+ let(:cached_object) { 'bogative' }
26
+ it 'returns a new object' do
27
+ expect(subject).to be_an(Ability)
28
+ expect(subject).to_not eql(cached_object)
29
+ end
16
30
  end
17
31
  context "unless reload requested" do
18
32
  subject { grantee.abilities(true) }
19
- it { should be_an(Ability) }
33
+ it 'returns a new object' do
34
+ expect(subject).to be_an(Ability)
35
+ expect(subject).to_not eql(cached_object)
36
+ end
20
37
  end
21
38
  end
22
39
 
23
40
  context "when store_cached_abilities provided" do
24
41
  before do
25
42
  @stored = nil
26
- Cancannible.store_cached_abilities = proc{ |grantee,ability| @stored = { grantee_id: grantee.id, ability: ability } }
43
+ Cancannible.store_cached_abilities = proc { |grantee, ability| @stored = { grantee_id: grantee.id, ability: ability } }
27
44
  end
28
- it "should store the cached object" do
45
+ it "stores the cached object" do
29
46
  expect { subject }.to change { @stored }.from(nil)
30
47
  expect(@stored[:grantee_id]).to eql(grantee.id)
31
48
  expect(@stored[:ability]).to be_an(Ability)
@@ -36,32 +53,29 @@ describe Cancannible do
36
53
  before do
37
54
  @stored = nil
38
55
  @store = 0
39
- Cancannible.get_cached_abilities = proc{|grantee| @stored }
40
- Cancannible.store_cached_abilities = proc{ |grantee,ability| @store += 1 ; @stored = { grantee_id: grantee.id, ability: ability } }
56
+ Cancannible.get_cached_abilities = proc { |grantee| @stored[:ability] if @stored }
57
+ Cancannible.store_cached_abilities = proc { |grantee, ability| @store += 1 ; @stored = { grantee_id: grantee.id, ability: ability } }
41
58
  end
42
- it "should store the cached object on the first call" do
59
+ it "stores the cached object on the first call" do
43
60
  expect { subject }.to change { @stored }.from(nil)
44
61
  expect(@store).to eql(1)
45
62
  expect(@stored[:grantee_id]).to eql(grantee.id)
46
63
  expect(@stored[:ability]).to be_an(Ability)
47
64
  end
48
- it "should return the cached object on the second call" do
65
+ it "returns the cached object on the second call" do
49
66
  expect { subject }.to change { @stored }.from(nil)
50
67
  expect(@store).to eql(1)
51
68
  expect { grantee.abilities }.to_not change { @store }
52
- expect(grantee.abilities[:grantee_id]).to eql(grantee.id)
53
- expect(grantee.abilities[:ability]).to be_an(Ability)
69
+ expect(grantee.abilities).to be_an(Ability)
70
+ expect(@stored[:grantee_id]).to eql(grantee.id)
54
71
  end
55
72
  it "should re-cache object on the second call if refresh requested" do
56
73
  expect { subject }.to change { @stored }.from(nil)
57
74
  expect(@store).to eql(1)
58
75
  expect { grantee.abilities(true) }.to change { @store }.from(1).to(2)
59
- expect(grantee.abilities[:grantee_id]).to eql(grantee.id)
60
- expect(grantee.abilities[:ability]).to be_an(Ability)
76
+ expect(grantee.abilities).to be_an(Ability)
77
+ expect(@stored[:grantee_id]).to eql(grantee.id)
61
78
  end
62
79
  end
63
-
64
-
65
80
  end
66
-
67
- end
81
+ end
@@ -14,4 +14,4 @@ describe Cancannible do
14
14
  subject
15
15
  end
16
16
  end
17
- end
17
+ end
@@ -1,6 +1,5 @@
1
1
  require 'spec_helper'
2
2
 
3
-
4
3
  describe Cancannible do
5
4
  let(:grantee_class) { User }
6
5
  let(:ability) { :blow }
@@ -9,7 +8,6 @@ describe Cancannible do
9
8
  subject(:grantee) { grantee_class.create!(username: username) }
10
9
 
11
10
  describe "#can?" do
12
-
13
11
  context "with custom attribute association restriction" do
14
12
  let(:resource_class) { Widget }
15
13
  before do
@@ -245,7 +243,5 @@ describe Cancannible do
245
243
  it { should be_falsey }
246
244
  end
247
245
  end
248
-
249
246
  end
250
-
251
247
  end
@@ -4,7 +4,6 @@ describe Cancannible::Grantee do
4
4
  let(:grantee_class) { Member }
5
5
 
6
6
  context "without permissions inheritance" do
7
-
8
7
  describe "##inheritable_permissions" do
9
8
  subject { grantee_class.inheritable_permissions }
10
9
  it { should be_empty }
@@ -58,31 +57,6 @@ describe Cancannible::Grantee do
58
57
  end
59
58
  end
60
59
 
61
- context "with a nil resource" do
62
- let!(:resource) { nil }
63
- describe "#can? -> nil" do
64
- subject { grantee.can?(:read, nil) }
65
- context "when permission is not set" do
66
- it { should be_falsey }
67
- end
68
- context "when permission is set" do
69
- before { grantee.can(:read, resource) }
70
- it { should be_truthy }
71
- end
72
- end
73
- describe "#can? -> ''" do
74
- subject { grantee.can?(:read, '') }
75
- context "when permission is not set" do
76
- it { should be_falsey }
77
- end
78
- context "when permission is set" do
79
- before { grantee.can(:read, resource) }
80
- it { should be_falsey }
81
- end
82
- end
83
- end
84
-
85
-
86
60
  context "with a resource class" do
87
61
  let!(:resource) { Widget }
88
62
 
@@ -121,15 +95,14 @@ describe Cancannible::Grantee do
121
95
  context "with a non-existent model" do
122
96
  describe "instance" do
123
97
  let!(:obsolete_permission) {grantee.permissions.create!(asserted: true, ability: 'manage', resource_type: 'Bogative', resource_id: 33) }
124
- it "should not error on load" do
125
- expect { grantee.abilities }.to_not raise_error
98
+ it "raises CanCan::Error" do
99
+ expect { grantee.abilities }.to raise_error(CanCan::Error)
126
100
  end
127
101
  end
128
102
  describe "class" do
129
103
  let!(:obsolete_permission) {grantee.permissions.create!(asserted: true, ability: 'manage', resource_type: 'Bogative') }
130
- it "should not error on load" do
131
- grantee.abilities
132
- expect { grantee.abilities }.to_not raise_error
104
+ it "raises CanCan::Error" do
105
+ expect { grantee.abilities }.to raise_error(CanCan::Error)
133
106
  end
134
107
  end
135
108
  end
@@ -138,19 +111,17 @@ describe Cancannible::Grantee do
138
111
  class SuperBogative < ActiveRecord::Base
139
112
  end
140
113
  context "instance" do
141
- let!(:obsolete_permission) { grantee.permissions.create!(asserted: true, ability: 'manage', resource_type: 'SuperBogative', resource_id: 33) }
142
- it "should not error on load" do
114
+ let!(:invalid_permission) { grantee.permissions.create!(asserted: true, ability: 'manage', resource_type: 'SuperBogative', resource_id: 33) }
115
+ it "does not error on load" do
143
116
  expect { grantee.abilities }.to_not raise_error
144
117
  end
145
118
  end
146
119
  context "class" do
147
- let!(:obsolete_permission) { grantee.permissions.create!(asserted: true, ability: 'manage', resource_type: 'SuperBogative') }
148
- it "should not error on load" do
120
+ let!(:invalid_permission) { grantee.permissions.create!(asserted: true, ability: 'manage', resource_type: 'SuperBogative') }
121
+ it "does not error on load" do
149
122
  expect { grantee.abilities }.to_not raise_error
150
123
  end
151
124
  end
152
125
  end
153
-
154
126
  end
155
-
156
127
  end
@@ -1,11 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
-
4
3
  describe Cancannible do
5
4
  let(:grantee_class) { User }
6
5
 
7
6
  context "with mulitple sources of permissions inheritance" do
8
-
9
7
  describe "##inheritable_permissions" do
10
8
  subject { grantee_class.inheritable_permissions }
11
9
  it { should eql([:roles, :group]) }
@@ -15,12 +13,12 @@ describe Cancannible do
15
13
  let!(:role_b) { Role.create! }
16
14
  let!(:group_a) { Group.create! }
17
15
  let!(:group_b) { Group.create! }
18
- subject(:grantee) {
16
+ subject(:grantee) do
19
17
  u = grantee_class.new(group: group_a)
20
18
  u.roles << role_a
21
19
  u.save!
22
20
  u
23
- }
21
+ end
24
22
 
25
23
  context "with a symbolic resource" do
26
24
  let!(:resource) { :something }
@@ -43,10 +41,8 @@ describe Cancannible do
43
41
  it { should be_truthy }
44
42
  end
45
43
  end
46
-
47
44
  end
48
45
 
49
-
50
46
  context "with a resource class" do
51
47
  let!(:resource) { Widget }
52
48
 
@@ -68,7 +64,6 @@ describe Cancannible do
68
64
  it { should be_truthy }
69
65
  end
70
66
  end
71
-
72
67
  end
73
68
 
74
69
  context "with a resource instance" do
@@ -136,10 +131,6 @@ describe Cancannible do
136
131
  it { should be_truthy }
137
132
  end
138
133
  end
139
-
140
-
141
134
  end
142
-
143
135
  end
144
-
145
136
  end
metadata CHANGED
@@ -1,147 +1,129 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cancannible
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Gallagher
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-13 00:00:00.000000000 Z
11
+ date: 2022-03-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: 3.2.1
20
- - - "<"
17
+ - - "~>"
21
18
  - !ruby/object:Gem::Version
22
- version: '5.0'
19
+ version: '6.1'
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: 3.2.1
30
- - - "<"
24
+ - - "~>"
31
25
  - !ruby/object:Gem::Version
32
- version: '5.0'
26
+ version: '6.1'
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: activemodel
35
29
  requirement: !ruby/object:Gem::Requirement
36
30
  requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 3.2.1
40
- - - "<"
31
+ - - "~>"
41
32
  - !ruby/object:Gem::Version
42
- version: '5.0'
33
+ version: '6.1'
43
34
  type: :runtime
44
35
  prerelease: false
45
36
  version_requirements: !ruby/object:Gem::Requirement
46
37
  requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 3.2.1
50
- - - "<"
38
+ - - "~>"
51
39
  - !ruby/object:Gem::Version
52
- version: '5.0'
40
+ version: '6.1'
53
41
  - !ruby/object:Gem::Dependency
54
- name: cancan
42
+ name: cancancan
55
43
  requirement: !ruby/object:Gem::Requirement
56
44
  requirements:
57
- - - "~>"
45
+ - - ">="
58
46
  - !ruby/object:Gem::Version
59
- version: '1.6'
47
+ version: '0'
60
48
  type: :runtime
61
49
  prerelease: false
62
50
  version_requirements: !ruby/object:Gem::Requirement
63
51
  requirements:
64
- - - "~>"
52
+ - - ">="
65
53
  - !ruby/object:Gem::Version
66
- version: '1.6'
54
+ version: '0'
67
55
  - !ruby/object:Gem::Dependency
68
56
  name: activerecord
69
57
  requirement: !ruby/object:Gem::Requirement
70
58
  requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: 3.2.1
74
- - - "<"
59
+ - - "~>"
75
60
  - !ruby/object:Gem::Version
76
- version: '5.0'
61
+ version: '6.1'
77
62
  type: :development
78
63
  prerelease: false
79
64
  version_requirements: !ruby/object:Gem::Requirement
80
65
  requirements:
81
- - - ">="
82
- - !ruby/object:Gem::Version
83
- version: 3.2.1
84
- - - "<"
66
+ - - "~>"
85
67
  - !ruby/object:Gem::Version
86
- version: '5.0'
68
+ version: '6.1'
87
69
  - !ruby/object:Gem::Dependency
88
70
  name: sqlite3
89
71
  requirement: !ruby/object:Gem::Requirement
90
72
  requirements:
91
- - - "~>"
73
+ - - ">="
92
74
  - !ruby/object:Gem::Version
93
- version: '1.3'
75
+ version: 1.3.2
94
76
  type: :development
95
77
  prerelease: false
96
78
  version_requirements: !ruby/object:Gem::Requirement
97
79
  requirements:
98
- - - "~>"
80
+ - - ">="
99
81
  - !ruby/object:Gem::Version
100
- version: '1.3'
82
+ version: 1.3.2
101
83
  - !ruby/object:Gem::Dependency
102
84
  name: bundler
103
85
  requirement: !ruby/object:Gem::Requirement
104
86
  requirements:
105
- - - "~>"
87
+ - - ">="
106
88
  - !ruby/object:Gem::Version
107
- version: '1.6'
89
+ version: '0'
108
90
  type: :development
109
91
  prerelease: false
110
92
  version_requirements: !ruby/object:Gem::Requirement
111
93
  requirements:
112
- - - "~>"
94
+ - - ">="
113
95
  - !ruby/object:Gem::Version
114
- version: '1.6'
96
+ version: '0'
115
97
  - !ruby/object:Gem::Dependency
116
98
  name: rake
117
99
  requirement: !ruby/object:Gem::Requirement
118
100
  requirements:
119
- - - "~>"
101
+ - - ">="
120
102
  - !ruby/object:Gem::Version
121
- version: '10.0'
103
+ version: '0'
122
104
  type: :development
123
105
  prerelease: false
124
106
  version_requirements: !ruby/object:Gem::Requirement
125
107
  requirements:
126
- - - "~>"
108
+ - - ">="
127
109
  - !ruby/object:Gem::Version
128
- version: '10.0'
110
+ version: '0'
129
111
  - !ruby/object:Gem::Dependency
130
- name: rspec
112
+ name: rdoc
131
113
  requirement: !ruby/object:Gem::Requirement
132
114
  requirements:
133
- - - "~>"
115
+ - - ">="
134
116
  - !ruby/object:Gem::Version
135
- version: '3.2'
117
+ version: '0'
136
118
  type: :development
137
119
  prerelease: false
138
120
  version_requirements: !ruby/object:Gem::Requirement
139
121
  requirements:
140
- - - "~>"
122
+ - - ">="
141
123
  - !ruby/object:Gem::Version
142
- version: '3.2'
124
+ version: '0'
143
125
  - !ruby/object:Gem::Dependency
144
- name: appraisal
126
+ name: rspec
145
127
  requirement: !ruby/object:Gem::Requirement
146
128
  requirements:
147
129
  - - ">="
@@ -158,58 +140,30 @@ dependencies:
158
140
  name: guard-rspec
159
141
  requirement: !ruby/object:Gem::Requirement
160
142
  requirements:
161
- - - '='
143
+ - - ">="
162
144
  - !ruby/object:Gem::Version
163
- version: 4.6.4
145
+ version: '0'
164
146
  type: :development
165
147
  prerelease: false
166
148
  version_requirements: !ruby/object:Gem::Requirement
167
149
  requirements:
168
- - - '='
150
+ - - ">="
169
151
  - !ruby/object:Gem::Version
170
- version: 4.6.4
152
+ version: '0'
171
153
  - !ruby/object:Gem::Dependency
172
154
  name: rb-fsevent
173
155
  requirement: !ruby/object:Gem::Requirement
174
156
  requirements:
175
- - - '='
176
- - !ruby/object:Gem::Version
177
- version: 0.9.6
178
- type: :development
179
- prerelease: false
180
- version_requirements: !ruby/object:Gem::Requirement
181
- requirements:
182
- - - '='
183
- - !ruby/object:Gem::Version
184
- version: 0.9.6
185
- - !ruby/object:Gem::Dependency
186
- name: rb-inotify
187
- requirement: !ruby/object:Gem::Requirement
188
- requirements:
189
- - - '='
190
- - !ruby/object:Gem::Version
191
- version: 0.9.5
192
- type: :development
193
- prerelease: false
194
- version_requirements: !ruby/object:Gem::Requirement
195
- requirements:
196
- - - '='
197
- - !ruby/object:Gem::Version
198
- version: 0.9.5
199
- - !ruby/object:Gem::Dependency
200
- name: pry-coolline
201
- requirement: !ruby/object:Gem::Requirement
202
- requirements:
203
- - - '='
157
+ - - ">="
204
158
  - !ruby/object:Gem::Version
205
- version: 0.2.5
159
+ version: '0'
206
160
  type: :development
207
161
  prerelease: false
208
162
  version_requirements: !ruby/object:Gem::Requirement
209
163
  requirements:
210
- - - '='
164
+ - - ">="
211
165
  - !ruby/object:Gem::Version
212
- version: 0.2.5
166
+ version: '0'
213
167
  description: Extends CanCan with dynamic, inheritable permissions stored in a database,
214
168
  with caching and multi-tenant refinements
215
169
  email:
@@ -218,20 +172,14 @@ executables: []
218
172
  extensions: []
219
173
  extra_rdoc_files: []
220
174
  files:
175
+ - ".github/workflows/ruby.yml"
221
176
  - ".gitignore"
222
- - ".rspec"
223
- - ".travis.yml"
224
- - Appraisals
225
177
  - Gemfile
226
178
  - Guardfile
227
179
  - LICENSE.txt
228
180
  - README.md
229
181
  - Rakefile
230
182
  - cancannible.gemspec
231
- - gemfiles/rails_3.gemfile
232
- - gemfiles/rails_3.gemfile.lock
233
- - gemfiles/rails_4.gemfile
234
- - gemfiles/rails_4.gemfile.lock
235
183
  - lib/cancannible.rb
236
184
  - lib/cancannible/config.rb
237
185
  - lib/cancannible/grantee.rb
@@ -255,7 +203,7 @@ homepage: https://github.com/evendis/cancannible
255
203
  licenses:
256
204
  - MIT
257
205
  metadata: {}
258
- post_install_message:
206
+ post_install_message:
259
207
  rdoc_options: []
260
208
  require_paths:
261
209
  - lib
@@ -270,9 +218,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
218
  - !ruby/object:Gem::Version
271
219
  version: '0'
272
220
  requirements: []
273
- rubyforge_project:
274
- rubygems_version: 2.6.12
275
- signing_key:
221
+ rubygems_version: 3.2.20
222
+ signing_key:
276
223
  specification_version: 4
277
224
  summary: Dynamic, configurable permissions for CanCan
278
225
  test_files:
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --format documentation
2
- --color
data/.travis.yml DELETED
@@ -1,9 +0,0 @@
1
- # These are specific configuration settings required for travis-ci
2
- language: ruby
3
- before_script: "bundle exec rake appraisal:install"
4
- script: "bundle exec rake appraisal"
5
- rvm:
6
- - 1.9.3
7
- - 2.1.9
8
- notifications:
9
- email: false
data/Appraisals DELETED
@@ -1,11 +0,0 @@
1
- appraise "rails-3" do
2
- gem "activesupport", '~> 3.2'
3
- gem "activemodel", '~> 3.2'
4
- gem "activerecord", '~> 3.2'
5
- end
6
-
7
- appraise "rails-4" do
8
- gem "activesupport", '~> 4.0'
9
- gem "activemodel", '~> 4.0'
10
- gem "activerecord", '~> 4.0'
11
- end
@@ -1,9 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activesupport", "~> 3.2"
6
- gem "activemodel", "~> 3.2"
7
- gem "activerecord", "~> 3.2"
8
-
9
- gemspec :path => "../"
@@ -1,110 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- cancannible (1.0.1)
5
- activemodel (>= 3.2.1, < 5.0)
6
- activesupport (>= 3.2.1, < 5.0)
7
- cancan (~> 1.6)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- activemodel (3.2.22.5)
13
- activesupport (= 3.2.22.5)
14
- builder (~> 3.0.0)
15
- activerecord (3.2.22.5)
16
- activemodel (= 3.2.22.5)
17
- activesupport (= 3.2.22.5)
18
- arel (~> 3.0.2)
19
- tzinfo (~> 0.3.29)
20
- activesupport (3.2.22.5)
21
- i18n (~> 0.6, >= 0.6.4)
22
- multi_json (~> 1.0)
23
- appraisal (2.2.0)
24
- bundler
25
- rake
26
- thor (>= 0.14.0)
27
- arel (3.0.3)
28
- builder (3.0.4)
29
- cancan (1.6.10)
30
- coderay (1.1.2)
31
- concurrent-ruby (1.0.5)
32
- coolline (0.5.0)
33
- unicode_utils (~> 1.4)
34
- diff-lcs (1.3)
35
- ffi (1.9.21)
36
- formatador (0.2.5)
37
- guard (2.14.2)
38
- formatador (>= 0.2.4)
39
- listen (>= 2.7, < 4.0)
40
- lumberjack (>= 1.0.12, < 2.0)
41
- nenv (~> 0.1)
42
- notiffany (~> 0.0)
43
- pry (>= 0.9.12)
44
- shellany (~> 0.0)
45
- thor (>= 0.18.1)
46
- guard-compat (1.2.1)
47
- guard-rspec (4.6.4)
48
- guard (~> 2.1)
49
- guard-compat (~> 1.1)
50
- rspec (>= 2.99.0, < 4.0)
51
- i18n (0.9.4)
52
- concurrent-ruby (~> 1.0)
53
- listen (3.0.5)
54
- rb-fsevent (>= 0.9.3)
55
- rb-inotify (>= 0.9)
56
- lumberjack (1.0.12)
57
- method_source (0.9.0)
58
- multi_json (1.13.1)
59
- nenv (0.3.0)
60
- notiffany (0.1.1)
61
- nenv (~> 0.1)
62
- shellany (~> 0.0)
63
- pry (0.11.3)
64
- coderay (~> 1.1.0)
65
- method_source (~> 0.9.0)
66
- pry-coolline (0.2.5)
67
- coolline (~> 0.5)
68
- rake (10.5.0)
69
- rb-fsevent (0.9.6)
70
- rb-inotify (0.9.5)
71
- ffi (>= 0.5.0)
72
- rspec (3.7.0)
73
- rspec-core (~> 3.7.0)
74
- rspec-expectations (~> 3.7.0)
75
- rspec-mocks (~> 3.7.0)
76
- rspec-core (3.7.1)
77
- rspec-support (~> 3.7.0)
78
- rspec-expectations (3.7.0)
79
- diff-lcs (>= 1.2.0, < 2.0)
80
- rspec-support (~> 3.7.0)
81
- rspec-mocks (3.7.0)
82
- diff-lcs (>= 1.2.0, < 2.0)
83
- rspec-support (~> 3.7.0)
84
- rspec-support (3.7.1)
85
- shellany (0.0.1)
86
- sqlite3 (1.3.13)
87
- thor (0.20.0)
88
- tzinfo (0.3.53)
89
- unicode_utils (1.4.0)
90
-
91
- PLATFORMS
92
- ruby
93
-
94
- DEPENDENCIES
95
- activemodel (~> 3.2)
96
- activerecord (~> 3.2)
97
- activesupport (~> 3.2)
98
- appraisal
99
- bundler (~> 1.6)
100
- cancannible!
101
- guard-rspec (= 4.6.4)
102
- pry-coolline (= 0.2.5)
103
- rake (~> 10.0)
104
- rb-fsevent (= 0.9.6)
105
- rb-inotify (= 0.9.5)
106
- rspec (~> 3.2)
107
- sqlite3 (~> 1.3)
108
-
109
- BUNDLED WITH
110
- 1.16.0
@@ -1,9 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activesupport", "~> 4.0"
6
- gem "activemodel", "~> 4.0"
7
- gem "activerecord", "~> 4.0"
8
-
9
- gemspec :path => "../"
@@ -1,113 +0,0 @@
1
- PATH
2
- remote: ..
3
- specs:
4
- cancannible (1.0.1)
5
- activemodel (>= 3.2.1, < 5.0)
6
- activesupport (>= 3.2.1, < 5.0)
7
- cancan (~> 1.6)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- activemodel (4.2.10)
13
- activesupport (= 4.2.10)
14
- builder (~> 3.1)
15
- activerecord (4.2.10)
16
- activemodel (= 4.2.10)
17
- activesupport (= 4.2.10)
18
- arel (~> 6.0)
19
- activesupport (4.2.10)
20
- i18n (~> 0.7)
21
- minitest (~> 5.1)
22
- thread_safe (~> 0.3, >= 0.3.4)
23
- tzinfo (~> 1.1)
24
- appraisal (2.2.0)
25
- bundler
26
- rake
27
- thor (>= 0.14.0)
28
- arel (6.0.4)
29
- builder (3.2.3)
30
- cancan (1.6.10)
31
- coderay (1.1.2)
32
- concurrent-ruby (1.0.5)
33
- coolline (0.5.0)
34
- unicode_utils (~> 1.4)
35
- diff-lcs (1.3)
36
- ffi (1.9.21)
37
- formatador (0.2.5)
38
- guard (2.14.2)
39
- formatador (>= 0.2.4)
40
- listen (>= 2.7, < 4.0)
41
- lumberjack (>= 1.0.12, < 2.0)
42
- nenv (~> 0.1)
43
- notiffany (~> 0.0)
44
- pry (>= 0.9.12)
45
- shellany (~> 0.0)
46
- thor (>= 0.18.1)
47
- guard-compat (1.2.1)
48
- guard-rspec (4.6.4)
49
- guard (~> 2.1)
50
- guard-compat (~> 1.1)
51
- rspec (>= 2.99.0, < 4.0)
52
- i18n (0.9.4)
53
- concurrent-ruby (~> 1.0)
54
- listen (3.0.5)
55
- rb-fsevent (>= 0.9.3)
56
- rb-inotify (>= 0.9)
57
- lumberjack (1.0.12)
58
- method_source (0.9.0)
59
- minitest (5.11.3)
60
- nenv (0.3.0)
61
- notiffany (0.1.1)
62
- nenv (~> 0.1)
63
- shellany (~> 0.0)
64
- pry (0.11.3)
65
- coderay (~> 1.1.0)
66
- method_source (~> 0.9.0)
67
- pry-coolline (0.2.5)
68
- coolline (~> 0.5)
69
- rake (10.5.0)
70
- rb-fsevent (0.9.6)
71
- rb-inotify (0.9.5)
72
- ffi (>= 0.5.0)
73
- rspec (3.7.0)
74
- rspec-core (~> 3.7.0)
75
- rspec-expectations (~> 3.7.0)
76
- rspec-mocks (~> 3.7.0)
77
- rspec-core (3.7.1)
78
- rspec-support (~> 3.7.0)
79
- rspec-expectations (3.7.0)
80
- diff-lcs (>= 1.2.0, < 2.0)
81
- rspec-support (~> 3.7.0)
82
- rspec-mocks (3.7.0)
83
- diff-lcs (>= 1.2.0, < 2.0)
84
- rspec-support (~> 3.7.0)
85
- rspec-support (3.7.1)
86
- shellany (0.0.1)
87
- sqlite3 (1.3.13)
88
- thor (0.20.0)
89
- thread_safe (0.3.6)
90
- tzinfo (1.2.5)
91
- thread_safe (~> 0.1)
92
- unicode_utils (1.4.0)
93
-
94
- PLATFORMS
95
- ruby
96
-
97
- DEPENDENCIES
98
- activemodel (~> 4.0)
99
- activerecord (~> 4.0)
100
- activesupport (~> 4.0)
101
- appraisal
102
- bundler (~> 1.6)
103
- cancannible!
104
- guard-rspec (= 4.6.4)
105
- pry-coolline (= 0.2.5)
106
- rake (~> 10.0)
107
- rb-fsevent (= 0.9.6)
108
- rb-inotify (= 0.9.5)
109
- rspec (~> 3.2)
110
- sqlite3 (~> 1.3)
111
-
112
- BUNDLED WITH
113
- 1.16.0