coast 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/coast.rb +267 -0
  2. 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: []