cancannible 1.0.1 → 2.0.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
- 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