heimdallr-resource 1.0.3 → 1.2.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/.rspec +1 -2
- data/CHANGELOG.md +9 -0
- data/README.md +9 -5
- data/heimdallr-resource.gemspec +4 -3
- data/lib/heimdallr-resource.rb +2 -0
- data/lib/heimdallr/resource.rb +21 -191
- data/lib/heimdallr/resource_implementation.rb +190 -0
- data/spec/{resource_spec.rb → controllers/entities_controller_spec.rb} +25 -7
- data/spec/controllers/fluffies_controller_spec.rb +20 -0
- data/spec/controllers/things_controller_spec.rb +31 -0
- data/spec/dummy/app/controllers/{entity_controller.rb → entities_controller.rb} +6 -2
- data/spec/dummy/app/controllers/things_controller.rb +29 -0
- data/spec/dummy/app/models/entity.rb +2 -0
- data/spec/dummy/app/models/thing.rb +16 -0
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/config/routes.rb +6 -5
- data/spec/dummy/db/schema.rb +5 -0
- data/spec/models/resource_implementation_spec.rb +382 -0
- data/spec/models/resource_spec.rb +91 -0
- data/spec/spec_helper.rb +1 -0
- metadata +44 -48
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/config/environments/development.rb +0 -23
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -10
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/fluffies_spec.rb +0 -22
data/.rspec
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
--color
|
2
|
-
--format progress
|
1
|
+
--tty --color --format progress
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.2.0
|
4
|
+
|
5
|
+
* Numerous fixes [@alerticus][], [@voidseeker][]
|
6
|
+
* :instance_name option [@voidseeker][]
|
7
|
+
* :through_association option [@voidseeker][]
|
8
|
+
* Improved specs [@alerticus][], [@voidseeker][]
|
9
|
+
|
3
10
|
## 1.0.2
|
4
11
|
|
5
12
|
* Additional methods resources assignation [@whitequark][]
|
@@ -8,5 +15,7 @@
|
|
8
15
|
|
9
16
|
* load_and_authorize_resource accepts just one hash parameter from now [@_inossidabile][]
|
10
17
|
|
18
|
+
[@voidseeker]: https://github.com/voidseeker
|
19
|
+
[@alerticus]: http://github.com/AlexanderPavlenko
|
11
20
|
[@_inossidabile]: http://twitter.com/#!/_inossidabile
|
12
21
|
[@whitequark]: http://twitter.com/#!/whitequark
|
data/README.md
CHANGED
@@ -5,15 +5,17 @@ Heimdallr Resource is a gem which provides CanCan-like interface for writing sec
|
|
5
5
|
controllers on top of [Heimdallr](http://github.com/roundlake/heimdallr)-protected
|
6
6
|
models.
|
7
7
|
|
8
|
+

|
9
|
+
|
8
10
|
Overview
|
9
11
|
--------
|
10
12
|
|
11
|
-
API of Heimdallr Resource basically consists of two methods, `load_resource` and `
|
13
|
+
API of Heimdallr Resource basically consists of two methods, `load_resource` and `load_and_authorize_resource`.
|
12
14
|
Both work by adding a filter in standard Rails filter chain and obey the `:only` and `:except` options.
|
13
15
|
|
14
16
|
`load_resource` loads a record or scope and wraps it in a Heimadllr proxy. For `index` action, a scope is loaded. For `show`, `new`, `create`, `edit`, `update` and `destroy` a record is loaded. No further action is performed by Heimdallr Resource.
|
15
17
|
|
16
|
-
`
|
18
|
+
`load_and_authorize_resource` loads a record and verifies if the current security context allows for creating, updating or destroying the records. The checks are performed for `new`, `create`, `edit`, `update` and `destroy` actions. `index` and `show` will simply follow the defined `:fetch` scope.
|
17
19
|
|
18
20
|
```ruby
|
19
21
|
class CricketController < ApplicationController
|
@@ -70,7 +72,7 @@ Custom methods (besides CRUD)
|
|
70
72
|
By default Heimdallr Resource will consider non-CRUD methods a `:record` methods (like `show`). So it will try to find entity using `params[:id]`. To modify this behavior to make it work like `index` or `create`, you can explicitly define the way it should handle the methods.
|
71
73
|
|
72
74
|
```ruby
|
73
|
-
load_and_authorize :collection => [:search], :new_record => [:special_create]
|
75
|
+
load_and_authorize :collection => [:search], :new_record => [:special_create]
|
74
76
|
```
|
75
77
|
|
76
78
|
Inlined resources
|
@@ -106,8 +108,10 @@ Credits
|
|
106
108
|
|
107
109
|
<img src="http://roundlake.ru/assets/logo.png" align="right" />
|
108
110
|
|
109
|
-
* Peter Zotov ([@whitequark](http://twitter.com
|
110
|
-
* Boris Staal ([@_inossidabile](http://twitter.com
|
111
|
+
* Peter Zotov ([@whitequark](http://twitter.com/whitequark))
|
112
|
+
* Boris Staal ([@_inossidabile](http://twitter.com/_inossidabile))
|
113
|
+
* Alexander Pavlenko ([@alerticus](https://twitter.com/alerticus))
|
114
|
+
* Shamil Fattakhov ([@voidseeker](https://github.com/voidseeker))
|
111
115
|
|
112
116
|
LICENSE
|
113
117
|
-------
|
data/heimdallr-resource.gemspec
CHANGED
@@ -3,9 +3,9 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "heimdallr-resource"
|
6
|
-
s.version = "1.0
|
7
|
-
s.authors = ["Peter Zotov", "Boris Staal"]
|
8
|
-
s.email = ["whitequark@whitequark.org", "boris@roundlake.ru"]
|
6
|
+
s.version = "1.2.0"
|
7
|
+
s.authors = ["Peter Zotov", "Boris Staal", "Alexander Pavlenko", "Shamil Fattakhov"]
|
8
|
+
s.email = ["whitequark@whitequark.org", "boris@roundlake.ru", "a.pavlenko@roundlake.ru"]
|
9
9
|
s.homepage = "http://github.com/roundlake/heimdallr-resource"
|
10
10
|
s.summary = %q{Heimdallr-Resource provides CanCan-like interface for Heimdallr-secured objects.}
|
11
11
|
s.description = s.summary
|
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
|
18
18
|
s.add_development_dependency "rspec-rails"
|
19
|
+
s.add_development_dependency "rr"
|
19
20
|
s.add_development_dependency "activerecord"
|
20
21
|
s.add_development_dependency "sqlite3"
|
21
22
|
s.add_development_dependency "tzinfo"
|
data/lib/heimdallr/resource.rb
CHANGED
@@ -1,210 +1,40 @@
|
|
1
1
|
module Heimdallr
|
2
|
-
# {AccessDenied} exception is to be raised when access is denied to an action.
|
3
|
-
class AccessDenied < StandardError; end
|
4
|
-
|
5
|
-
module ResourceImplementation
|
6
|
-
class << self
|
7
|
-
def prepare_options(klass, options)
|
8
|
-
options = options.merge :resource => (options[:resource] || klass.name.sub(/Controller$/, '').underscore).to_s
|
9
|
-
|
10
|
-
filter_options = {}
|
11
|
-
filter_options[:only] = options.delete(:only) if options.has_key?(:only)
|
12
|
-
filter_options[:except] = options.delete(:except) if options.has_key?(:except)
|
13
|
-
|
14
|
-
[ options, filter_options ]
|
15
|
-
end
|
16
|
-
|
17
|
-
def load(controller, options)
|
18
|
-
unless controller.instance_variable_defined?(ivar_name(controller, options))
|
19
|
-
if options.has_key? :through
|
20
|
-
target = load_target(controller, options)
|
21
|
-
|
22
|
-
if target
|
23
|
-
if options[:singleton]
|
24
|
-
scope = target.send(:"#{variable_name(options)}")
|
25
|
-
else
|
26
|
-
scope = target.send(:"#{variable_name(options).pluralize}")
|
27
|
-
end
|
28
|
-
elsif options[:shallow]
|
29
|
-
scope = class_name(options).constantize.scoped
|
30
|
-
else
|
31
|
-
raise "Cannot fetch #{options[:resource]} via #{options[:through]}"
|
32
|
-
end
|
33
|
-
else
|
34
|
-
scope = class_name(options).constantize.scoped
|
35
|
-
end
|
36
|
-
|
37
|
-
loaders = {
|
38
|
-
collection: -> {
|
39
|
-
controller.instance_variable_set(ivar_name(controller, options), scope)
|
40
|
-
},
|
41
|
-
|
42
|
-
new_record: -> {
|
43
|
-
controller.instance_variable_set(
|
44
|
-
ivar_name(controller, options),
|
45
|
-
scope.new(controller.params[params_key_name(options)] || {})
|
46
|
-
)
|
47
|
-
},
|
48
|
-
|
49
|
-
record: -> {
|
50
|
-
controller.instance_variable_set(
|
51
|
-
ivar_name(controller, options),
|
52
|
-
scope.find([:"#{params_key_name(options)}_id", :id].map{|key| controller.params[key] }.reject(&:blank?)[0])
|
53
|
-
)
|
54
|
-
},
|
55
|
-
|
56
|
-
related_record: -> {
|
57
|
-
unless controller.params[:"#{params_key_name(options)}_id"].blank?
|
58
|
-
controller.instance_variable_set(
|
59
|
-
ivar_name(controller, options),
|
60
|
-
scope.find(controller.params[:"#{params_key_name(options)}_id"])
|
61
|
-
)
|
62
|
-
end
|
63
|
-
}
|
64
|
-
}
|
65
|
-
|
66
|
-
loaders[action_type(controller.params[:action], options)].()
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def authorize(controller, options)
|
71
|
-
value = controller.instance_variable_get(ivar_name(controller, options))
|
72
|
-
return unless value
|
73
|
-
|
74
|
-
controller.instance_variable_set(ivar_name(controller, options.merge(:insecure => true)), value)
|
75
|
-
|
76
|
-
value = value.restrict(controller.security_context)
|
77
|
-
controller.instance_variable_set(ivar_name(controller, options), value)
|
78
|
-
|
79
|
-
case controller.params[:action]
|
80
|
-
when 'new', 'create'
|
81
|
-
value.assign_attributes(value.reflect_on_security[:restrictions].fixtures[:create])
|
82
|
-
|
83
|
-
unless value.reflect_on_security[:operations].include? :create
|
84
|
-
raise Heimdallr::AccessDenied, "Cannot create model"
|
85
|
-
end
|
86
|
-
|
87
|
-
when 'edit', 'update'
|
88
|
-
value.assign_attributes(value.reflect_on_security[:restrictions].fixtures[:update])
|
89
|
-
|
90
|
-
unless value.reflect_on_security[:operations].include? :update
|
91
|
-
raise Heimdallr::AccessDenied, "Cannot update model"
|
92
|
-
end
|
93
|
-
|
94
|
-
when 'destroy'
|
95
|
-
unless value.destroyable?
|
96
|
-
raise Heimdallr::AccessDenied, "Cannot delete model"
|
97
|
-
end
|
98
|
-
end unless options[:related]
|
99
|
-
end
|
100
|
-
|
101
|
-
def load_target(controller, options)
|
102
|
-
Array.wrap(options[:through]).map do |parent|
|
103
|
-
loaded = controller.instance_variable_get(:"@#{variable_name parent}")
|
104
|
-
unless loaded
|
105
|
-
load(controller, :resource => parent.to_s, :related => true)
|
106
|
-
loaded = controller.instance_variable_get(:"@#{variable_name parent}")
|
107
|
-
end
|
108
|
-
if loaded && options[:authorize_chain]
|
109
|
-
authorize(controller, :resource => parent.to_s, :related => true)
|
110
|
-
end
|
111
|
-
controller.instance_variable_get(:"@#{variable_name parent}")
|
112
|
-
end.reject(&:nil?).first
|
113
|
-
end
|
114
|
-
|
115
|
-
def ivar_name(controller, options)
|
116
|
-
if action_type(controller.params[:action], options) == :collection
|
117
|
-
:"@#{variable_name(options).pluralize}"
|
118
|
-
else
|
119
|
-
:"@#{variable_name(options)}"
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def action_type(action, options)
|
124
|
-
if options[:related]
|
125
|
-
:related_record
|
126
|
-
else
|
127
|
-
action = action.to_sym
|
128
|
-
case action
|
129
|
-
when :index
|
130
|
-
:collection
|
131
|
-
when :new, :create
|
132
|
-
:new_record
|
133
|
-
when :show, :edit, :update, :destroy
|
134
|
-
:record
|
135
|
-
else
|
136
|
-
if options[:collection] && options[:collection].include?(action)
|
137
|
-
:collection
|
138
|
-
elsif options[:new] && options[:new].include?(action)
|
139
|
-
:new_record
|
140
|
-
else
|
141
|
-
:record
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
def variable_name(options)
|
148
|
-
if options.kind_of? Hash
|
149
|
-
options[:resource]
|
150
|
-
else
|
151
|
-
options.to_s
|
152
|
-
end.parameterize('_')
|
153
|
-
end
|
154
|
-
|
155
|
-
def class_name(options)
|
156
|
-
if options.kind_of? Hash
|
157
|
-
options[:resource]
|
158
|
-
else
|
159
|
-
options.to_s
|
160
|
-
end.classify
|
161
|
-
end
|
162
|
-
|
163
|
-
def params_key_name(options)
|
164
|
-
if options.kind_of? Hash
|
165
|
-
options[:resource]
|
166
|
-
else
|
167
|
-
options.to_s
|
168
|
-
end.split('/').last
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
2
|
|
173
3
|
# {Resource} is a mixin providing CanCan-like interface for Rails controllers.
|
174
4
|
module Resource
|
175
5
|
extend ActiveSupport::Concern
|
176
6
|
|
177
7
|
module ClassMethods
|
178
|
-
def
|
179
|
-
|
180
|
-
load_resource(options)
|
181
|
-
authorize_resource(options)
|
8
|
+
def load_resource(options = {})
|
9
|
+
Heimdallr::ResourceImplementation.add_before_filter self, :load_resource, options
|
182
10
|
end
|
183
11
|
|
184
|
-
def
|
185
|
-
|
186
|
-
self.own_heimdallr_options = options
|
187
|
-
|
188
|
-
before_filter filter_options do |controller|
|
189
|
-
Heimdallr::ResourceImplementation.load(controller, options)
|
190
|
-
end
|
12
|
+
def load_and_authorize_resource(options = {})
|
13
|
+
Heimdallr::ResourceImplementation.add_before_filter self, :load_and_authorize_resource, options
|
191
14
|
end
|
192
15
|
|
193
|
-
def
|
194
|
-
options
|
195
|
-
|
196
|
-
|
197
|
-
before_filter filter_options do |controller|
|
198
|
-
Heimdallr::ResourceImplementation.authorize(controller, options)
|
16
|
+
def skip_authorization_check(options = {})
|
17
|
+
prepend_before_filter options do |controller|
|
18
|
+
controller.instance_variable_set :@_skip_authorization_check, true
|
199
19
|
end
|
200
20
|
end
|
201
21
|
|
202
|
-
|
203
|
-
|
22
|
+
protected
|
204
23
|
def own_heimdallr_options=(options)
|
205
|
-
|
24
|
+
class << self
|
25
|
+
attr_accessor :heimdallr_options
|
26
|
+
end
|
206
27
|
self.heimdallr_options = options
|
207
28
|
end
|
208
29
|
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
def skip_authorization_check?
|
33
|
+
@_skip_authorization_check
|
34
|
+
end
|
209
35
|
end
|
210
|
-
|
36
|
+
|
37
|
+
# {AccessDenied} exception is to be raised when access is denied to an action.
|
38
|
+
class AccessDenied < StandardError; end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
module Heimdallr
|
2
|
+
class ResourceImplementation
|
3
|
+
def self.add_before_filter(controller_class, method, options)
|
4
|
+
options, filter_options = Heimdallr::ResourceImplementation.prepare_options controller_class, options
|
5
|
+
controller_class.send :own_heimdallr_options=, options
|
6
|
+
|
7
|
+
controller_class.class_eval do
|
8
|
+
before_filter filter_options do |controller|
|
9
|
+
Heimdallr::ResourceImplementation.new(controller, options).send method
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.prepare_options(controller_class, options)
|
15
|
+
options = options.dup
|
16
|
+
options[:resource] ||= controller_class.name.sub(/Controller$/, '').singularize.underscore
|
17
|
+
|
18
|
+
filter_keys = [:only, :except]
|
19
|
+
|
20
|
+
filter_options = filter_keys.inject({}) do |hash, key|
|
21
|
+
hash[key] = options.delete key if options.has_key? key
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
|
25
|
+
[options, filter_options]
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize(controller, options)
|
29
|
+
@controller = controller
|
30
|
+
@options = options
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_resource
|
34
|
+
ResourceLoader.new(@controller, @options).load
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_and_authorize_resource
|
38
|
+
resource = ResourceLoader.new(@controller, @options, :restricted => true).load
|
39
|
+
authorize_resource resource unless @controller.send :skip_authorization_check?
|
40
|
+
resource
|
41
|
+
end
|
42
|
+
|
43
|
+
def authorize_resource(resource)
|
44
|
+
case @controller.params[:action]
|
45
|
+
when 'new', 'create'
|
46
|
+
raise Heimdallr::AccessDenied, "Cannot create model" unless resource.creatable?
|
47
|
+
resource.assign_attributes resource.reflect_on_security[:restrictions].fixtures[:create]
|
48
|
+
|
49
|
+
when 'edit', 'update'
|
50
|
+
raise Heimdallr::AccessDenied, "Cannot update model" unless resource.modifiable?
|
51
|
+
resource.assign_attributes resource.reflect_on_security[:restrictions].fixtures[:update]
|
52
|
+
|
53
|
+
when 'destroy'
|
54
|
+
raise Heimdallr::AccessDenied, "Cannot delete model" unless resource.destroyable?
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class ResourceLoader
|
59
|
+
def initialize(controller, options, loader_options = {})
|
60
|
+
@restricted = loader_options[:restricted]
|
61
|
+
@parent = loader_options[:parent]
|
62
|
+
@controller = controller
|
63
|
+
@options = options
|
64
|
+
@params = controller.params
|
65
|
+
end
|
66
|
+
|
67
|
+
def load
|
68
|
+
return @controller.instance_variable_get(ivar_name) if @controller.instance_variable_defined? ivar_name
|
69
|
+
|
70
|
+
if !@parent && @options.has_key?(:through)
|
71
|
+
parent_resource = load_parent
|
72
|
+
raise "Cannot fetch #{@options[:resource]} through #{@options[:through]}" unless parent_resource || @options[:shallow]
|
73
|
+
else
|
74
|
+
parent_resource = nil
|
75
|
+
end
|
76
|
+
|
77
|
+
resource = self.send action_type, resource_scope(parent_resource), parent_resource
|
78
|
+
@controller.instance_variable_set ivar_name, resource unless resource.nil?
|
79
|
+
resource
|
80
|
+
end
|
81
|
+
|
82
|
+
def load_parent
|
83
|
+
Array.wrap(@options[:through]).map { |parent|
|
84
|
+
ResourceLoader.new(@controller, {:resource => parent}, :restricted => @restricted, :parent => true).load
|
85
|
+
}.reject(&:nil?).first
|
86
|
+
end
|
87
|
+
|
88
|
+
def resource_scope(parent_resource)
|
89
|
+
if parent_resource
|
90
|
+
if @options[:through_association]
|
91
|
+
parent_resource.send @options[:through_association]
|
92
|
+
elsif @options[:singleton]
|
93
|
+
parent_resource.send :"#{variable_name}"
|
94
|
+
else
|
95
|
+
parent_resource.send :"#{variable_name.pluralize}"
|
96
|
+
end
|
97
|
+
else
|
98
|
+
if @restricted
|
99
|
+
class_name.constantize.restrict(@controller.security_context)
|
100
|
+
else
|
101
|
+
class_name.constantize.scoped
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def collection(scope, parent_resource)
|
107
|
+
scope
|
108
|
+
end
|
109
|
+
|
110
|
+
def new_resource(scope, parent_resource)
|
111
|
+
attributes = @params[params_key_name] || {}
|
112
|
+
|
113
|
+
if @options[:singleton] && parent_resource
|
114
|
+
if scope.nil?
|
115
|
+
parent_resource.send singleton_builder_name, attributes
|
116
|
+
else
|
117
|
+
scope.assign_attributes attributes
|
118
|
+
scope
|
119
|
+
end
|
120
|
+
else
|
121
|
+
scope.new attributes
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def resource(scope, parent_resource)
|
126
|
+
if @options[:singleton] && parent_resource
|
127
|
+
scope
|
128
|
+
else
|
129
|
+
key = [:"#{params_key_name}_id", :id].map{|key| @params[key] }.find &:present?
|
130
|
+
scope.send(@options[:finder] || :find, key)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def parent_resource(scope, parent_resource)
|
135
|
+
key = @params[:"#{params_key_name}_id"]
|
136
|
+
return if key.blank?
|
137
|
+
scope.send(@options[:finder] || :find, key)
|
138
|
+
end
|
139
|
+
|
140
|
+
def action_type
|
141
|
+
if @parent
|
142
|
+
:parent_resource
|
143
|
+
else
|
144
|
+
case action = @params[:action].to_sym
|
145
|
+
when :index
|
146
|
+
:collection
|
147
|
+
when :new, :create
|
148
|
+
:new_resource
|
149
|
+
when :show, :edit, :update, :destroy
|
150
|
+
:resource
|
151
|
+
else
|
152
|
+
if @options[:collection] && @options[:collection].include?(action)
|
153
|
+
:collection
|
154
|
+
elsif @options[:new_record] && @options[:new_record].include?(action)
|
155
|
+
:new_resource
|
156
|
+
else
|
157
|
+
:resource
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def ivar_name
|
164
|
+
name = (@options[:instance_name] || variable_name).to_s
|
165
|
+
name = name.pluralize if action_type == :collection
|
166
|
+
:"@#{name}"
|
167
|
+
end
|
168
|
+
|
169
|
+
def resource_name
|
170
|
+
@options[:resource].to_s
|
171
|
+
end
|
172
|
+
|
173
|
+
def variable_name
|
174
|
+
resource_name.parameterize('_')
|
175
|
+
end
|
176
|
+
|
177
|
+
def class_name
|
178
|
+
resource_name.classify
|
179
|
+
end
|
180
|
+
|
181
|
+
def params_key_name
|
182
|
+
resource_name.split('/').last
|
183
|
+
end
|
184
|
+
|
185
|
+
def singleton_builder_name
|
186
|
+
:"build_#{@options[:through_association] || variable_name}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|