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.
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: []