modify_resource 0.0.1
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +46 -0
- data/Rakefile +11 -0
- data/lib/modify_resource/rails/action_controller/modify_resource.rb +236 -0
- data/lib/modify_resource/rails/action_controller/resource_info.rb +22 -0
- data/lib/modify_resource/rails/action_controller/router.rb +11 -0
- data/lib/modify_resource/rails/action_controller/update_as.rb +87 -0
- data/lib/modify_resource/rails/active_model/update_permitted_attributes.rb +90 -0
- data/lib/modify_resource/rails/active_record/mixed_identifier_for_user_resource.rb +50 -0
- data/lib/modify_resource/version.rb +3 -0
- data/lib/modify_resource.rb +22 -0
- data/modify_resource.gemspec +21 -0
- data/test/modify_resource_test.rb +1 -0
- data/test/test_helper.rb +0 -0
- metadata +95 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Colin Young
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# ModifyResource
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
Add this line to your application's Gemfile:
|
6
|
+
|
7
|
+
gem 'modify_resource'
|
8
|
+
|
9
|
+
And then execute:
|
10
|
+
|
11
|
+
$ bundle
|
12
|
+
|
13
|
+
Or install it yourself as:
|
14
|
+
|
15
|
+
$ gem install modify_resource
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
#### Including
|
20
|
+
|
21
|
+
Just include `ModifyResource` in your controller, or, if you want it available in your entire application:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
# application.rb
|
25
|
+
class ApplicationController < ActionController::Base
|
26
|
+
|
27
|
+
class << self
|
28
|
+
include Rails.application.routes.url_helpers
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
#### `redirect_to`
|
35
|
+
|
36
|
+
You can change how your successful `create`s or `update`s are handled by changing where they redirect to in the `options` hash.
|
37
|
+
|
38
|
+
Note: If you want to use the `:redirect_to` option, and you want to use Rails routes, you'll need to `include ActionController::Base` in your controller (or ApplicationController) that you also `include ModifyResource` in.
|
39
|
+
|
40
|
+
## Contributing
|
41
|
+
|
42
|
+
1. Fork it
|
43
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
44
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
45
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
46
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
require_relative 'resource_info'
|
2
|
+
require_relative 'router'
|
3
|
+
|
4
|
+
module ActionController
|
5
|
+
|
6
|
+
module ModifyResource
|
7
|
+
include ResourceInfo
|
8
|
+
include ActionView::Helpers::TextHelper
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# A shortcut - just add modify_on :create, :update
|
13
|
+
# if your variable is the controller's name -- e.g. @widget in WidgetsController
|
14
|
+
def modify_on(*actions)
|
15
|
+
# Define in the method so that the user could override if they wanted
|
16
|
+
options = actions.extract_options!
|
17
|
+
actions.each do |action|
|
18
|
+
unless method_defined?(action)
|
19
|
+
define_method action do
|
20
|
+
modify_resource_with action, options
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# :nodoc:
|
28
|
+
def self.included(base)
|
29
|
+
base.extend(ClassMethods)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Handles the usual @var = Model.find(params[:id]); @var.save
|
33
|
+
# etc. stuff.
|
34
|
+
def modify_resource_with(*args) # ([res=nil, ], verb=:update, options={}, args=nil)
|
35
|
+
# Set var to resource matching controller's name if res is a symbol
|
36
|
+
if args.first.is_a? Symbol or args.first.is_a? String
|
37
|
+
res = instance_variable_get(:"@#{resource_name}")
|
38
|
+
else
|
39
|
+
res = args.shift
|
40
|
+
end
|
41
|
+
|
42
|
+
# Set up default values
|
43
|
+
verb = args[0] || :update
|
44
|
+
options = args[1] || {}
|
45
|
+
_params = args[2] || nil
|
46
|
+
as_user = nil
|
47
|
+
|
48
|
+
# model_name is this res's model_name
|
49
|
+
model_name = res.class.model_name.underscore.downcase
|
50
|
+
|
51
|
+
# Grab params if not set
|
52
|
+
_params ||= params[model_name]
|
53
|
+
|
54
|
+
# We may need the current user instance
|
55
|
+
options[:as_current] ||= options[:as_user] # Backwards compat
|
56
|
+
|
57
|
+
if options[:as_current] and res.respond_to?(:as_user)
|
58
|
+
res.as_user = self.send "current_#{options[:as_current]}"
|
59
|
+
end
|
60
|
+
|
61
|
+
# Actually perform update, or create, destroy, etc.
|
62
|
+
modified = case verb
|
63
|
+
when :update
|
64
|
+
res.update_permitted_attributes(_params)
|
65
|
+
when :create
|
66
|
+
res.deep_attributes = _params
|
67
|
+
res.persisted?
|
68
|
+
else
|
69
|
+
res.method(verb).arity == 0 ? res.send(verb) : res.send(verb, _params)
|
70
|
+
end
|
71
|
+
|
72
|
+
# the resource was updated
|
73
|
+
instance_variable_set :"@#{resource_name}", res
|
74
|
+
|
75
|
+
raise 'As_user MUST be unset on ALL items.' if res.valid? and res.as_user.present?
|
76
|
+
|
77
|
+
# We're updating a nested resource, so we need to set its parent for it
|
78
|
+
update_resource_parent(res) unless parent_for(res).present?
|
79
|
+
|
80
|
+
# Actually save or create.
|
81
|
+
if modified
|
82
|
+
|
83
|
+
unless request.xhr?
|
84
|
+
|
85
|
+
options[:redirect_with_resources] ||= [ :self ]
|
86
|
+
after = params[:after]
|
87
|
+
unless (path = options[:redirect_to]).blank?
|
88
|
+
router = Router.new
|
89
|
+
success_path = if options[:redirect_with_resources].blank?
|
90
|
+
router.send path
|
91
|
+
else
|
92
|
+
router.send path, *collect_resources_for(res, options[:redirect_with_resources])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
success_path ||= resource_path_with_base(:production, res)
|
96
|
+
|
97
|
+
msg = options[:success].try(:call, res)
|
98
|
+
|
99
|
+
if msg.blank?
|
100
|
+
|
101
|
+
msg = "#{action_name.capitalize.gsub(/e$/,'')}ed "
|
102
|
+
|
103
|
+
if after.present? and after.pluralize == after
|
104
|
+
# Redirect to the plural (index) page
|
105
|
+
model_name = params[:after]
|
106
|
+
msg << model_name.pluralize
|
107
|
+
success_path << '/' + after
|
108
|
+
else
|
109
|
+
# Redirect to the show page for the resource.
|
110
|
+
# Flash is like 'Widget 2 has been updated'.
|
111
|
+
name = String.new.tap do |s|
|
112
|
+
break s = res.title if res.respond_to? :title
|
113
|
+
break s = res.name if res.respond_to? :name
|
114
|
+
s = res.id
|
115
|
+
end
|
116
|
+
msg << "#{model_name.humanize.downcase} '#{truncate(name, length: 20)}'"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
flash[:notice] = msg
|
121
|
+
redirect_to success_path
|
122
|
+
else
|
123
|
+
render json: res
|
124
|
+
end
|
125
|
+
else
|
126
|
+
messages = res.errors.messages
|
127
|
+
unless request.xhr?
|
128
|
+
flash[:error] = messages
|
129
|
+
begin
|
130
|
+
render :edit
|
131
|
+
rescue
|
132
|
+
# They didn't respond to that action
|
133
|
+
if res.persisted?
|
134
|
+
render :show
|
135
|
+
else
|
136
|
+
render :new
|
137
|
+
end
|
138
|
+
end
|
139
|
+
else
|
140
|
+
render json: {errors: messages}, status: :unprocessable_entity
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
# :nodoc:
|
148
|
+
def resource_path_with_base(base, res)
|
149
|
+
components, resources = path_components_for(res, base).try(:compact)
|
150
|
+
|
151
|
+
return url_for unless components.present?
|
152
|
+
|
153
|
+
unless components.nil? || components.empty?
|
154
|
+
path = components.join('_') + '_path'
|
155
|
+
send(path, *resources)
|
156
|
+
else
|
157
|
+
:"#{base.to_s.pluralize}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# :nodoc: Climbs up the resource's parent associations to generate a rails route
|
162
|
+
def path_components_for(res, base, components=[], resources=[])
|
163
|
+
return nil unless res.present?
|
164
|
+
|
165
|
+
component = component_for(res)
|
166
|
+
|
167
|
+
# Redirect to the index if the res was just deleted
|
168
|
+
component = component.pluralize unless res.persisted?
|
169
|
+
|
170
|
+
components.unshift component
|
171
|
+
resources.unshift res if res.persisted?
|
172
|
+
|
173
|
+
unless component.to_s == base.to_s
|
174
|
+
path_components_for(parent_for(res), base, components, resources)
|
175
|
+
else
|
176
|
+
[components, resources]
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# :nodoc: gets path component for a resource
|
181
|
+
def component_for(res)
|
182
|
+
res.class.model_name.downcase
|
183
|
+
end
|
184
|
+
|
185
|
+
# :nodoc: gets a nested resource's parent
|
186
|
+
def parent_for(res)
|
187
|
+
parents = possible_parents_for(res)
|
188
|
+
return nil unless parents.count == 1
|
189
|
+
|
190
|
+
component = component_for(res)
|
191
|
+
parent_component = parents[0].sub('_id', '')
|
192
|
+
res.send(parent_component)
|
193
|
+
end
|
194
|
+
|
195
|
+
# :nodoc: gets possible parents based on attributes ending in '_id'
|
196
|
+
def possible_parents_for(res)
|
197
|
+
Array.new.tap do |possibilities|
|
198
|
+
res.attributes.keys.each do |field|
|
199
|
+
next unless field[/_id$/]
|
200
|
+
cleaned = field.sub '_id', ''
|
201
|
+
# Fields that end in _id but do not point to a constant are ignored.
|
202
|
+
possibilities << cleaned if Object.const_defined? cleaned.classify
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# :nodoc: Adds the resource to its parent
|
208
|
+
def update_resource_parent(res)
|
209
|
+
parents = possible_parents_for(res)
|
210
|
+
return if parents.empty? or parents.count > 1
|
211
|
+
|
212
|
+
if parents.count > 1
|
213
|
+
raise "Can't guess parent, multiple options for resource.\n#{res.inspect}\n#{parents.inspect}"
|
214
|
+
end
|
215
|
+
|
216
|
+
parent_class = parents.first.classify.constantize
|
217
|
+
parent_name = parent_class.model_name.downcase
|
218
|
+
parent_param = parent_name + '_id'
|
219
|
+
parent = parent_class.find(params[parent_param])
|
220
|
+
return unless parent.present?
|
221
|
+
|
222
|
+
instance_variable_set :"@#{parent_name}", parent
|
223
|
+
|
224
|
+
child_name = res.class.model_name.downcase.pluralize
|
225
|
+
child_name = child_name.singularize if !parent.respond_to?(child_name)
|
226
|
+
|
227
|
+
association = parent.send(child_name)
|
228
|
+
association << res
|
229
|
+
end
|
230
|
+
|
231
|
+
# Converts a list of symbols into the items necessary to compose redirection URLS
|
232
|
+
def collect_resources_for res, arr
|
233
|
+
arr.collect { |i| res.send(i) }
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActionController
|
2
|
+
module ModifyResource
|
3
|
+
module ResourceInfo
|
4
|
+
|
5
|
+
def resource_name
|
6
|
+
controller_name[/(\w+)$/].singularize
|
7
|
+
end
|
8
|
+
|
9
|
+
def model_class
|
10
|
+
resource_name.capitalize.constantize
|
11
|
+
end
|
12
|
+
|
13
|
+
def resource
|
14
|
+
res = instance_variable_get "@#{resource_name}"
|
15
|
+
begin
|
16
|
+
res ||= model_class.find params[:id]
|
17
|
+
rescue; end
|
18
|
+
res
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module ActionController
|
2
|
+
|
3
|
+
module UpdateAs
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
|
7
|
+
def update_as_current(user_class=:user, nested_resources={})
|
8
|
+
append_before_filter do
|
9
|
+
return unless [:PUT, :POST, :PATCH].include?(request.method.to_sym) and
|
10
|
+
params[:_method] != "delete"
|
11
|
+
|
12
|
+
update_as(self.send(:"current_#{user_class}"), resource, nested_resources)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def update_as_current_user(nested_resources={})
|
17
|
+
update_as_current :user, nested_resources
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def update_as(user, current_resource, nested_resources={})
|
23
|
+
case nested_resources
|
24
|
+
when Symbol, String, Array
|
25
|
+
update_resource(current_resource, Array(nested_resources), as: user)
|
26
|
+
else
|
27
|
+
return update_resource(current_resource, as: user) if nested_resources.empty?
|
28
|
+
|
29
|
+
nested_resources.each do |res, fields|
|
30
|
+
res = if res.to_s == current_resource.class.name.downcase
|
31
|
+
current_resource
|
32
|
+
else
|
33
|
+
current_resource.send(res)
|
34
|
+
end
|
35
|
+
update_resource res, fields, as: user
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.included(base)
|
41
|
+
base.extend(ClassMethods)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def add_user_id_to(hash_or_user, user_hash)
|
47
|
+
return unless hash_or_user.present?
|
48
|
+
raise UserNotProvidedError unless user = user_hash[:as]
|
49
|
+
user_class = user.class.model_name.downcase.underscore # 'user', etc.
|
50
|
+
|
51
|
+
case hash_or_user
|
52
|
+
when Hash
|
53
|
+
hash_or_user[:"#{user_class}_identifier"] = user.id
|
54
|
+
else
|
55
|
+
hash_or_user.send :"#{user_class}=", user
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def update_resource(*args) # resource, (optional: fields=[]), user_hash={}
|
60
|
+
resource = args.first
|
61
|
+
user_hash = args.last
|
62
|
+
raise UserNotProvidedError unless user = user_hash[:as]
|
63
|
+
fields = args[1] if args.count > 2
|
64
|
+
|
65
|
+
resource_name = resource.class.name.downcase
|
66
|
+
parameters = params[resource_name]
|
67
|
+
|
68
|
+
if parameters.present? and fields.present?
|
69
|
+
fields.each do |field|
|
70
|
+
|
71
|
+
field_attribute = field.to_s + '_attributes' unless field[/_attributes/].present?
|
72
|
+
handle = parameters[field_attribute]
|
73
|
+
|
74
|
+
handle = [handle] unless handle.is_a?(Array)
|
75
|
+
handle.each do |individual_resource|
|
76
|
+
add_user_id_to(individual_resource, as: user)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
else
|
80
|
+
add_user_id_to(resource, as: user)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class UserNotProvidedError < StandardError
|
87
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
|
3
|
+
# This variable is to aid models methods that need the current user.
|
4
|
+
# It is very different from solutions that use Thread --
|
5
|
+
# 1. First of all, it's paired with modify_resource_with, and
|
6
|
+
# 2. I've hooked into after_save to double-ensure that the
|
7
|
+
# @as_user variable is unset after any change.
|
8
|
+
|
9
|
+
module UpdatePermittedAttributes
|
10
|
+
def update_permitted_attributes(attributes)
|
11
|
+
if attributes.all_permitted?
|
12
|
+
update_attributes(attributes, without_protection: true)
|
13
|
+
else
|
14
|
+
update_attributes(attributes)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def deep_attributes=(attributes)
|
19
|
+
attributes.each do |key, value|
|
20
|
+
next unless key.to_s[m = /_attributes$/]
|
21
|
+
nested = self.send key.gsub(m, '')
|
22
|
+
if nested.respond_to? :each
|
23
|
+
self.send(nested).each do |built|
|
24
|
+
value.map { |sub_params| built.attributes = sub_params }
|
25
|
+
end
|
26
|
+
attributes.delete(key)
|
27
|
+
else
|
28
|
+
nested.attributes = value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
self.attributes = attributes
|
32
|
+
save
|
33
|
+
end
|
34
|
+
|
35
|
+
# Hook into models that accept nested attributes.
|
36
|
+
module ClassMethods
|
37
|
+
|
38
|
+
def accepts_nested_attributes_for(field, options={})
|
39
|
+
|
40
|
+
before_validation do
|
41
|
+
return unless @as_user.present?
|
42
|
+
child = self.send(field)
|
43
|
+
|
44
|
+
# Copy down the chain as needed.
|
45
|
+
# As_user will be unset on both models after save.
|
46
|
+
if child.respond_to? :map
|
47
|
+
children = child
|
48
|
+
children.map {|c| c.as_user = @as_user }
|
49
|
+
else
|
50
|
+
child.try(:as_user=, @as_user)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
super(field, options)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
# Add/override statechanging methods to ensure @as_user is unset
|
60
|
+
def self.included(base)
|
61
|
+
# We need ActiveModel callbacks
|
62
|
+
base.extend ActiveModel::Callbacks
|
63
|
+
|
64
|
+
# Add our stuff
|
65
|
+
base.send :attr_accessor, :as_user
|
66
|
+
base.extend ClassMethods
|
67
|
+
|
68
|
+
[:after_save, :after_destroy].each do |m|
|
69
|
+
base.send(m) do
|
70
|
+
self.as_user = nil
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
ActiveRecord::Base.send :include, ActiveModel::UpdatePermittedAttributes
|
79
|
+
|
80
|
+
class Hash
|
81
|
+
|
82
|
+
def all_permitted?
|
83
|
+
self.each do |key, value|
|
84
|
+
if value.is_a?(Hash)
|
85
|
+
return true unless value.respond_to? :all_permitted? # For those without security enabled.
|
86
|
+
return false if !value.all_permitted? and !key.numeric?
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module MixedIdentifierForUserResource
|
2
|
+
def has_mixed_identifier_for(user_resource, options={})
|
3
|
+
|
4
|
+
user_resource = user_resource.to_s
|
5
|
+
|
6
|
+
self.send :attr_accessible, :"#{user_resource}_identifier"
|
7
|
+
|
8
|
+
instance_eval <<-END
|
9
|
+
validate :"#{user_resource}_identifier", presence: true
|
10
|
+
END
|
11
|
+
|
12
|
+
class_eval <<-END
|
13
|
+
def #{user_resource}_identifier=(identifier)
|
14
|
+
if identifier.is_a? Fixnum or identifier.numeric? or identifier.parameter_id?
|
15
|
+
self.#{user_resource}_id = identifier
|
16
|
+
else
|
17
|
+
# Try to uncover the as_user of either this resource or the parent
|
18
|
+
self.#{user_resource} = #{user_resource.classify}.find_or_initialize_by_email(identifier)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def #{user_resource}_identifier
|
23
|
+
resource = self.#{user_resource}
|
24
|
+
resource.try(:id) || resource.try(:email) || resource.try(:email_address)
|
25
|
+
end
|
26
|
+
|
27
|
+
def mass_assignment_authorizer(role)
|
28
|
+
super(role) << "#{user_resource}_identifier"
|
29
|
+
end
|
30
|
+
|
31
|
+
before_validation do
|
32
|
+
if #{user_resource}.present? and #{user_resource}.new_record? and #{user_resource}.respond_to? :invite!
|
33
|
+
#{user_resource}.invite! @as_user
|
34
|
+
self.#{user_resource}_id = #{user_resource}.id
|
35
|
+
end
|
36
|
+
end
|
37
|
+
END
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class String
|
43
|
+
|
44
|
+
# Is the string something like '234234234-Joe-Test'? This is used in params.
|
45
|
+
def parameter_id?
|
46
|
+
self[/^[0-9]+\-[\D]+/].present?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
ActiveRecord::Base.extend(MixedIdentifierForUserResource)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "require_all"
|
2
|
+
|
3
|
+
$: << File.dirname(__FILE__)
|
4
|
+
|
5
|
+
require "modify_resource/version"
|
6
|
+
require "modify_resource/rails/action_controller/modify_resource"
|
7
|
+
require "modify_resource/rails/action_controller/update_as"
|
8
|
+
require "modify_resource/rails/active_model/update_permitted_attributes"
|
9
|
+
require "modify_resource/rails/active_record/mixed_identifier_for_user_resource"
|
10
|
+
|
11
|
+
module ModifyResource
|
12
|
+
|
13
|
+
def self.included(base)
|
14
|
+
if defined? Rails and base < ActionController::Base
|
15
|
+
|
16
|
+
# Add `modify_on` and other methods to the controller
|
17
|
+
base.send :include, ActionController::ModifyResource
|
18
|
+
base.send :include, ActionController::UpdateAs
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'modify_resource/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "modify_resource"
|
8
|
+
gem.version = ModifyResource::VERSION
|
9
|
+
gem.authors = ["Colin Young"]
|
10
|
+
gem.email = ["me@colinyoung.com"]
|
11
|
+
gem.description = %q{This gem makes rails automatic. Securely.}
|
12
|
+
gem.summary = %q{stop writing the same controller actions for resources}
|
13
|
+
gem.homepage = ""
|
14
|
+
gem.add_dependency "require_all"
|
15
|
+
gem.add_dependency "rake"
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($/)
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.require_paths = ["lib"]
|
21
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'test_helper'
|
data/test/test_helper.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: modify_resource
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Colin Young
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-08 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: require_all
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: This gem makes rails automatic. Securely.
|
47
|
+
email:
|
48
|
+
- me@colinyoung.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- LICENSE.txt
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- lib/modify_resource.rb
|
59
|
+
- lib/modify_resource/rails/action_controller/modify_resource.rb
|
60
|
+
- lib/modify_resource/rails/action_controller/resource_info.rb
|
61
|
+
- lib/modify_resource/rails/action_controller/router.rb
|
62
|
+
- lib/modify_resource/rails/action_controller/update_as.rb
|
63
|
+
- lib/modify_resource/rails/active_model/update_permitted_attributes.rb
|
64
|
+
- lib/modify_resource/rails/active_record/mixed_identifier_for_user_resource.rb
|
65
|
+
- lib/modify_resource/version.rb
|
66
|
+
- modify_resource.gemspec
|
67
|
+
- test/modify_resource_test.rb
|
68
|
+
- test/test_helper.rb
|
69
|
+
homepage: ''
|
70
|
+
licenses: []
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project:
|
89
|
+
rubygems_version: 1.8.24
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: stop writing the same controller actions for resources
|
93
|
+
test_files:
|
94
|
+
- test/modify_resource_test.rb
|
95
|
+
- test/test_helper.rb
|