trust 0.6.3 → 0.7.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.
data/README.md CHANGED
@@ -141,8 +141,32 @@ can? :edit, @account, @client # is current user allowed to edit the accoun
141
141
  #### On ActiveRecord objects you will use permits?
142
142
 
143
143
  ``` Ruby
144
- @customer.permits? :edit # does the current user have permission to edit the given customer?
145
- Customer.permits? :create, @client # does the current user have permission to create customers?
144
+ @customer.permits? :edit # does the current user have permission to edit the given customer?
145
+ Customer.permits? :create, @client # does the current user have permission to create customers for client?
146
+ Customer.permits? :create, @client, :by => @auditor # does the auditor have permission to create customers?
147
+ Customer.permits? :create, :for => @client, :by => @auditor # same as above
148
+ ```
149
+
150
+ #### You can also designate actors in your model so you can test if other people has access to do operations on a subject
151
+
152
+ Include the Actor role in the class
153
+ ``` Ruby
154
+ class Auditor
155
+ include Trust::Actor
156
+ ...
157
+ end
158
+ ```
159
+
160
+ Now you can test if the auditor has permission to modify customer for client. Three ways of writing it
161
+ ``` Ruby
162
+ @auditor.can? :update, @customer, @client
163
+ @auditor.can? :update, @customer, :for => @client
164
+ @auditor.can? :update, @customer, :parent => @client
165
+ ```
166
+
167
+ The above is the same as
168
+ ``` Ruby
169
+ @customer.permits? :update, @client, :by => @auditor
146
170
  ```
147
171
 
148
172
  ## Instance variables
@@ -0,0 +1,76 @@
1
+ # Copyright (c) 2012 Bingo Entreprenøren AS
2
+ # Copyright (c) 2012 Teknobingo Scandinavia AS
3
+ # Copyright (c) 2012 Knut I. Stenmark
4
+ # Copyright (c) 2012 Patrick Hanevold
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+
25
+ module Trust
26
+ # = Trust::ActiveModel extension
27
+ #
28
+ # Extends ActiveRecord with the +permits?+ and +ensure_permitted!+ method on class and instances
29
+ # If using Mongoid same features are included there
30
+ #
31
+ # Options:
32
+ #
33
+ # * +:parent+ - Specifies that the persmision should be tested in the context of a parent
34
+ # * +:by+ - Specifies an actor to be used instead of the currently logged in user
35
+ #
36
+ # ==== Examples
37
+ #
38
+ # # If current user is permitted to create customers, create it
39
+ # if Customer.permits? :create
40
+ # Customer.create attributes
41
+ # end
42
+ #
43
+ # # If current user is permitted to create accounts for the given customer, create it
44
+ # if Account.permits? :create, @customer
45
+ # Account.create attributes
46
+ # end
47
+ #
48
+ # # If the specified actor is permitted to create accounts for the given customer, create it
49
+ # if Account.permits? :create, @customer, :by => @actor
50
+ # Account.create attributes
51
+ # end
52
+ #
53
+ # # Raise an exception if user is not permitted to update the given customer, else save it
54
+ # @customer.ensure_permitted! :update
55
+ # @customer.save
56
+ #
57
+ # # Raise an exception if the specified user is not permitted to update the given customer, else save it
58
+ # @customer.ensure_permitted! :update, :by => @actor
59
+ # @customer.save
60
+ module ActiveModel
61
+ extend ActiveSupport::Concern
62
+
63
+ included do
64
+ include ClassMethods
65
+ end
66
+
67
+ module ClassMethods
68
+ def permits?(action, *args)
69
+ Trust::Authorization.authorized?(action, self, *args)
70
+ end
71
+ def ensure_permitted!(action, *args)
72
+ Trust::Authorization.authorize!(action, self, *args)
73
+ end
74
+ end
75
+ end
76
+ end
@@ -23,43 +23,33 @@
23
23
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
24
 
25
25
  module Trust
26
- module ActiveRecord
26
+ # = Trust::Actor extension
27
+ #
28
+ # Include this module if you want to check if an actor can act upon a specific subject
29
+ #
30
+ # ==== Examples
31
+ #
32
+ # # If the @actor can create customers, create it
33
+ # if @actor.can? :create, Customer
34
+ # Customer.create attributes
35
+ # end
36
+ #
37
+ # # If @actor can create accounts for the given customer, create it
38
+ # if @actor.can? :create, Account, @customer
39
+ # Account.create attributes
40
+ # end
41
+ # # It is also possible to make code more descripting for the same as above
42
+ # if @actor.can? :create, Account, :parent => @customer # or, ...
43
+ # if @actor.can? :create, Account, :for => @customer
44
+ #
45
+ module Actor
27
46
  extend ActiveSupport::Concern
28
- # = Trust::ActiveRecord extension
29
- # Extends ActiveRecord with the +permits?+ and +ensure_permitted!+ method on class and instances
30
- #
31
- # ==== Examples
32
- #
33
- # # If current user is permitted to create customers, create it
34
- # if Customer.permits? :create
35
- # Customer.create attributes
36
- # end
37
- #
38
- # # If current user is permitted to create accounts for the given customer, create it
39
- # if Account.permits? :create, @customer
40
- # Account.create attributes
41
- # end
42
- #
43
- # # If current user is permitted to update the given customer, update it
44
- # if @customer.permits? :update
45
- # @customer.save
46
- # end
47
- #
48
- # # Raise an exception if user is not permitted to update the given customer, else save it
49
- # @customer.ensure_permitted! :update
50
- # @customer.save
51
47
 
52
- included do
53
- include ClassMethods
54
- end
55
-
56
- module ClassMethods
57
- def permits?(action, parent = nil)
58
- Trust::Authorization.authorized?(action, self, parent)
59
- end
60
- def ensure_permitted!(action, parent = nil)
61
- Trust::Authorization.authorize!(action, self, parent)
62
- end
48
+ def can?(action, subject, *args)
49
+ options = args.extract_options!
50
+ options[:parent] ||= args.first || options.delete(:for)
51
+ options[:by] = self
52
+ Trust::Authorization.authorized?(action, subject, options)
63
53
  end
64
54
  end
65
55
  end
@@ -23,13 +23,26 @@
23
23
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
24
 
25
25
  module Trust
26
+ # = Trust Authorization
26
27
  class Authorization
27
28
  class << self
28
- # Returns true if user is authorized to perform +action+ on +object+ or +class+
29
- # If +parent+ is given, +parent+ may be tested in the implemented Permissions class
29
+
30
+ # Returns true if user is authorized to perform +action+ on +object+ or +class+.
31
+ #
32
+ # Options:
33
+ #
34
+ # * +:parent+ - the parent class to associate the subject with, can also be specified after the object
35
+ # or class. If +parent+ is given, +parent+ may be tested in the implemented Permissions class.
36
+ # +:parent+ is also aliased to +:for+.
37
+ #
38
+ # * +:by+ - Spoecify an actor instead of the user currently logged in
39
+ #
30
40
  # This method is called by the +can?+ method in Trust::Controller, and is normally
31
41
  # not necessary to call directly.
32
- def authorized?(action, object_or_class, parent)
42
+ def authorized?(action, object_or_class, *args)
43
+ options = args.extract_options!
44
+ parent = options[:parent] || options[:for] || args.first
45
+ actor = options[:by] || user
33
46
  if object_or_class.is_a? Class
34
47
  klass = object_or_class
35
48
  object = nil
@@ -40,35 +53,47 @@ module Trust
40
53
  # Identify which class to instanciate and then check authorization
41
54
  auth = authorizing_class(klass)
42
55
  # Rails.logger.debug "Trust: Authorizing class for #{klass.name} is #{auth.name}"
43
- auth.new(user, action.to_sym, klass, object, parent).authorized?
56
+ auth.new(actor, action.to_sym, klass, object, parent).authorized?
44
57
  end
45
58
 
46
59
  # Tests if user is authorized to perform +action+ on +object+ or +class+, with the
47
60
  # optional parent and raises Trust::AccessDenied exception if not permitted.
48
- # If using this method directly, an optional +message+ can be passed in to
49
- # replace the default message used.
61
+ #
62
+ # Options:
63
+ #
64
+ # * +:parent+ - the parent class to associate the subject with, can also be specified after the object
65
+ # or class. If +parent+ is given, +parent+ may be tested in the implemented Permissions class.
66
+ # +:parent+ is also aliased to +:for+.
67
+ #
68
+ # * +:by+ - Spoecify an actor instead of the user currently logged in
69
+ #
70
+ # * +:message+ - The message to be passed onto the AccessDenied exception class
71
+ #
50
72
  # This method is used by the +access_control+ method in Trust::Controller
51
- def authorize!(action, object_or_class, parent, message = nil)
52
- access_denied!(message, action, object_or_class, parent) unless authorized?(action, object_or_class, parent)
73
+ def authorize!(action, object_or_class, *args)
74
+ options = args.extract_options!
75
+ parent = options[:parent] || options[:for] || args.first
76
+ message = options[:message]
77
+ access_denied!(message, action, object_or_class, parent) unless authorized?(action, object_or_class, parent, options)
53
78
  end
54
79
 
55
- def access_denied!(message = nil, action = nil, subject = nil, parent = nil) # nodoc
80
+ def access_denied!(message = nil, action = nil, subject = nil, parent = nil) #:nodoc:
56
81
  raise AccessDenied.new(message, action, subject)
57
82
  end
58
83
 
59
- # returns the current +user+ being used in the authorization process
84
+ # Returns the current +user+ being used in the authorization process
60
85
  def user
61
86
  Thread.current["current_user"]
62
87
  end
63
88
 
64
- # sets the current +user+ to be used in the authorization process.
65
- # the +user+ is thread safe.
89
+ # Sets the current +user+ to be used in the authorization process.
90
+ # The +user+ is thread safe.
66
91
  def user=(user)
67
92
  Thread.current["current_user"] = user
68
93
  end
69
94
 
70
95
  private
71
- def authorizing_class(klass) # nodoc
96
+ def authorizing_class(klass) #:nodoc:
72
97
  auth = nil
73
98
  klass.ancestors.each do |k|
74
99
  break if k == ::ActiveRecord::Base
@@ -24,6 +24,7 @@
24
24
 
25
25
  module Trust
26
26
  module Controller
27
+ # = Trust Coontroller Properties
27
28
  class Properties
28
29
  delegate :logger, :to => Rails
29
30
  attr_reader :controller
@@ -33,7 +34,7 @@ module Trust
33
34
  attr_accessor :member_actions
34
35
  attr_accessor :collection_actions
35
36
 
36
- def initialize(controller, properties) # nodoc
37
+ def initialize(controller, properties) #:nodoc:
37
38
  @controller = controller
38
39
  @model = controller.controller_path
39
40
  if properties
@@ -50,16 +51,18 @@ module Trust
50
51
  end
51
52
 
52
53
  class << self
53
- # returns a controller properties object
54
- # ensures controller properties are instantiated in a correct manner and that inheritance is supported
54
+ # Returns a controller properties object.
55
+ #
56
+ # Ensures controller properties are instantiated in a correct manner and that inheritance is supported
55
57
  def instantiate(controller)
56
58
  new(controller, controller.superclass.instance_variable_get(:@properties))
57
59
  end
58
60
  end
59
61
 
60
- # returns or sets the model to be used in a controller
61
- # If not set, the controller_path is used
62
- # You can override the model to be accessed in a controller by setting the model
62
+ # Returns or sets the model to be used in a controller
63
+ #
64
+ # If not set, the controller_path is used.
65
+ # You can override the model to be accessed in a controller by setting the model.
63
66
  # Note that you should specify the model in plural form.
64
67
  #
65
68
  # ==== Example
@@ -81,10 +84,12 @@ module Trust
81
84
  end
82
85
 
83
86
  # Specify associated resources (nested resources)
84
- # Example:
85
- # belongs_to :lottery
86
- # belongs_to :table, :card_game
87
- # belongs_to :card_game, :as => :bridge
87
+ #
88
+ # === Example
89
+ #
90
+ # +belongs_to+ :lottery
91
+ # +belongs_to+ :table, :card_game
92
+ # +belongs_to+ :card_game, :as => :bridge
88
93
  #
89
94
  def belongs_to(*resources)
90
95
  raise ArgumentError, "You must specify at least one resource after belongs_to" unless resources
@@ -99,8 +104,10 @@ module Trust
99
104
  @associations.size > 0
100
105
  end
101
106
 
102
- # actions(options)
103
- # Options
107
+ # Specify actions to handle
108
+ #
109
+ # === Options
110
+ #
104
111
  # :new => actions # specify new actions - default id :new, :create
105
112
  # :member => actions # specify member actions - default is :show, :edit, :update, :destroy
106
113
  # :collection => actions # specify collection actions - default is :index
@@ -61,7 +61,8 @@ module Trust
61
61
  end
62
62
 
63
63
  # Sets the instance variable
64
- # Normally set by +load+
64
+ #
65
+ # Normally set by +load+.
65
66
  # You can access this method from the resource object.
66
67
  #
67
68
  # ==== Example
@@ -97,12 +98,14 @@ module Trust
97
98
  end
98
99
 
99
100
  # Sets the instance variable for collection
101
+ #
100
102
  # You may want to set this variable in your index action, we do not yet support loading of collections
101
103
  def instances=(instances)
102
104
  @controller.instance_variable_set(:"@#{plural_instance_name}", instances)
103
105
  end
104
106
 
105
107
  # Returns either the instances or the instance.
108
+ #
106
109
  # We have found that this can be useful in some implementation patterns
107
110
  def instantiated
108
111
  instances || instance
@@ -113,8 +116,10 @@ module Trust
113
116
  info.klass
114
117
  end
115
118
 
116
- # Loads the resource
119
+ # Loads the resource
120
+ #
117
121
  # See Trust::Controller::Properties which controls the behavior of this method.
122
+ #
118
123
  # It will normally find the instance variable for existing object or initialize them as new.
119
124
  # If using nested resources and +belongs_to+ has been declared in the controller it will use the
120
125
  # parent relation if found.
@@ -134,6 +139,7 @@ module Trust
134
139
  end
135
140
 
136
141
  # Returns the name of the instance for the resource
142
+ #
137
143
  # ==== Example
138
144
  #
139
145
  # # in AccountsController
@@ -143,6 +149,7 @@ module Trust
143
149
  end
144
150
 
145
151
  # Returns the plural name of the instance for the resource
152
+ #
146
153
  # ==== Example
147
154
  #
148
155
  # # in AccountsController
@@ -152,6 +159,7 @@ module Trust
152
159
  end
153
160
 
154
161
  # Returns the name of the parent resource
162
+ #
155
163
  # ==== Example
156
164
  #
157
165
  # # in AccountsController where belongs_to :customer has been declared
@@ -171,31 +179,35 @@ module Trust
171
179
  end
172
180
  end
173
181
 
174
- # ResorceInfo resolves information about the resource accessed in action controller
182
+ # = ResorceInfo
183
+ #
184
+ # resolves information about the resource accessed in action controller
175
185
  #
176
- # Examples in PeopleController (simple case)
177
- # ===
186
+ # === Examples in PeopleController (simple case)
187
+ #
178
188
  # resource.info.klass => Person
179
189
  # resource.info.params => {:person => {...}} # fetches the parameters for the resource
180
190
  # resource.info.name => :person
181
191
  # resource.info.plural_name => :people
182
192
  # resource.info.path => 'people' # this is the controller_path
183
193
  #
184
- # Examples in Lottery::AssignmentsController (with name space)
185
- # ===
194
+ # === Examples in Lottery::AssignmentsController (with name space)
195
+ #
186
196
  # resource.info.klass => Lottery::Assignment
187
197
  # resource.info.params => {:lottery_assignment => {...}}
188
198
  # resource.info.name => :lottery_assignment
189
199
  # resource.info.plural_name => :lottery_assignments
190
200
  # resource.info.path => 'lottery/assignments' # this is the controller_path
191
201
  #
192
- # Examples in ArchiveController (with inheritance)
202
+ # === Examples in ArchiveController (with inheritance)
193
203
  # Assumptions on routes:
204
+ #
194
205
  # resources :archives
195
206
  # resources :secret_acrvives, :controller => :archives
196
207
  # resources :public_acrvives, :controller => :archives
197
- # examples below assumes that the route secret_arcives is being accessed at the moment
198
- # ===
208
+ #
209
+ # === Examples below assumes that the route secret_arcives is being accessed at the moment
210
+ #
199
211
  # resource.info.klass => Archive
200
212
  # resource.info.params => {:secret_archive => {...}}
201
213
  # resource.info.name => :archive
@@ -203,27 +215,29 @@ module Trust
203
215
  # resource.info.path => 'archive' # this is the controller_path
204
216
  # resource.info.real_class => SecretArchive # Returns the real class which is accessed at the moment
205
217
  #
206
-
207
218
  class Resource::Info
208
219
  attr_reader :klass, :params, :name, :path, :real_class
209
220
 
210
- def params
221
+ def params #:nodoc:
211
222
  @data
212
223
  end
213
224
 
214
225
  protected
215
- def self.var_name(klass)
226
+ def self.var_name(klass) #:nodoc:
216
227
  klass.to_s.underscore.tr('/','_').to_sym
217
228
  end
218
- def var_name(klass)
229
+ def var_name(klass) #:nodoc:
219
230
  self.class.var_name(klass)
220
231
  end
221
232
  end
222
233
 
223
-
234
+ # = Resource::ResorceInfo
235
+ #
236
+ # Resolves the resource in subject
237
+ # (see #ResourceInfo)
224
238
  class Resource::ResourceInfo < Resource::Info
225
239
 
226
- def initialize(model, params)
240
+ def initialize(model, params) #:nodoc:
227
241
  @path, params = model, params
228
242
  @klass = model.to_s.classify.constantize
229
243
  @name = model.to_s.singularize.underscore.gsub('/','_').to_sym
@@ -234,13 +248,15 @@ module Trust
234
248
  @data = params[var_name(ptr)]
235
249
  end
236
250
 
251
+ # Returns the plural name of the resource
237
252
  def plural_name
238
253
  @plural_name ||= path.underscore.tr('/','_').to_sym
239
254
  end
240
255
 
241
- # returns an accessor for association. Tries with full name association first, and if that does not match, tries the demodularized association.
256
+ # Returns an accessor for association. Tries with full name association first, and if that does not match, tries the demodularized association.
257
+ #
258
+ # === Explanation
242
259
  #
243
- # Explanation:
244
260
  # Assuming
245
261
  # resource is instance of Lottery::Package #1 (@lottery_package)
246
262
  # association is Lottery::Prizes
@@ -258,6 +274,10 @@ module Trust
258
274
  end
259
275
  end
260
276
 
277
+ # = Resource::ParentInfo
278
+ #
279
+ # Resolves the parent resource in subject
280
+ # (see #ResourceInfo)
261
281
  class Resource::ParentInfo < Resource::Info
262
282
  attr_reader :object,:as
263
283
  def initialize(resources, params, request)
@@ -23,6 +23,7 @@
23
23
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
24
 
25
25
  module Trust
26
+ # = Trust Controller
26
27
  module Controller
27
28
  autoload :Resource, 'trust/controller/resource'
28
29
  autoload :Properties, 'trust/controller/properties'
@@ -49,6 +50,7 @@ module Trust
49
50
  delegate :belongs_to, :actions, :model, :to => :properties
50
51
 
51
52
  # Enables authorization in controller
53
+ #
52
54
  # +trustee+ accepts +:off+ or a hash of +callback+ options such as +:except+ and +:only+
53
55
  #
54
56
  # +trustee+ automatically calls the class methods: +set_user+, +load_resource+ and +access_control+
@@ -82,8 +84,6 @@ module Trust
82
84
  # redirect_to root_url, :alert => exception.message
83
85
  # end
84
86
  # end
85
-
86
-
87
87
  def trustee(*args)
88
88
  module_eval do
89
89
  include TrustInstanceMethods
@@ -95,15 +95,20 @@ module Trust
95
95
  end
96
96
 
97
97
  # Enable or disable +before_filter+ callback for setting the current user
98
- # Arguments:
98
+ #
99
+ # === Arguments:
100
+ #
99
101
  # :off - switch callback off
100
102
  # :only - only include these actions
101
103
  # :except - except these actions
102
104
  def set_user(*args)
103
105
  _filter_setting(:set_user, *args)
104
106
  end
107
+
105
108
  # Enable or disable +before_filter+ callback for setting the loading resource
106
- # Arguments:
109
+ #
110
+ # === Arguments:
111
+ #
107
112
  # :off - switch callback off
108
113
  # :only - only include these actions
109
114
  # :except - except these actions
@@ -112,7 +117,9 @@ module Trust
112
117
  end
113
118
  # Enable or disable +before_filter+ callback for setting the access control, i.e. verifying permissions
114
119
  # for the logged in user
115
- # Arguments:
120
+ #
121
+ # === Arguments:
122
+ #
116
123
  # :off - switch callback off
117
124
  # :only - only include these actions
118
125
  # :except - except these actions
@@ -132,7 +139,7 @@ module Trust
132
139
 
133
140
  module TrustInstanceMethods
134
141
  # Returns the controller Trust::Controller::Properties.
135
- # If no properties are instantiated, it will be instantiated
142
+ # If no properties are instantiated, it will be instantiated.
136
143
  #
137
144
  # == Delegated methods
138
145
  #
@@ -146,8 +153,9 @@ module Trust
146
153
  self.class.properties
147
154
  end
148
155
 
149
- # Sets the current user. It assumes +current_user+ is defined
150
- # This method is triggered as a callback on +before_filter+
156
+ # Sets the current user. It assumes +current_user+ is defined.
157
+ #
158
+ # This method is triggered as a callback on +before_filter+.
151
159
  # You may override this method.
152
160
  #
153
161
  # ==== Example
@@ -160,28 +168,32 @@ module Trust
160
168
  end
161
169
 
162
170
  # Returns the Trust::Controller::Resource resource for the controller.
163
- # Available as a helper in views
164
- # See Trust::Controller::Resource for relevant methods
171
+ #
172
+ # Available as a helper in views.
173
+ # See {Trust::Controller::Resource} for relevant methods.
165
174
  def resource
166
175
  @resource ||= Trust::Controller::Resource.new(self, self.class.properties, action_name, params, request)
167
176
  end
168
177
 
169
178
  # Loads the resource which basically means loading the instance and eventual parent defined through +belongs_to+
179
+ #
170
180
  # This method is triggered as a callback on +before_filter+
171
- # See Trust::Controller::Resource for more information
181
+ # See {Trust::Controller::Resource} for more information
172
182
  def load_resource
173
183
  resource.load
174
184
  end
175
185
 
176
- # Performs the actual access_control
186
+ # Performs the actual access_control.
187
+ #
177
188
  # This method is triggered as a callback on +before_filter+
178
189
  def access_control
179
190
  Trust::Authorization.authorize!(action_name, resource.instance || resource.klass, resource.parent)
180
191
  end
181
192
 
182
- # Tests for current users permissions
193
+ # Tests for current users permissions.
194
+ #
183
195
  # If access control is not sufficient in controller, you may use this method.
184
- # Also available as a helper in views
196
+ # Also available as a helper in views.
185
197
  #
186
198
  # ==== Examples
187
199
  # can? :edit # does the current user have permission to edit the current resource?
@@ -23,9 +23,10 @@
23
23
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
24
 
25
25
  module Trust
26
+ # = Trust InheritableAttribute
26
27
  module InheritableAttribute
27
28
 
28
- def self.deep_copy value
29
+ def self.deep_copy( value) #:nodoc:
29
30
  if value.is_a? Hash
30
31
  Hash[*value.map{ |k,v| [self.deep_copy(k),self.deep_copy(v)] }.flatten(1)]
31
32
  elsif value.is_a? Array
@@ -40,11 +41,12 @@ module Trust
40
41
  extend ActiveSupport::Concern
41
42
 
42
43
  module ClassMethods
43
- # Creates an inheritable attribute with accessors in the singleton class. Derived classes inherit the
44
- # attributes. This is especially helpful with arrays or hashes that are extended in the inheritance
45
- # chain. Note that you have to initialize the inheritable attribute.
44
+ # Creates an inheritable attribute with accessors in the singleton class.
45
+ #
46
+ # Derived classes inherit the attributes. This is especially helpful with arrays or hashes that
47
+ # are extended in the inheritance chain. Note that you have to initialize the inheritable attribute.
46
48
  #
47
- # Example:
49
+ # === Example
48
50
  #
49
51
  # class Cat
50
52
  # inheritable_attr :drinks