Class: ActionController::Permitter

Inherits:
Object
  • Object
show all
Defined in:
lib/action_controller/permitter.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params, user, authorizer = nil) ⇒ Permitter

Returns a new instance of Permitter.



53
54
55
# File 'lib/action_controller/permitter.rb', line 53

def initialize(params, user, authorizer = nil)
  @params, @user, @authorizer = params, user, authorizer
end

Class Method Details

.inherited(subclass) ⇒ Object

When Permitter is inherited, it sets the resource (the symbol for params.require(some_sym)) to the unnamespaced model class that corresponds to the Permitter’s classname, e.g. by default A::B::ApplesController will use A::B::ApplePermitter which will do params.permit(:apple). To change this value, use the ‘resource` class method.



15
16
17
18
19
20
21
22
# File 'lib/action_controller/permitter.rb', line 15

def inherited(subclass)
  subclass.class_eval do
    class_attribute :permitted_attributes, :resource_name_override
    private_class_method :resource_name_override, :resource_name_override=

    self.permitted_attributes = []
  end
end

.permit(*args) ⇒ Object



24
25
26
27
28
29
30
# File 'lib/action_controller/permitter.rb', line 24

def permit(*args)
  options = args.extract_options!

  args.each do |name|
    self.permitted_attributes += [ActionController::PermitterAttribute.new(name, options)]
  end
end

.resource(name) ⇒ Object



38
39
40
# File 'lib/action_controller/permitter.rb', line 38

def resource(name)
  self.resource_name_override = name
end

.resource_nameObject



42
43
44
45
46
47
48
49
50
# File 'lib/action_controller/permitter.rb', line 42

def resource_name
  name = self.name

  # in Rails 3.2+ could do:
  # name.demodulize.chomp('Permitter').underscore.to_sym
  # Rails < 3.2
  last_index = name.rindex('::')
  resource_name_override || (last_index ? name[(last_index+2)..-1] : name).chomp('Permitter').underscore.to_sym
end

.scope(name) ⇒ Object



32
33
34
35
36
# File 'lib/action_controller/permitter.rb', line 32

def scope(name)
  with_options :scope => name do |nested|
    yield nested
  end
end

Instance Method Details

#authorize!(*args, &block) ⇒ Object



86
87
88
89
# File 'lib/action_controller/permitter.rb', line 86

def authorize!(*args, &block)
  # implementing here is clearer than doing a delegate :authorize!, :to => :authorizer, imo.
  authorizer ? authorizer.__send__(:authorize!, *args, &block) : nil
end

#permitted_paramsObject



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/action_controller/permitter.rb', line 57

def permitted_params
  scopes = {}
  unscoped_attributes = []

  permitted_attributes.each do |attribute|
    scope_name = attribute.options[:scope]
    (scope_name ? (scopes[scope_name] ||= []) : unscoped_attributes) << attribute.name
  end

  # class_attribute creates an instance method called resource_name, which we'll allow overriding of in the permitter definition, if desired for some odd reason.
  @filtered_params ||= params.require(resource_name).permit(*unscoped_attributes, scopes)

  permitted_attributes.select {|a| a.options[:authorize]}.each do |attribute|
    scope_name = attribute.options[:scope]
    values = scope_name ? Array.wrap(@filtered_params[scope_name]).collect {|hash| hash[attribute.name]}.compact : Array.wrap(@filtered_params[attribute.name])
    klass_name = attribute.options[:as].try(:to_s) || attribute.name.to_s.split(/(.+)_ids?/)[1]
    raise PermitterError.new("Cannot permit #{attribute.name.inspect} unless you specify the the attribute name (e.g. :something_id or :something_ids), or a class name via the :as option (e.g. :as => Something)") unless klass_name
    klass = klass_name.classify.constantize

    values.each do |record_id|
      record = klass.find record_id
      permission = attribute.options[:authorize].to_sym || :read
      authorize! permission, record
    end
  end

  @filtered_params
end

#resource_nameObject



91
92
93
# File 'lib/action_controller/permitter.rb', line 91

def resource_name
  self.class.resource_name
end