simple_roles 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/CHANGELOG.md +21 -0
  2. data/Gemfile +2 -4
  3. data/README.md +100 -17
  4. data/Rakefile +6 -12
  5. data/db/migrate/001_create_user_roles.rb +5 -4
  6. data/db/migrate/002_create_roles.rb +6 -3
  7. data/lib/simple_roles/configuration.rb +64 -11
  8. data/lib/simple_roles/engine.rb +2 -0
  9. data/lib/simple_roles/macros.rb +2 -5
  10. data/lib/simple_roles/many/persistence.rb +44 -0
  11. data/lib/simple_roles/many/roles_methods.rb +88 -0
  12. data/lib/simple_roles/many.rb +5 -0
  13. data/lib/simple_roles/one/persistence.rb +13 -0
  14. data/lib/simple_roles/one/roles_methods.rb +38 -0
  15. data/lib/simple_roles/one.rb +5 -0
  16. data/lib/simple_roles/packager.rb +18 -0
  17. data/lib/simple_roles/version.rb +1 -1
  18. data/lib/simple_roles.rb +27 -12
  19. data/simple_roles.gemspec +36 -30
  20. data/spec/dummy/config/database.yml +2 -13
  21. data/spec/dummy/config/environments/development.rb +0 -3
  22. data/spec/dummy/config/initializers/simple_roles.rb +2 -1
  23. data/spec/integration/main_spec.rb +6 -6
  24. data/spec/integration/requests/main_spec.rb +16 -17
  25. data/spec/simple_roles/configuration_spec.rb +66 -0
  26. data/spec/simple_roles/integration_many_spec.rb +47 -0
  27. data/spec/simple_roles/macros_spec.rb +25 -10
  28. data/spec/{support/aliases.rb → simple_roles/many/persistence_spec.rb} +0 -0
  29. data/spec/simple_roles/many_spec.rb +186 -0
  30. data/spec/simple_roles/one_spec.rb +77 -0
  31. data/spec/spec_helper.rb +40 -21
  32. data/spec/support/controller_macros.rb +1 -18
  33. data/spec/support/database.yml +1 -1
  34. data/spec/support/factories.rb +6 -17
  35. data/spec/support/migrations/010_create_one_users.rb +16 -0
  36. data/spec/support/migrations/{010_create_users.rb → 011_create_users.rb} +3 -3
  37. data/spec/support/{fixtures/models → models}/.gitkeep +0 -0
  38. data/spec/support/models/one_user.rb +2 -0
  39. data/spec/support/{fixtures/models → models}/user.rb +0 -1
  40. data/spec/support/setup_roles.rb +5 -0
  41. data/spec/support/transaction.rb +30 -0
  42. data/spec/transaction_spec.rb +15 -0
  43. metadata +176 -137
  44. data/lib/simple_roles/base.rb +0 -111
  45. data/lib/simple_roles/roles_array.rb +0 -63
  46. data/spec/integration/messages_spec.rb +0 -62
  47. data/spec/simple_roles/base_spec.rb +0 -191
  48. data/spec/support/rspec_helpers.rb +0 -22
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ # master
2
+
3
+ ...
4
+
5
+ # Version 0.0.6
6
+
7
+ ### Added
8
+
9
+ * Added strategies: "One" - the simplest strategy possible and "Many" - the former only strategy from older versions.
10
+
11
+ ### Changed
12
+
13
+ * SimpleRoles.configure - much better DSL
14
+
15
+ ### Removed
16
+
17
+ * Removed RolesArray presenter in "Many" strategy
18
+
19
+ # Versions <= 0.0.5
20
+
21
+ Long-long history here undocumented...
data/Gemfile CHANGED
@@ -7,16 +7,14 @@ source "http://rubygems.org"
7
7
  gem 'require_all'
8
8
  gem 'sugar-high'
9
9
  gem 'sweetloader'
10
+ gem 'activerecord'
10
11
 
11
12
  group :development, :test do
12
- gem 'activerecord'
13
13
  gem 'rake-kit'
14
14
  gem 'devise'
15
15
  gem 'mysql2'
16
16
  gem 'jeweler'
17
17
  gem 'cutter'
18
- gem 'rails'
19
- gem 'rspec-rails'
20
- gem 'capybara'
18
+ gem 'rspec'
21
19
  gem 'factory_girl'
22
20
  end
data/README.md CHANGED
@@ -10,7 +10,7 @@ If you are looking for a real serious roles system solution try [Troles](https:/
10
10
 
11
11
  ### Prerequisites
12
12
 
13
- SimpleRoles only assumes you have User model
13
+ SimpleRoles requires you have User model. That's all.
14
14
 
15
15
  ### Not a Gem yet
16
16
 
@@ -21,7 +21,7 @@ gem 'simple_roles', :git => "git://github.com/stanislaw/simple_roles.git"
21
21
  bundle update
22
22
  ```
23
23
 
24
- ### Set up valid roles you're gonna have in your app
24
+ ### Set up valid roles you're gonna have in your app and choose a Strategy.
25
25
 
26
26
  Create file simple_roles.rb in config/initializers and write there:
27
27
 
@@ -29,19 +29,88 @@ Create file simple_roles.rb in config/initializers and write there:
29
29
  # config/initializers/simple_roles.rb
30
30
  SimpleRoles.configure do |config|
31
31
  config.valid_roles = [:user, :admin, :editor]
32
+ config.strategy = :many # Default is :one
32
33
  end
33
34
  ```
34
35
 
35
- ### Copy and migrate SimpleRoles migrations by following rake task:
36
+ or in a nicer way:
37
+
38
+ ```ruby
39
+ # config/initializers/simple_roles.rb
40
+ SimpleRoles.configure do
41
+ valid_roles :user, :admin, :editor
42
+ strategy :many # Default is :one
43
+ end
44
+ ```
45
+
46
+ Now it is time to choose beetween two strategies possible:
47
+
48
+ * One - each of your users has only one role. It is the most common
49
+ choise for the most of the apps.
50
+ * Many - your user can be _:editor_ and _:curator_ and _:instructor_ all
51
+ at the same time. More rare one, setup is slightly more complex.
52
+
53
+ ### One Strategy
54
+
55
+ One strategy assumes your User model has string-typed 'role' column. Add this to your migrations and run them:
56
+
57
+ ```ruby
58
+ class CreateUsers < ActiveRecord::Migration
59
+ def up
60
+ create_table(:users) do |t|
61
+ # ...
62
+ t.string :role
63
+ # ...
64
+ end
65
+ end
66
+
67
+ def down
68
+ drop_table :users
69
+ end
70
+ end
71
+ ```
72
+
73
+ Finally, include 'simple_roles' macros in your User model:
74
+
75
+ ```ruby
76
+ class User
77
+ simple_roles
78
+ end
79
+ ```
80
+
81
+ ### Many strategy
82
+
83
+ In its background 'Many' strategy has following setup, based on <i>has_many :through</i> relations:
84
+
85
+ ```ruby
86
+ class User < ActiveRecord::Base
87
+ has_many :user_roles
88
+ has_many :roles, :through => :user_roles
89
+ end
90
+
91
+ class UserRole < ActiveRecord::Base
92
+ belongs_to :user
93
+ belongs_to :role
94
+ end
95
+
96
+ class Role < ActiveRecord::Base
97
+ has_many :user_roles
98
+ has_many :users, :through => :user_roles
99
+ end
100
+ ```
101
+
102
+ **You don't need to create these classes (UserRoles, Roles) and write these associations by hands** - all these classes SimpleRoles configures **automatically**. The only class you need is User and you must have *simple_roles* in it (see below).
103
+
104
+ **But you need** to supply migrations for them - copy and migrate SimpleRoles migrations by following rake task:
36
105
 
37
106
  ```ruby
38
107
  rake simple_roles_engine:install:migrations
39
108
  rake db:migrate
40
109
  ```
41
110
 
42
- Note! Migrations are based on roles you set up as valid (see previous step). If you do not create initializer with valid_roles, then valid_roles will be set up to defaults: :user and :admin.
111
+ **Note!** Migrations are based on roles you are to set up as valid (see previous step). If you do not create initializer with valid_roles, then valid_roles will be set up to defaults: :user and :admin.
43
112
 
44
- ### And finally include 'simple_roles' macros in your User model:
113
+ And finally include 'simple_roles' macros in your User model:
45
114
 
46
115
  ```ruby
47
116
  class User
@@ -49,33 +118,47 @@ class User
49
118
  end
50
119
  ```
51
120
 
52
- ## Usage
121
+ ### Notes
122
+
123
+ You can skip configuration in initializers and write it the following
124
+ way:
53
125
 
54
126
  ```ruby
55
- user.roles => #<RolesArray: {}>
127
+ class User
128
+ simple_roles do
129
+ strategy :one
130
+ valid_roles :user, :editor
131
+ end
132
+ end
133
+ ```
134
+
135
+ ## Usage example
136
+
137
+ ```ruby
138
+ user = User.new
139
+ user.roles # => []
56
140
 
57
141
  user.roles = :admin
58
- user.roles # => #<RolesArray: {:admin}>
59
- user.roles_list # => #<RolesArray: {:admin}>
142
+ user.roles # => [:admin]
143
+ user.roles_list # => [:admin]
144
+
60
145
  user.admin? # => true
61
146
  user.is_admin? # => true
62
147
 
63
- user.roles << :user
64
- user.roles # => #<RolesArray: {:admin, :user}>
148
+ user.roles = [:admin, :user]
149
+ user.roles # => [:admin, :user]
65
150
  user.is_user? # => true
66
151
 
67
152
  user.add_role :editor
68
- user.roles # => #<RolesArray: #{:admin, :user, :editor}>
153
+ user.roles # => [:admin, :user, :editor]
69
154
 
70
155
  user.remove_role :user
71
- user.roles # => #<RolesArray: {:admin, :editor}>
156
+ user.roles # => [:admin, :editor]
72
157
  user.has_role?(:admin) # => true
73
158
  user.has_any_role?(:admin, :blip) # => true
74
159
  user.has_role?(:blogger) # => false
75
160
  ```
76
161
 
77
- ## Todo:
162
+ ## Copyright
78
163
 
79
- - Write role groups part
80
- - Provide some more config options
81
- - More and better tests
164
+ Copyright (c) 2012 Stanislaw Pankevich.
data/Rakefile CHANGED
@@ -12,6 +12,9 @@ rescue LoadError
12
12
  RDoc::Task = Rake::RDocTask
13
13
  end
14
14
 
15
+ $:.unshift File.expand_path('lib', File.dirname(__FILE__))
16
+ require 'simple_roles'
17
+
15
18
  require 'jeweler'
16
19
  Jeweler::Tasks.new do |gem|
17
20
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
@@ -22,6 +25,7 @@ Jeweler::Tasks.new do |gem|
22
25
  gem.description = %Q{Simple Role System for Rails Apps}
23
26
  gem.email = "s.pankevich@gmail.com"
24
27
  gem.authors = ["stanislaw"]
28
+ gem.version = SimpleRoles::VERSION
25
29
  # dependencies defined in Gemfile
26
30
  end
27
31
  Jeweler::RubygemsDotOrgTasks.new
@@ -35,19 +39,9 @@ RDoc::Task.new(:rdoc) do |rdoc|
35
39
  end
36
40
 
37
41
  APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
38
- load 'rails/tasks/engine.rake'
39
42
 
43
+ load 'rails/tasks/engine.rake'
40
44
 
41
45
  Bundler::GemHelper.install_tasks
42
46
 
43
- require 'rake/testtask'
44
-
45
- Rake::TestTask.new(:test) do |t|
46
- t.libs << 'lib'
47
- t.libs << 'test'
48
- t.pattern = 'test/**/*_test.rb'
49
- t.verbose = false
50
- end
51
-
52
-
53
- task :default => :test
47
+ # task :default => :test
@@ -1,11 +1,12 @@
1
1
  class CreateUserRoles < ActiveRecord::Migration
2
2
  def up
3
- create_table :user_roles do |t|
4
- t.integer :user_id
5
- t.integer :role_id
3
+ create_table :user_roles do |t|
4
+ t.integer :user_id, :null => false
5
+ t.integer :role_id, :null => false
6
6
 
7
- t.timestamps
7
+ t.timestamps
8
8
  end
9
+
9
10
  add_index :user_roles, [:user_id, :role_id]
10
11
  end
11
12
 
@@ -1,10 +1,12 @@
1
1
  class CreateRoles < ActiveRecord::Migration
2
2
  def up
3
3
  create_table :roles do |t|
4
- t.string :name
4
+ t.string :name, :null => false
5
5
  t.timestamps
6
6
  end
7
7
 
8
+ add_index :roles, :name, :unique => true
9
+
8
10
  create_roles
9
11
  end
10
12
 
@@ -12,10 +14,11 @@ class CreateRoles < ActiveRecord::Migration
12
14
  drop_table :roles
13
15
  end
14
16
 
15
-
16
17
  def create_roles
17
18
  SimpleRoles::Configuration.valid_roles.each do |role|
18
- Role.create(:name => role.to_s)
19
+ r = Role.new
20
+ r.name = role.to_s
21
+ r.save
19
22
  end
20
23
  end
21
24
  end
@@ -1,33 +1,86 @@
1
- require 'singleton'
2
1
  module SimpleRoles
3
2
  module Configuration
4
-
5
3
  extend self
6
4
 
7
- attr_accessor :valid_roles, :user_models
5
+ attr_writer :strategy, :user_models
8
6
 
9
7
  def user_models
10
8
  @user_models ||= []
11
9
  end
12
10
 
11
+ def valid_roles *vr
12
+ if vr.any?
13
+ self.valid_roles = vr.flatten
14
+ end
15
+
16
+ @valid_roles ||= default_roles
17
+ end
18
+
13
19
  def valid_roles= vr
14
- raise "There should be an array of valid roles" if !vr.kind_of?(Array)
20
+ check_roles(vr)
21
+
15
22
  @valid_roles = vr
16
- distribute_methods
17
- end
18
23
 
19
- def valid_roles
20
- @valid_roles || default_roles
24
+ distribute_methods
21
25
  end
22
26
 
23
27
  def default_roles
24
28
  [:user, :admin]
25
29
  end
26
30
 
27
- def distribute_methods
28
- user_models.each do |um|
29
- um.register_roles_methods
31
+ def strategy st = nil
32
+ if st
33
+ self.strategy = st
30
34
  end
35
+
36
+ @strategy ||= default_strategy
37
+ end
38
+
39
+ def strategy= st
40
+ check_strategy st
41
+
42
+ @strategy = st
43
+ end
44
+
45
+ def available_strategies
46
+ strategies.keys
47
+ end
48
+
49
+ def strategy_class _strategy = nil
50
+ strategies[_strategy || strategy]
51
+ end
52
+
53
+ def strategies
54
+ {
55
+ :one => SimpleRoles::One,
56
+ :many => SimpleRoles::Many
57
+ }
58
+ end
59
+
60
+ private
61
+
62
+ def distribute_methods
63
+ user_models.each(&:register_dynamic_methods)
64
+ end
65
+
66
+ def check_strategy strategy
67
+ raise "Wrong strategy!" unless available_strategies.include? strategy
68
+ end
69
+
70
+ def check_roles rolez = valid_roles
71
+ raise "There should be an array of valid roles" unless rolez.kind_of?(Array)
72
+
73
+ rolez.map do |rolle|
74
+ begin
75
+ Role.find_by_name! rolle.to_s
76
+ rescue
77
+ puts "SimpleRoles warning: Couldn't find Role for #{rolle}. Maybe you need to re-run migrations?"
78
+ end
79
+ end if strategy == :many
80
+ end
81
+
82
+ def default_strategy
83
+ :one
31
84
  end
32
85
  end
33
86
  end
@@ -1,4 +1,6 @@
1
1
  module SimpleRoles
2
2
  class Engine < Rails::Engine
3
+ initializer 'simple_roles' do |app|
4
+ end
3
5
  end
4
6
  end
@@ -1,11 +1,8 @@
1
1
  module SimpleRoles
2
2
  module Macros
3
- def self.included(base)
4
- end
5
-
6
3
  def simple_roles &block
7
- yield SimpleRoles::Configuration if block
8
- include SimpleRoles::Base
4
+ SimpleRoles.config.instance_exec(SimpleRoles.config, &block) if block
5
+ SimpleRoles.package self
9
6
  end
10
7
  end
11
8
  end
@@ -0,0 +1,44 @@
1
+ module SimpleRoles
2
+ module Many
3
+ module Persistence
4
+ class << self
5
+ def included base
6
+ base.class_eval %{
7
+ has_many :user_roles
8
+ has_many :roles, :through => :user_roles
9
+ }
10
+ end
11
+ end
12
+
13
+ def roles
14
+ super.map(&:name).map(&:to_sym)
15
+ end
16
+
17
+ def roles= *rolez
18
+ rolez.to_symbols!.flatten!
19
+
20
+ super retrieve_roles(rolez)
21
+
22
+ save!
23
+ end
24
+
25
+ private
26
+
27
+ def retrieve_roles rolez
28
+ raise "Not a valid role!" if (rolez - config.valid_roles).size > 0
29
+
30
+ rolez.map do |rolle|
31
+ begin
32
+ Role.find_by_name! rolle.to_s
33
+ rescue
34
+ raise "Couldn't find Role for #{rolle}. Maybe you need to re-run migrations?"
35
+ end
36
+ end
37
+ end
38
+
39
+ def config
40
+ SimpleRoles::Configuration
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,88 @@
1
+ module SimpleRoles
2
+ module Many
3
+ module RolesMethods
4
+ class << self
5
+ def included base
6
+ base.class_eval %{
7
+ extend SimpleRoles::Many::RolesMethods::DynamicMethods
8
+ }
9
+ end
10
+ end
11
+
12
+ module DynamicMethods
13
+ class << self
14
+ def extended base
15
+ base.register_dynamic_methods
16
+ end
17
+ end
18
+
19
+ def register_dynamic_methods
20
+ valid_roles.each do |role|
21
+ class_eval %{
22
+ def self.#{role}s
23
+ Role.find_by_name("#{role}").users
24
+ end
25
+
26
+ def self.#{role}s_ids
27
+ Role.find_by_name("#{role}").user_ids
28
+ end
29
+ }
30
+
31
+ define_method :"#{role}?" do
32
+ roles.include?(:"#{role}")
33
+ end
34
+
35
+ alias_method :"is_#{role}?", :"#{role}?"
36
+ end
37
+ end
38
+
39
+ def valid_roles
40
+ SimpleRoles::Configuration.valid_roles
41
+ end
42
+ end
43
+
44
+ def roles_list
45
+ roles
46
+ end
47
+
48
+ def mass_assignment_authorizer *args
49
+ super.empty? ? super : (super + [:roles])
50
+ end
51
+
52
+ def has_roles? *rolez
53
+ rolez.flatten!
54
+
55
+ # rrr roles
56
+ rolez.all? do |role|
57
+ roles.include? role
58
+ end
59
+ end
60
+
61
+ alias_method :has_role?, :has_roles?
62
+
63
+ def has_any_role? *rolez
64
+ rolez.flatten!
65
+
66
+ rolez.any? do |role|
67
+ roles.include? role
68
+ end
69
+ end
70
+
71
+ def add_roles *rolez
72
+ self.roles = roles + rolez
73
+ end
74
+
75
+ alias_method :add_role, :add_roles
76
+
77
+ def remove_roles *rolez
78
+ self.roles = roles - rolez
79
+ end
80
+
81
+ alias_method :remove_role, :remove_roles
82
+
83
+ def set_role r
84
+ self.roles = r
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,5 @@
1
+ module SimpleRoles
2
+ module Many
3
+ autoload_modules :Persistence, :RolesMethods
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ module SimpleRoles
2
+ module One
3
+ module Persistence
4
+ def role
5
+ super.to_sym
6
+ end
7
+
8
+ def role= r
9
+ super r.to_s
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,38 @@
1
+ module SimpleRoles
2
+ module One
3
+ module RolesMethods
4
+ include SimpleRoles::One::Persistence
5
+
6
+ class << self
7
+ def included base
8
+ base.extend DynamicMethods
9
+ end
10
+ end
11
+
12
+ def set_role r
13
+ self.role= r
14
+ save!
15
+ end
16
+
17
+ module DynamicMethods
18
+ class << self
19
+ def extended base
20
+ base.register_dynamic_methods
21
+ end
22
+ end
23
+
24
+ def register_dynamic_methods
25
+ SimpleRoles.config.valid_roles.each do |r|
26
+ scope :"#{r}s", where(:role => r.to_s)
27
+
28
+ define_method :"#{r}?" do
29
+ role == r
30
+ end
31
+
32
+ alias_method :"is_#{r}?", :"#{r}?"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,5 @@
1
+ module SimpleRoles
2
+ module One
3
+ autoload_modules :Persistence, :RolesMethods
4
+ end
5
+ end
@@ -0,0 +1,18 @@
1
+ module SimpleRoles
2
+ module Packager
3
+ extend self
4
+
5
+ def package clazz, strategy = config.strategy
6
+ SimpleRoles::Configuration.user_models << clazz
7
+
8
+ clazz.send :include, SimpleRoles::config.strategy_class(strategy)::Persistence
9
+ clazz.send :include, SimpleRoles::config.strategy_class(strategy)::RolesMethods
10
+ end
11
+
12
+ private
13
+
14
+ def config
15
+ SimpleRoles.config
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module SimpleRoles
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.6"
3
3
  end
data/lib/simple_roles.rb CHANGED
@@ -1,19 +1,34 @@
1
- require "sweetloader"
2
- require "require_all"
3
- require "sugar-high/array"
4
- require "sugar-high/dsl"
1
+ require 'sweetloader'
2
+ require 'require_all'
5
3
 
6
- require "simple_roles/engine" if defined?(Rails)
7
- require "simple_roles/macros"
4
+ require 'sugar-high/array'
5
+ require 'sugar-high/dsl'
8
6
 
9
- require_all File.expand_path("../../app", __FILE__)
7
+ require 'active_record'
8
+
9
+ require 'simple_roles/version'
10
+
11
+ require 'simple_roles/engine' if defined?(Rails)
12
+ require 'simple_roles/macros'
13
+
14
+ require_all File.expand_path('../../app', __FILE__)
10
15
 
11
16
  module SimpleRoles
12
- autoload_modules :Base, :Configuration, :RolesArray
17
+ autoload_modules :Configuration, :Packager, :One, :Many
18
+
19
+ extend self
20
+
21
+ def configure &block
22
+ config.instance_exec config, &block
23
+ end
24
+
25
+ def config
26
+ SimpleRoles::Configuration
27
+ end
13
28
 
14
- class << self
15
- def configure &block
16
- yield SimpleRoles::Configuration
17
- end
29
+ def packager
30
+ SimpleRoles::Packager
18
31
  end
32
+
33
+ delegate :package, :to => :packager, :prefix => false
19
34
  end