Module: LoadAndAuthorizeResource::ClassMethods

Defined in:
lib/load_and_authorize_resource.rb

Instance Method Summary collapse

Instance Method Details

#authorize_parent(*names) ⇒ Object

Macro sets a before filter to authorize the parent resource. Assumes ther resource is already set (in a before filter).

class NotesController < ApplicationController
  authorize_parent :group
end

If ‘@group` is not found, or calling `current_user.can_read?(@group)` fails, an exception will be raised.

If the parent resource is optional, and you only want to check authorization if it is set, you can set the ‘:shallow` option to `true`:

class NotesController < ApplicationController
  authorize_parent :group, shallow: true
end

Parameters:

  • options (Hash)

    a customizable set of options



144
145
146
147
148
149
# File 'lib/load_and_authorize_resource.rb', line 144

def authorize_parent(*names)
  options = names.extract_options!.dup
  required = !(options.delete(:shallow) || options.delete(:optional))
  save_nested_resource_options(:auth, names, required)
  before_filter :authorize_parent, options
end

#authorize_resource(options = {}) ⇒ Object

Checks authorization on the already-loaded resource.

This method calls ‘current_user.can_<action>?(@resource)` and raises an exception if the answer is ’no’.

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :except (Boolean)

    controller actions to ignore when applying this filter

  • :only (Boolean)

    controller actions to apply this filter



192
193
194
195
196
197
198
# File 'lib/load_and_authorize_resource.rb', line 192

def authorize_resource(options={})
  options = options.dup
  unless options[:only] or options[:except]
    options.reverse_merge!(only: [:show, :new, :create, :edit, :update, :destroy])
  end
  before_filter :authorize_resource, options
end

#load_and_authorize_parent(*names) ⇒ Object

A convenience method for calling both ‘load_parent` and `authorize_parent`



152
153
154
155
# File 'lib/load_and_authorize_resource.rb', line 152

def load_and_authorize_parent(*names)
  load_parent(*names)
  authorize_parent(*names)
end

#load_and_authorize_resource(options = {}) ⇒ Object

A convenience method for calling both ‘load_resource` and `authorize_resource`



201
202
203
204
# File 'lib/load_and_authorize_resource.rb', line 201

def load_and_authorize_resource(options={})
  load_resource(options)
  authorize_resource(options)
end

#load_parent(*names) ⇒ Object

Macro sets a before filter to load the parent resource. Pass in one symbol for each potential parent you’re nested under.

For example, if you have routes:

resources :people do
  resources :notes
end

resources :groups do
  resources :notes
end

…you can call load_parent like so in your controller:

class NotesController < ApplicationController
  load_parent :person, :group
end

This will attempt to do the following for each resource, in order:

  1. look for ‘params`

  2. if present, call ‘Person.find(params)`

  3. set @person

If we’ve exhausted our list of potential parent resources without seeing the needed parameter (:person_id or :group_id), then a LoadAndAuthorizeResource::ParameterMissing error is raised.

Note: load_parent assumes you’ve only nested your route a single layer deep, e.g. /parents/1/children/2 You’re on your own if you want to load multiple nested parents, e.g. /grandfathers/1/parents/2/children/3

If you wish to also allow shallow routes (no parent), you can set the ‘:shallow` option to `true`:

class NotesController < ApplicationController
  load_parent :person, :group, shallow: true
end

The ‘:shallow` option is aliased to `:optional` in cases where it sense to think about parent resources that way. Further, you can call the macro more than once should you want to make some optional and some not:

class NotesController < ApplicationController
  load_parent :person, group, optional: true
  load_parent :book
end

Additionally, a private method is defined with the same name as the resource. The method looks basically like this (if you were to write it yourself):

class NotesController < ApplicationController

  private

  def notes
    if @person
      @person.notes.scoped
    elsif not required(:person)
      Note.scoped
    end
  end
end

You can change the name of this accessor if it is not the same as the resource this controller represents:

class NotesController < ApplicationController
  load_parent :group, children: :people
end

This will create a private method called “people” that either returns ‘@group.people.scoped` or Person.scoped (only if @group is optional).

Parameters:

  • names (Array<String, Symbol>)

    one or more names of resources in lower case

  • options (Hash)

    a customizable set of options



115
116
117
118
119
120
121
# File 'lib/load_and_authorize_resource.rb', line 115

def load_parent(*names)
  options = names.extract_options!.dup
  required = !(options.delete(:shallow) || options.delete(:optional))
  save_nested_resource_options(:load, names, required)
  define_scope_method(names, options.delete(:children))
  before_filter :load_parent, options
end

#load_resource(options = {}) ⇒ Object

Load the resource and set to an instance variable.

For example:

class NotesController < ApplicationController
  load_resource
end

…automatically finds the note for actions ‘show`, `edit`, `update`, and `destroy`.

For the ‘new` action, simply instantiates a new resource. For `create`, instantiates and sets attributes to `<resource>_params`.

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :except (Boolean)

    controller actions to ignore when applying this filter

  • :only (Boolean)

    controller actions to apply this filter (default is show, new, create, edit, update, and destroy)

  • :children (String, Symbol)

    name of child accessor (inferred from controller name, e.g. “notes” for the NotesController)



176
177
178
179
180
181
182
183
# File 'lib/load_and_authorize_resource.rb', line 176

def load_resource(options={})
  options = options.dup
  unless options[:only] or options[:except]
    options.reverse_merge!(only: [:show, :new, :create, :edit, :update, :destroy])
  end
  define_scope_method([], options.delete(:children))
  before_filter :load_resource, options
end

#resource_accessor_nameObject

Returns the name of the resource, in plural form, e.g. “notes”

By default, this is simply the ‘controller_name`.



218
219
220
# File 'lib/load_and_authorize_resource.rb', line 218

def resource_accessor_name
  controller_name
end

#resource_nameObject

Returns the name of the resource, in singular form, e.g. “note”

By default, this is simply ‘controller_name.singularize`.



210
211
212
# File 'lib/load_and_authorize_resource.rb', line 210

def resource_name
  controller_name.singularize
end