coast 0.9.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/lib/coast.rb +267 -0
- metadata +57 -0
data/lib/coast.rb
ADDED
@@ -0,0 +1,267 @@
|
|
1
|
+
# Makes any controller resourceful by providing the following actions:
|
2
|
+
# * new
|
3
|
+
# * edit
|
4
|
+
# * index
|
5
|
+
# * show
|
6
|
+
# * create
|
7
|
+
# * update
|
8
|
+
# * destroy
|
9
|
+
#
|
10
|
+
# There are 3 callbacks that you can leverage to manage the RESTful behavior:
|
11
|
+
# * before - Happens before any logic, just like a Rails before_filter.
|
12
|
+
# Note that this callback is invoked before any authorization is applied
|
13
|
+
# * respond_to - Happens after CRUD operations but before rendering a response
|
14
|
+
# * after - Happens after any logic, just like a Rails after_filter
|
15
|
+
#
|
16
|
+
# You can hook into the controller's lifecycle like so:
|
17
|
+
#
|
18
|
+
# before([action]) do
|
19
|
+
# # logic here
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# respond_to([action]) do
|
23
|
+
# # logic here
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# after([action]) do
|
27
|
+
# # logic here
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# Resourceful leans heavily on Rails naming conventions.
|
31
|
+
# If you are using Rails naming convetions, all this power is yours for free.
|
32
|
+
module Coast
|
33
|
+
|
34
|
+
module ClassMethods
|
35
|
+
|
36
|
+
def set_authorize_method(arg)
|
37
|
+
@authorize_method = arg
|
38
|
+
end
|
39
|
+
alias :authorize_method= :set_authorize_method
|
40
|
+
|
41
|
+
def authorize_method
|
42
|
+
@authorize_method ||= :abstract_authorize
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_resourceful_model(arg)
|
46
|
+
@resourceful_model = arg
|
47
|
+
end
|
48
|
+
alias :resourceful_model= :set_resourceful_model
|
49
|
+
|
50
|
+
def resourceful_model
|
51
|
+
return @resourceful_model if @resourceful_model
|
52
|
+
|
53
|
+
# try to determine the model based on convention
|
54
|
+
name = self.name.gsub(/Controller$/i, "").classify
|
55
|
+
# require the file to ensure the constant will be defined
|
56
|
+
require "#{RAILS_ROOT}/app/models/#{name.underscore}" rescue nil
|
57
|
+
@resourceful_model = Object.const_get(name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def before(action, &callback)
|
61
|
+
define_method "before_#{action}", &callback
|
62
|
+
end
|
63
|
+
|
64
|
+
def respond_to(action, &callback)
|
65
|
+
define_method "respond_to_#{action}", &callback
|
66
|
+
end
|
67
|
+
|
68
|
+
def after(action, &callback)
|
69
|
+
define_method "after_#{action}", &callback
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.included(mod)
|
75
|
+
mod.extend(ClassMethods)
|
76
|
+
end
|
77
|
+
|
78
|
+
def abstract_authorize(*args); end
|
79
|
+
|
80
|
+
# -----------------------------------------------------------------------------------------------
|
81
|
+
# begin restful actions
|
82
|
+
|
83
|
+
|
84
|
+
# begin UI actions
|
85
|
+
def new
|
86
|
+
invoke_callback(:before_new)
|
87
|
+
@resourceful_item ||= resourceful_model.new
|
88
|
+
send(self.class.authorize_method, :new, @resourceful_item, request)
|
89
|
+
init_instance_variables
|
90
|
+
|
91
|
+
invoke_callback(:respond_to_new)
|
92
|
+
unless performed?
|
93
|
+
respond_to do |format|
|
94
|
+
format.html { render :new }
|
95
|
+
format.xml { render :xml => { :message => "Format not supported! Use the html format." } }
|
96
|
+
format.json { render :json => { :message => "Format not supported! Use the html format." } }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
invoke_callback(:after_new)
|
101
|
+
end
|
102
|
+
|
103
|
+
def edit
|
104
|
+
invoke_callback(:before_edit)
|
105
|
+
@resourceful_item ||= resourceful_model.find(params[:id])
|
106
|
+
send(self.class.authorize_method, :edit, @resourceful_item, request)
|
107
|
+
init_instance_variables
|
108
|
+
invoke_callback(:respond_to_edit)
|
109
|
+
|
110
|
+
unless performed?
|
111
|
+
respond_to do |format|
|
112
|
+
format.html { render :edit }
|
113
|
+
format.xml { render :xml => { :message => "Format not supported! Use the html format." } }
|
114
|
+
format.json { render :json => { :message => "Format not supported! Use the html format." } }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
invoke_callback(:after_edit)
|
119
|
+
end
|
120
|
+
# end UI actions
|
121
|
+
|
122
|
+
|
123
|
+
# begin READ actions
|
124
|
+
def index
|
125
|
+
invoke_callback(:before_index)
|
126
|
+
@resourceful_list ||= resourceful_model.all
|
127
|
+
send(self.class.authorize_method, :index, @resourceful_list, request)
|
128
|
+
init_instance_variables
|
129
|
+
|
130
|
+
invoke_callback(:respond_to_index)
|
131
|
+
unless performed?
|
132
|
+
respond_to do |format|
|
133
|
+
format.html { render :index }
|
134
|
+
format.xml { render :xml => @resourceful_list }
|
135
|
+
format.json { render :json => @resourceful_list }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
invoke_callback(:after_index)
|
140
|
+
end
|
141
|
+
|
142
|
+
def show
|
143
|
+
invoke_callback(:before_show)
|
144
|
+
@resourceful_item ||= resourceful_model.find(params[:id])
|
145
|
+
send(self.class.authorize_method, :show, @resourceful_item, request)
|
146
|
+
init_instance_variables
|
147
|
+
|
148
|
+
invoke_callback(:respond_to_show)
|
149
|
+
unless performed?
|
150
|
+
respond_to do |format|
|
151
|
+
format.html { render :show }
|
152
|
+
format.xml { render :xml => @resourceful_item }
|
153
|
+
format.json { render :json => @resourceful_item }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
invoke_callback(:after_show)
|
158
|
+
end
|
159
|
+
# end READ actions
|
160
|
+
|
161
|
+
|
162
|
+
# begin MUTATING actions
|
163
|
+
def create
|
164
|
+
invoke_callback(:before_create)
|
165
|
+
@resourceful_item ||= resourceful_model.new(params[resourceful_model.name.underscore])
|
166
|
+
send(self.class.authorize_method, :create, @resourceful_item, request)
|
167
|
+
init_instance_variables
|
168
|
+
success = @skip_db_create || @resourceful_item.save
|
169
|
+
|
170
|
+
invoke_callback(:respond_to_create)
|
171
|
+
unless performed?
|
172
|
+
respond_to do |format|
|
173
|
+
if success
|
174
|
+
flash[:notice] = "#{resourceful_model.name} was successfully created."
|
175
|
+
format.html { redirect_to(@resourceful_item) }
|
176
|
+
format.xml { render :xml => @resourceful_item, :status => :created, :location => @resourceful_item }
|
177
|
+
format.json { render :json => @resourceful_item, :status => :created, :location => @resourceful_item }
|
178
|
+
else
|
179
|
+
format.html { render :action => "new" }
|
180
|
+
format.xml { render :xml => @resourceful_item.errors, :status => :unprocessable_entity }
|
181
|
+
format.json { render :json => @resourceful_item.errors, :status => :unprocessable_entity }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
invoke_callback(:after_create)
|
187
|
+
end
|
188
|
+
|
189
|
+
def update
|
190
|
+
invoke_callback(:before_update)
|
191
|
+
@resourceful_item ||= resourceful_model.find(params[:id])
|
192
|
+
send(self.class.authorize_method, :update, @resourceful_item, request)
|
193
|
+
init_instance_variables
|
194
|
+
success = @skip_db_update || @resourceful_item.update_attributes(params[resourceful_model.name.underscore])
|
195
|
+
|
196
|
+
invoke_callback(:respond_to_update)
|
197
|
+
unless performed?
|
198
|
+
respond_to do |format|
|
199
|
+
if success
|
200
|
+
flash[:notice] = "#{resourceful_model.name} was successfully updated."
|
201
|
+
format.html { redirect_to(@resourceful_item) }
|
202
|
+
format.xml { render :xml => @resourceful_item }
|
203
|
+
format.json { render :json => @resourceful_item }
|
204
|
+
else
|
205
|
+
format.html { render :action => "edit" }
|
206
|
+
format.xml { render :xml => @resourceful_item.errors, :status => :unprocessable_entity }
|
207
|
+
format.json { render :json => @resourceful_item.errors, :status => :unprocessable_entity }
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
invoke_callback(:after_update)
|
213
|
+
end
|
214
|
+
|
215
|
+
def destroy
|
216
|
+
invoke_callback(:before_destroy)
|
217
|
+
@resourceful_item ||= resourceful_model.find(params[:id])
|
218
|
+
send(self.class.authorize_method, :destroy, @resourceful_item, request)
|
219
|
+
init_instance_variables
|
220
|
+
@resourceful_item.destroy unless @skip_db_destroy
|
221
|
+
|
222
|
+
invoke_callback(:respond_to_destroy)
|
223
|
+
unless performed?
|
224
|
+
flash[:notice] = "#{resourceful_model.name} was successfully destroyed" if @resourceful_item.destroyed?
|
225
|
+
respond_to do |format|
|
226
|
+
format.html { redirect_to root_url }
|
227
|
+
format.xml { render :xml => @resourceful_item }
|
228
|
+
format.json { render :json => @resourceful_item }
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
invoke_callback(:after_destroy)
|
233
|
+
end
|
234
|
+
# end MUTATING actions
|
235
|
+
|
236
|
+
# end restful actions
|
237
|
+
# -----------------------------------------------------------------------------------------------
|
238
|
+
|
239
|
+
protected
|
240
|
+
|
241
|
+
def resourceful_model
|
242
|
+
self.class.resourceful_model
|
243
|
+
end
|
244
|
+
|
245
|
+
def init_instance_variables
|
246
|
+
instance_variable_set(item_instance_var_name, @resourceful_item) unless instance_variable_get(item_instance_var_name)
|
247
|
+
instance_variable_set(list_instance_var_name, @resourceful_list) unless instance_variable_get(list_instance_var_name)
|
248
|
+
end
|
249
|
+
|
250
|
+
def item_instance_var_name
|
251
|
+
return @item_instance_var_name if @item_instance_var_name
|
252
|
+
name = resourceful_model.name.underscore.gsub("/", "_")
|
253
|
+
puts name
|
254
|
+
@item_instance_var_name ||= "@#{name}"
|
255
|
+
end
|
256
|
+
|
257
|
+
def list_instance_var_name
|
258
|
+
@list_instance_var_name ||= item_instance_var_name.pluralize
|
259
|
+
end
|
260
|
+
|
261
|
+
private
|
262
|
+
|
263
|
+
def invoke_callback(name)
|
264
|
+
send(name) if respond_to?(name)
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: coast
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nathan Hopkins
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &2164573380 !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: *2164573380
|
25
|
+
description: Resourceful behavior for Rails controllers with a Sinatra like DSL.
|
26
|
+
email: nate.hop@gmail.com
|
27
|
+
executables: []
|
28
|
+
extensions: []
|
29
|
+
extra_rdoc_files: []
|
30
|
+
files:
|
31
|
+
- lib/coast.rb
|
32
|
+
homepage: https://github.com/hopsoft/coast
|
33
|
+
licenses:
|
34
|
+
- MIT
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.8.10
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: Coast
|
57
|
+
test_files: []
|