cream 0.8.6 → 0.8.7
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.
- data/Changelog.txt +6 -1
- data/Design Ideas.textile +463 -0
- data/Gemfile +1 -0
- data/README.textile +158 -34
- data/Rakefile +8 -7
- data/VERSION +1 -1
- data/app/views/cream/menu/_admin_login_items.html.erb +2 -2
- data/app/views/cream/menu/_login_items.html.erb +2 -2
- data/app/views/cream/menu/_registration_items.html.erb +2 -2
- data/config/locales/cream.da.yml +16 -0
- data/cream.gemspec +38 -27
- data/lib/cream.rb +1 -0
- data/lib/cream/configure/after_init/role_config.rb +25 -21
- data/lib/cream/configure/rails.rb +8 -5
- data/lib/cream/controller/application_controller.rb +22 -0
- data/lib/cream/helper/role.rb +102 -11
- data/lib/generators/cream/app/app_generator.rb +50 -26
- data/lib/generators/cream/full_config/full_config_generator.rb +44 -9
- data/lib/generators/cream/helpers/all.rb +1 -0
- data/lib/generators/cream/helpers/execute_helper.rb +0 -4
- data/lib/generators/cream/helpers/gemfile_helper.rb +28 -0
- data/lib/generators/cream/helpers/orm_helper.rb +6 -2
- data/lib/generators/cream/helpers/strategy_helper.rb +28 -0
- data/lib/generators/cream/views/haml_util.rb +3 -4
- data/lib/generators/cream/views/views_generator.rb +13 -13
- data/lib/generators/devise/config/app_helper.rb +1 -1
- data/lib/generators/devise/config/config_generator.rb +1 -3
- data/lib/generators/devise/config/{gem_helper.rb → gem_config_helper.rb} +0 -23
- data/lib/generators/devise/customize/customize_generator.rb +49 -0
- data/lib/generators/devise/customize/customize_messages.rb +52 -0
- data/lib/generators/devise/customize/helpers/query_customizers.rb +43 -0
- data/lib/generators/devise/customize/helpers/recover_login.rb +80 -0
- data/lib/generators/devise/customize/helpers/username_helper.rb +149 -0
- data/lib/generators/devise/users/users_generator.rb +1 -3
- data/lib/generators/permits/config/config_generator.rb +1 -3
- data/lib/generators/roles/config/config_generator.rb +26 -4
- data/sandbox/any_user.rb +98 -0
- data/{lib/generators → sandbox}/cream_refactor.rb +0 -0
- data/sandbox/str_test.rb +50 -0
- data/spec/cream/configure/rails_role_spec.rb +1 -1
- data/spec/cream/helper/role_spec.rb +71 -21
- data/wiki/Cream-generators-overview.textile +79 -0
- data/wiki/How to gollum wiki.txt +13 -0
- metadata +107 -72
- data/wiki/CONFIG_GENERATOR.txt +0 -21
- data/wiki/DESIGN.txt +0 -21
- data/wiki/INSTALLATION.txt +0 -6
- data/wiki/PERMITS.txt +0 -32
- data/wiki/ROLE_STRATEGIES.txt +0 -40
- data/wiki/SPEC_NOTES.txt +0 -6
- data/wiki/VIEWS_GENERATOR.txt +0 -35
- data/wiki/VIEW_HELPERS.txt +0 -162
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'generators/cream/helpers/all'
|
2
|
+
|
3
|
+
module Devise
|
4
|
+
module Customizers
|
5
|
+
class UserName
|
6
|
+
include Cream::GeneratorHelper
|
7
|
+
extend Rails3::Assist::UseMacro
|
8
|
+
include Rails3::Assist::BasicLogger
|
9
|
+
use_helpers :app, :special, :file, :model
|
10
|
+
|
11
|
+
attr_accessor :orm, :user_class, :login_attribute
|
12
|
+
|
13
|
+
def initialize orm, user_class, login_attribute
|
14
|
+
@orm = orm
|
15
|
+
@user_class = user_class
|
16
|
+
@login_attribute = login_attribute
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_to_user_class
|
20
|
+
logger.debug 'add_to_user_class'
|
21
|
+
if active_record? && !has_migration_file?(:add_username_to_users)
|
22
|
+
logger.debug 'create migration: add_username_to_users'
|
23
|
+
%x[rails g migration add_username_to_users username:string]
|
24
|
+
%x[rake db:migrate]
|
25
|
+
end
|
26
|
+
|
27
|
+
make_attribute_accessible
|
28
|
+
|
29
|
+
AuthenticationKeys.new(user_class, login_attribute).modify_initializer
|
30
|
+
|
31
|
+
if login_attribute == 'login'
|
32
|
+
configure_generic_login
|
33
|
+
::Devise::CustomizeMessage.locales_update
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def make_attribute_accessible
|
38
|
+
return if user_class_content? 'attr_accessible :username'
|
39
|
+
|
40
|
+
::File.insert_into model_file(user_class), :before_last => 'end' do
|
41
|
+
%q{
|
42
|
+
# accessor config
|
43
|
+
attr_accessible :username}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_virtual_login_accessor
|
48
|
+
return if user_class_content? 'attr_accessor :login'
|
49
|
+
|
50
|
+
::File.insert_into model_file(user_class), :before_last => 'end' do
|
51
|
+
%q{
|
52
|
+
attr_accessor :login}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def configure_generic_login
|
57
|
+
logger.debug 'configure generic login'
|
58
|
+
add_virtual_login_accessor
|
59
|
+
override_user_auth
|
60
|
+
modify_retrieve_password
|
61
|
+
end
|
62
|
+
|
63
|
+
def override_user_auth
|
64
|
+
if !is_default_devise_orm?
|
65
|
+
Devise::CustomizeMessage.find_record
|
66
|
+
return
|
67
|
+
end
|
68
|
+
|
69
|
+
return if user_class_content? '# self.find_for_database_authentication'
|
70
|
+
|
71
|
+
::File.insert_into model_file(user_class), :before_last => 'end' do
|
72
|
+
::Devise::QueryCustomizers::UserAuth.send orm
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def modify_retrieve_password
|
77
|
+
if !is_default_devise_orm?
|
78
|
+
::Devise::CustomizeMessage.retrieve_password
|
79
|
+
return
|
80
|
+
end
|
81
|
+
insert_reset_password_keys_stmt # in devise initializer
|
82
|
+
|
83
|
+
return if user_class_content? '# recover login'
|
84
|
+
|
85
|
+
content = recover_login_header << ::Devise::Customizers::RecoverLogin.new(orm).retrieve_password
|
86
|
+
|
87
|
+
::File.insert_into model_file(user_class), :before_last => 'end' do
|
88
|
+
content
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def insert_reset_password_keys_stmt
|
93
|
+
return if devise_init_content? '# reset_password_keys = [ :login ]'
|
94
|
+
::File.insert_into initializer_file(:devise), 'config.reset_password_keys = [ :login ]', :after => 'Rails::Application'
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
def user_class_content? content
|
100
|
+
read_model(user_class) =~ content.to_regexp
|
101
|
+
end
|
102
|
+
|
103
|
+
def devise_init_content? content
|
104
|
+
read_initializer(:devise) =~ content.to_regexp
|
105
|
+
end
|
106
|
+
|
107
|
+
def recover_login_header
|
108
|
+
%q{
|
109
|
+
protected
|
110
|
+
|
111
|
+
# recover login
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
class AuthenticationKeys
|
116
|
+
include Cream::GeneratorHelper
|
117
|
+
extend Rails3::Assist::UseMacro
|
118
|
+
include Rails3::Assist::BasicLogger
|
119
|
+
use_helpers :app, :special, :file
|
120
|
+
|
121
|
+
attr_accessor :login_attribute
|
122
|
+
|
123
|
+
def initialize user_class, login_attribute
|
124
|
+
@user_class = user_class
|
125
|
+
@login_attribute = login_attribute
|
126
|
+
end
|
127
|
+
|
128
|
+
def modify_initializer
|
129
|
+
logger.debug 'modify devise initializer'
|
130
|
+
return if devise_init_content? keys_stmt_replacement(login_attribute)
|
131
|
+
|
132
|
+
replace_initializer_content :devise, :where => default_keys_stmt, :with => keys_stmt_replacement(login_attribute)
|
133
|
+
end
|
134
|
+
|
135
|
+
def devise_init_content? content
|
136
|
+
read_initializer(:devise) =~ content.to_regexp
|
137
|
+
end
|
138
|
+
|
139
|
+
def keys_stmt_replacement name
|
140
|
+
"config.authentication_keys = [ :#{name} ]"
|
141
|
+
end
|
142
|
+
|
143
|
+
def default_keys_stmt
|
144
|
+
/# config.authentication_keys = [\s*:email\s*]/
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -56,9 +56,7 @@ module Devise
|
|
56
56
|
extend Rails3::Assist::UseMacro
|
57
57
|
include Rails3::Assist::BasicLogger
|
58
58
|
|
59
|
-
include Cream::GeneratorHelper
|
60
|
-
include Cream::GeneratorHelper::Executor
|
61
|
-
include Cream::GeneratorHelper::Args
|
59
|
+
include Cream::GeneratorHelper
|
62
60
|
|
63
61
|
include DeviseUserGenerator::Helper
|
64
62
|
include DeviseUserGenerator::RoutesHelper
|
@@ -33,9 +33,7 @@ module Permits
|
|
33
33
|
|
34
34
|
include Rails3::Assist::BasicLogger
|
35
35
|
|
36
|
-
include Cream::GeneratorHelper
|
37
|
-
include Cream::GeneratorHelper::Executor
|
38
|
-
include Cream::GeneratorHelper::Args
|
36
|
+
include Cream::GeneratorHelper
|
39
37
|
|
40
38
|
def permits_gems
|
41
39
|
gem 'cancan-permits'
|
@@ -10,10 +10,16 @@ module Roles
|
|
10
10
|
class ConfigGenerator < Rails::Generators::Base
|
11
11
|
desc "Configure Roles"
|
12
12
|
|
13
|
+
argument :user_class, :type => :string, :default => 'User', :desc => "User class name"
|
14
|
+
|
13
15
|
# ORM to use
|
14
16
|
class_option :orm, :type => :string, :default => 'active_record', :desc => "ORM to use"
|
15
17
|
class_option :strategy, :type => :string, :default => 'role_string', :desc => "Roles strategy to use"
|
16
18
|
class_option :roles, :type => :array, :default => ['guest', 'admin'], :desc => "Valid roles to use"
|
19
|
+
|
20
|
+
class_option :role_class, :type => :string, :aliases => "-rc", :default => 'Role', :desc => "Role class name", :optional => true
|
21
|
+
class_option :user_role_class, :type => :string, :aliases => "-urc", :default => 'UserRole', :desc => "User-Role (join table) class name", :optional => true
|
22
|
+
|
17
23
|
class_option :logfile, :type => :string, :default => nil, :desc => "Logfile location"
|
18
24
|
class_option :default_roles, :type => :boolean, :default => true, :desc => "Create default roles :admin and :guest"
|
19
25
|
class_option :gems, :type => :boolean, :default => true, :desc => "Add gems to gemfile?"
|
@@ -38,9 +44,7 @@ module Roles
|
|
38
44
|
include Rails3::Assist::BasicLogger
|
39
45
|
extend Rails3::Assist::UseMacro
|
40
46
|
|
41
|
-
include Cream::GeneratorHelper
|
42
|
-
include Cream::GeneratorHelper::Executor
|
43
|
-
include Cream::GeneratorHelper::Args
|
47
|
+
include Cream::GeneratorHelper
|
44
48
|
|
45
49
|
use_helpers :model, :file
|
46
50
|
|
@@ -51,7 +55,7 @@ module Roles
|
|
51
55
|
end
|
52
56
|
|
53
57
|
def create_roles
|
54
|
-
rgen "#{roles_generator}
|
58
|
+
rgen "#{roles_generator} #{user_class} --strategy #{strategy} --roles #{roles_list} #{default_roles_option} #{class_options}"
|
55
59
|
end
|
56
60
|
|
57
61
|
def set_valid_roles_cream
|
@@ -72,6 +76,24 @@ module Roles
|
|
72
76
|
|
73
77
|
private
|
74
78
|
|
79
|
+
def class_options
|
80
|
+
option_str = ""
|
81
|
+
if role_ref_strategy?
|
82
|
+
option_str << " --role-class #{role_class}"
|
83
|
+
option_str << " --user-role-class #{user_role_class}" if relational_mapper?
|
84
|
+
end
|
85
|
+
option_str
|
86
|
+
end
|
87
|
+
|
88
|
+
def role_class
|
89
|
+
options[:role_class] || 'Role'
|
90
|
+
end
|
91
|
+
|
92
|
+
def user_role_class
|
93
|
+
options[:user_role_class] || 'UserRole'
|
94
|
+
end
|
95
|
+
|
96
|
+
|
75
97
|
def user_exist_check
|
76
98
|
raise "ERROR: User model missing. Please create a User model before running this generator" if !has_user_model?
|
77
99
|
end
|
data/sandbox/any_user.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
class Stuff
|
2
|
+
def for_any_user options = nil, &block
|
3
|
+
yield if Labels.state_check Labels.extract(options), current_user
|
4
|
+
end
|
5
|
+
|
6
|
+
def not_for_any_user options = nil, &block
|
7
|
+
return if Labels.state_check Labels.extract(options), current_user
|
8
|
+
yield
|
9
|
+
end
|
10
|
+
|
11
|
+
def is? role
|
12
|
+
role == :guest
|
13
|
+
end
|
14
|
+
|
15
|
+
def current_user
|
16
|
+
Stuff.new
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
module Labels
|
22
|
+
class << self
|
23
|
+
def extract options
|
24
|
+
case options
|
25
|
+
when Symbol
|
26
|
+
return :logged_in if logged_in_labels.include?(options)
|
27
|
+
return :logged_out if logged_out_labels.include?(options)
|
28
|
+
when Hash
|
29
|
+
return :logged_in if logged_in_labels.any? {|lab| options[lab] }
|
30
|
+
return :logged_out if logged_out_labels.any? {|lab| options[lab] }
|
31
|
+
end
|
32
|
+
raise ArgumentException, "Unknown option #{options}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def state_check state, current_user
|
36
|
+
logged_in_check(state, current_user) || logged_out_check(state, current_user)
|
37
|
+
end
|
38
|
+
|
39
|
+
def logged_in_check state, current_user
|
40
|
+
state == :logged_in && is_not_guest?(current_user)
|
41
|
+
end
|
42
|
+
|
43
|
+
def logged_out_check state, current_user
|
44
|
+
state == :logged_out && is_guest?(current_user)
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_not_guest? current_user
|
48
|
+
!current_user || (current_user && !current_user.is?(:guest))
|
49
|
+
end
|
50
|
+
|
51
|
+
def is_guest? current_user
|
52
|
+
current_user && current_user.is?(:guest)
|
53
|
+
end
|
54
|
+
|
55
|
+
def logged_in_labels
|
56
|
+
[:logged_in, :signed_in, :not_logged_out, :not_signed_out]
|
57
|
+
end
|
58
|
+
|
59
|
+
def logged_out_labels
|
60
|
+
[:logged_out, :signed_out, :not_logged_in, :not_signed_in]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
s = Stuff.new
|
67
|
+
|
68
|
+
s.for_any_user :logged_in do
|
69
|
+
puts "log out - for_any_user :logged_in"
|
70
|
+
end
|
71
|
+
|
72
|
+
s.for_any_user :logged_out do
|
73
|
+
puts "log in - for_any_user :logged_out"
|
74
|
+
end
|
75
|
+
|
76
|
+
s.for_any_user :not_logged_in do
|
77
|
+
puts "log in - for_any_user :not_logged_in"
|
78
|
+
end
|
79
|
+
|
80
|
+
s.for_any_user :not_logged_out do
|
81
|
+
puts "log out - for_any_user :not_logged_out"
|
82
|
+
end
|
83
|
+
|
84
|
+
s.not_for_any_user :logged_in do
|
85
|
+
puts "log in - not_for_any_user :logged_in"
|
86
|
+
end
|
87
|
+
|
88
|
+
s.not_for_any_user :logged_out do
|
89
|
+
puts "log out - not_for_any_user :logged_out"
|
90
|
+
end
|
91
|
+
|
92
|
+
s.not_for_any_user :not_logged_in do
|
93
|
+
puts "log out - not_for_any_user :not_logged_in"
|
94
|
+
end
|
95
|
+
|
96
|
+
s.not_for_any_user :not_logged_out do
|
97
|
+
puts "log in - not_for_any_user :not_logged_out"
|
98
|
+
end
|
File without changes
|
data/sandbox/str_test.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# HAS BEEN MOVED TO SUGAR-HIGH :)
|
2
|
+
|
3
|
+
s = %q{
|
4
|
+
class Abc
|
5
|
+
def begin
|
6
|
+
|
7
|
+
end
|
8
|
+
end}
|
9
|
+
|
10
|
+
class String
|
11
|
+
def insert_before_last str, marker = 'end'
|
12
|
+
res = []
|
13
|
+
found = false
|
14
|
+
marker = case marker
|
15
|
+
when Symbol, String
|
16
|
+
marker.to_s
|
17
|
+
when Hash
|
18
|
+
marker[:marker].to_s
|
19
|
+
else
|
20
|
+
raise ArgumentException, "last argument is the marker and must be a String, Symbol or even Hash with a :marker option pointing to the marker (String or Symbol)"
|
21
|
+
end
|
22
|
+
|
23
|
+
marker = Regexp.escape(marker.reverse)
|
24
|
+
nl = Regexp.escape("\n")
|
25
|
+
# puts self
|
26
|
+
# puts "marker: #{marker}"
|
27
|
+
# puts "nl: #{nl}"
|
28
|
+
# puts "str: #{str}"
|
29
|
+
|
30
|
+
self.reverse.each_line do |x|
|
31
|
+
x.gsub! /#{nl}/, ''
|
32
|
+
if !found && x =~ /#{marker}/
|
33
|
+
replace = "#{str}\n" << x.reverse
|
34
|
+
res << replace
|
35
|
+
found = true
|
36
|
+
else
|
37
|
+
res << x.reverse
|
38
|
+
end
|
39
|
+
end
|
40
|
+
res.reverse
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# puts s.insert_before_last ' # hello'
|
45
|
+
# puts s.insert_before_last ' # hello', :marker => 'end'
|
46
|
+
puts s.insert_before_last ' # hello', :marker => :end
|
47
|
+
|
48
|
+
# s = s.strip.gsub(/(end$)/z, "#last\n\\1")
|
49
|
+
#
|
50
|
+
# puts s
|
@@ -29,7 +29,7 @@ describe "Rails extension" do
|
|
29
29
|
after_init :controller do
|
30
30
|
:controller.should be_extended_with Cream, :role
|
31
31
|
:controller.should be_extended_with Cream::Controller, :ability
|
32
|
-
:controller.should be_extended_with Cream::Helper, :role, :host
|
32
|
+
:controller.should be_extended_with Cream::Helper, :role, :host
|
33
33
|
end
|
34
34
|
|
35
35
|
init_app_railties :minimal, :view
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'cream/helper/role'
|
3
|
+
require 'cream/configure/rails'
|
3
4
|
|
4
5
|
describe Cream::Helper::Role do
|
5
6
|
|
@@ -8,27 +9,27 @@ describe Cream::Helper::Role do
|
|
8
9
|
context 'method auto-generated when Rails initialize based on registered roles' do
|
9
10
|
describe '#guest_area' do
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
12
|
+
it "should execute an Admin guarded block for :admin" do
|
13
|
+
view_engine do |e, view|
|
14
|
+
view.stubs(:has_role?).with([:admin]).returns true
|
15
|
+
|
16
|
+
res = e.run_template do
|
17
|
+
%{<%= for_admin { 'hello' } %>}
|
18
|
+
end
|
19
|
+
res.should match /hello/
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not execute an Admin guarded block for user not :admin" do
|
24
|
+
view_engine do |e, view|
|
25
|
+
view.stubs(:has_role?).with([:admin]).returns false
|
26
|
+
|
27
|
+
res = e.run_template do
|
28
|
+
%{<%= for_admin { 'hello' } %>}
|
29
|
+
end
|
30
|
+
res.should be_empty
|
31
|
+
end
|
32
|
+
end
|
32
33
|
end # desc
|
33
34
|
end # context
|
34
35
|
|
@@ -56,6 +57,31 @@ describe Cream::Helper::Role do
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
end # desc
|
60
|
+
|
61
|
+
describe '#for_role' do
|
62
|
+
it "display an :admin only block" do
|
63
|
+
view_engine do |e, view|
|
64
|
+
view.stubs(:has_role?).with([:admin]).returns true
|
65
|
+
|
66
|
+
res = e.run_template do
|
67
|
+
%{<%= for_role(:admin) { 'hello' } %>}
|
68
|
+
end
|
69
|
+
res.should match /hello/
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should not display a :guest only block" do
|
74
|
+
view_engine do |e, view|
|
75
|
+
view.stubs(:has_role?).with([:guest]).returns false
|
76
|
+
|
77
|
+
res = e.run_template do
|
78
|
+
%{<%= for_role(:guest) { 'hello' } %>}
|
79
|
+
end
|
80
|
+
res.should be_empty
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end # desc
|
84
|
+
|
59
85
|
|
60
86
|
describe '#not_for_roles' do
|
61
87
|
it "should not display a block not for :admin" do
|
@@ -80,6 +106,30 @@ describe Cream::Helper::Role do
|
|
80
106
|
end
|
81
107
|
end
|
82
108
|
end # desc
|
109
|
+
|
110
|
+
describe '#not_for_role' do
|
111
|
+
it "should not display a block not for :admin" do
|
112
|
+
view_engine do |e, view|
|
113
|
+
view.stubs(:has_role?).with([:admin]).returns true
|
114
|
+
|
115
|
+
res = e.run_template do
|
116
|
+
%{<%= not_for_role(:admin) { 'hello' } %>}
|
117
|
+
end
|
118
|
+
res.should be_empty
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should display a div block not for :guest" do
|
123
|
+
view_engine do |e, view|
|
124
|
+
view.stubs(:has_role?).with([:guest]).returns false
|
125
|
+
|
126
|
+
res = e.run_template do
|
127
|
+
%{<%= not_for_role(:guest) { 'hello' } %>}
|
128
|
+
end
|
129
|
+
res.should match /hello/
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end # desc
|
83
133
|
end
|
84
134
|
|
85
135
|
describe '#has_role?' do
|