coast 0.9.1 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Nathan Hopkins
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.
@@ -0,0 +1,186 @@
1
+ # Coast
2
+
3
+ ## Providing resourceful behavior for [Rails controllers](http://guides.rubyonrails.org/action_controller_overview.html)
4
+
5
+ ![Coast GEM](http://hopsoft.github.com/coast/images/coast.png)
6
+
7
+ ### ...if only the REST of life were this easy
8
+
9
+ Simply include the Coast module in your controller and get these actions for free.
10
+
11
+ `new` `edit` `index` `show` `create` `update` `destroy`
12
+
13
+ But wait... there's more.
14
+
15
+ * **Lightweight** - about 200 lines of code... *you can grok it in 5 minutes by skimming lib/coast.rb*
16
+ * **Unobtrusive** - no monkey patches
17
+ * **Flexible** - support for html, xml, and json formats
18
+ * **Familiar** - simple DSL for hooking into action callbacks
19
+ * **Secure** - implicit authorization with your favorite libs... *such as [CanCan](https://github.com/ryanb/cancan)*
20
+
21
+ ### Works best when you stick to [Rails conventions](http://guides.rubyonrails.org/getting_started.html)
22
+
23
+ ## Quick-start for the lazy
24
+
25
+ Assume you have a simple app structure for beach bums.
26
+
27
+ ```bash
28
+ app/controllers/beach_bums_controller.rb
29
+ app/models/beach_bum.rb
30
+ ```
31
+
32
+ Install the GEM.
33
+
34
+ ```bash
35
+ $gem install coast
36
+ ```
37
+
38
+ Tweak some files.
39
+
40
+ ```ruby
41
+ # config/routes.rb
42
+ Beach::Application.routes.draw do
43
+ resources :beach_bums
44
+ end
45
+ ```
46
+
47
+ ```ruby
48
+ # app/controllers/beach_bums_controller.rb
49
+ class BeachBumsController < ApplicationController
50
+ include Coast
51
+ end
52
+ ```
53
+
54
+ Congratulations... you now have a RESTful API for **beach bums**.
55
+
56
+ ## Callbacks
57
+
58
+ Coast uses a [Sinatra](http://www.sinatrarb.com/) like DSL to provide hooks into the action lifecycle.
59
+
60
+ The following hooks are supported for each action.
61
+
62
+ * `before` *- before any other action logic is performed... just like a [Rails before_filter](http://guides.rubyonrails.org/action_controller_overview.html#filters)*
63
+ * `respond_to` *- after authorization and db work but before rendering or redirecting*
64
+ * `after` *- after all other action logic is performed... just like a [Rails after_filter](http://guides.rubyonrails.org/action_controller_overview.html#filters)*
65
+
66
+ ### How to use the callbacks
67
+
68
+ ```ruby
69
+ # app/controllers/beach_bums_controller.rb
70
+ class BeachBumsController < ApplicationController
71
+ include Coast
72
+
73
+ before :show do
74
+ # take control and load a 'beach_bum' instead of letting Coast do it for us
75
+ @resourceful_item = BeachBum.find(params[:id])
76
+
77
+ # Coast will implicitly create an @beach_bum variable that references @resourceful_item
78
+ # cool eh?
79
+ end
80
+
81
+ respond_to :show do
82
+ # take control of rendering or redirecting instead of letting Coast do it for us
83
+ render :text => "Out surfing."
84
+ end
85
+
86
+ after :show do
87
+ # do some last minute housekeeping after every thing else is done
88
+ Rails.logger.info "Hey brah... we just completed the show action."
89
+ end
90
+
91
+ end
92
+ ```
93
+
94
+ ## Authorization
95
+
96
+ Coast implicitly calls an authorize method prior to executing any action logic.
97
+
98
+ You have complete control over this method. Here's an example.
99
+
100
+ ```ruby
101
+ # app/controllers/beach_bums_controller.rb
102
+ class BeachBumsController < ApplicationController
103
+ include Coast
104
+ set_authorize_method :authorize
105
+
106
+ def authorize(action, data, request)
107
+ # restrict all RESTful actions
108
+ raise "Unauthorized"
109
+ end
110
+
111
+ rescue_from Exception do |ex|
112
+ render :text => "Not Allowed", :status => 401
113
+ end
114
+ end
115
+ ```
116
+
117
+ Note the authorize method signature. The first arg is the **action** being performed. The second arg is the **record(s)** being operated on. The last arg is the **request** object.
118
+
119
+ While originally written to support [CanCan](https://github.com/ryanb/cancan), its pretty simple to take control and manage authorization yourself.
120
+
121
+ ## Advanced Usage
122
+
123
+ Coast comes with few tricks up its sleeve.
124
+
125
+ If your model and controller names deviate from Rails conventions, you can explicitly set the model like so.
126
+
127
+ ```ruby
128
+ # app/controllers/beach_bums_controller.rb
129
+ class BeachBumsController < ApplicationController
130
+ include Coast
131
+ set_resourceful_model SurferDude
132
+ end
133
+ ```
134
+
135
+ You can conditionally prevent mutating behavior on the server by setting an instance variable like so. *It's a little arcane, but that's on purpose.*
136
+
137
+ ```ruby
138
+ # app/controllers/beach_bums_controller.rb
139
+ class BeachBumsController < ApplicationController
140
+ include Coast
141
+
142
+ before :create do
143
+ # prevent the user from actually creating a record
144
+ @skip_db_create = true
145
+ end
146
+
147
+ before :update do
148
+ # prevent the user from actually saving a record
149
+ @skip_db_update = true
150
+ end
151
+
152
+ before :destroy do
153
+ # prevent the user from actually destroying a record
154
+ @skip_db_destroy = true
155
+ end
156
+
157
+ end
158
+ ```
159
+
160
+ ## Testing
161
+
162
+ There are some interesting additions to MiniTest::Mock since I mock some of Rails to make testing fast & fun.
163
+
164
+ Poke around the test code and let me know what you think.
165
+
166
+ How to run the tests.
167
+
168
+ ```bash
169
+ $rvm 1.9.3
170
+ $gem install bundler
171
+ $bundle
172
+ $rake test
173
+ ```
174
+
175
+ Ahh... passing tests.
176
+
177
+ ## Contributing
178
+
179
+ I'm looking for hand-outs, so please fork and submit pull requests. Bug fixes, features, whatever...
180
+
181
+ ## Nods
182
+
183
+ [I'm tired of writing RESTful boilerplate (& scaffold is overkill), so I'm stoked natehop released the Coast gem.](https://twitter.com/tehviking/status/189739333857710080)
184
+
185
+ -- Brandon Hayes, April 10, 2012
186
+
@@ -1,3 +1,8 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+ Bundler.require :default
4
+ require File.join(File.dirname(__FILE__), "coast", "version")
5
+
1
6
  # Makes any controller resourceful by providing the following actions:
2
7
  # * new
3
8
  # * edit
@@ -32,6 +37,14 @@
32
37
  module Coast
33
38
 
34
39
  module ClassMethods
40
+ def set_localized(arg)
41
+ @set_localized = arg
42
+ end
43
+ alias :localized= :set_localized
44
+
45
+ def localized?
46
+ @set_localized
47
+ end
35
48
 
36
49
  def set_authorize_method(arg)
37
50
  @authorize_method = arg
@@ -155,7 +168,7 @@ module Coast
155
168
  unless performed?
156
169
  respond_to do |format|
157
170
  if success
158
- flash[:notice] = "#{resourceful_model.name} was successfully created."
171
+ write_to_flash :notice, "#{resourceful_model.name} was successfully created."
159
172
  format.html { redirect_to(@resourceful_item) }
160
173
  format_json_and_xml(format, @resourceful_item, :status => :created, :location => @resourceful_item)
161
174
  else
@@ -177,7 +190,7 @@ module Coast
177
190
  unless performed?
178
191
  respond_to do |format|
179
192
  if success
180
- flash[:notice] = "#{resourceful_model.name} was successfully updated."
193
+ write_to_flash :notice, "#{resourceful_model.name} was successfully updated."
181
194
  format.html { redirect_to(@resourceful_item) }
182
195
  format_json_and_xml(format, @resourceful_item)
183
196
  else
@@ -197,7 +210,7 @@ module Coast
197
210
  @resourceful_item.destroy unless @skip_db_destroy
198
211
  invoke_callback(:respond_to_destroy)
199
212
  unless performed?
200
- flash[:notice] = "#{resourceful_model.name} was successfully destroyed" if @resourceful_item.destroyed?
213
+ write_to_flash(:notice, "#{resourceful_model.name} was successfully destroyed.") if @resourceful_item.destroyed?
201
214
  respond_to do |format|
202
215
  format.html { redirect_to root_url }
203
216
  format_json_and_xml(format, @resourceful_item)
@@ -233,6 +246,15 @@ module Coast
233
246
 
234
247
  private
235
248
 
249
+ def write_to_flash(key, message)
250
+ if self.class.localized?
251
+ message_key = message.downcase.strip.gsub(/\W+$/, "").gsub(/\W/, "_")
252
+ flash[key] = I18n.translate(message_key)
253
+ else
254
+ flash[key] = message
255
+ end
256
+ end
257
+
236
258
  def invoke_callback(name)
237
259
  send(name) if respond_to?(name)
238
260
  end
@@ -0,0 +1,3 @@
1
+ module Coast
2
+ VERSION = "0.9.3"
3
+ end
@@ -0,0 +1,248 @@
1
+ require "rubygems"
2
+ require "bundler"
3
+ Bundler.require(:default, :test)
4
+ require "active_support/all"
5
+ require File.join(File.dirname(__FILE__), "..", "lib", "coast")
6
+
7
+ class TestCoast < MicroTest::Test
8
+
9
+ RESTFUL_METHODS = %w(index show new edit create update destroy)
10
+ ITEM_METHODS = %w(show new edit create update destroy)
11
+ UI_METHODS = %w(new edit)
12
+ READ_METHODS = %w(index show)
13
+ MUTATE_METHODS = %w(create update destroy)
14
+
15
+ # Creates a mock model instance [ActiveRecord::Base].
16
+ def self.mock_model
17
+ mock = MicroMock.make.new
18
+ mock.stub(:destroy) { @destroyed = true }
19
+ mock.stub(:destroyed?) { @destroyed }
20
+ mock.stub(:update_attributes) { |*args| @attributes_updated = true }
21
+ mock.stub(:save) { |*args| @saved = true }
22
+ mock.stub(:table_name) { "mocks" }
23
+ mock.class.stub(:find) { |*args| TestCoast.mock_model }
24
+ mock.class.stub(:all) { [1..5].map { TestCoast.mock_model } }
25
+ mock
26
+ end
27
+
28
+ # Creates a mock request instance [ActionDispatch::Request].
29
+ def self.mock_request
30
+ mock = MicroMock.make.new
31
+ mock.stub(:request) { @request ||= MicroMock.make.new }
32
+ mock.stub(:params) { @params ||= {} }
33
+ mock.stub(:flash) { @flash ||= {} }
34
+ mock
35
+ end
36
+
37
+ # Creates a mock controller instance [ActionController::Base].
38
+ def self.mock_controller
39
+ mock = MicroMock.make.new
40
+ mock.class.send :include, Coast
41
+ mock.stub(:authorize!) { |*args| @authorize_invoked = true }
42
+ mock.stub(:authorize_invoked?) { @authorize_invoked }
43
+ mock.stub(:respond_to) { |&block| @responded = true; block.call(format) }
44
+ mock.stub(:responded?) { @responded }
45
+ mock.stub(:render) { |*args| @performed = @rendered = true }
46
+ mock.stub(:performed?) { @performed }
47
+ mock.stub(:rendered?) { @rendered }
48
+ mock.stub(:redirect_to) { |*args| @redirected = true; render }
49
+ mock.stub(:redirected?) { @redirected }
50
+ mock.stub(:request) { @request ||= TestCoast.mock_request }
51
+ mock.stub(:params) { request.params }
52
+ mock.stub(:flash) { request.flash }
53
+ mock.stub(:format) { @format ||= TestCoast.mock_format }
54
+ mock.stub(:root_url) { "/" }
55
+ mock
56
+ end
57
+
58
+ # Creates a mock format instance [ActionController::MimeResponds::Collector].
59
+ def self.mock_format
60
+ mock = MicroMock.make.new
61
+ mock.stub(:html) { |&block| @html = true; block.call if block }
62
+ mock.stub(:xml) { |&block| @xml = true; block.call if block }
63
+ mock.stub(:json) { |&block| @json = true; block.call if block }
64
+ mock
65
+ end
66
+
67
+ before do
68
+ @model = TestCoast.mock_model
69
+ @controller = TestCoast.mock_controller
70
+ @controller.class.set_resourceful_model @model.class
71
+ end
72
+
73
+ test ".set_localized" do
74
+ @controller.class.set_localized true
75
+ assert @controller.class.localized?
76
+ end
77
+
78
+ test ".localized=" do
79
+ @controller.class.localized = true
80
+ assert @controller.class.localized?
81
+ end
82
+
83
+ test ".set_authorize_method" do
84
+ @controller.class.set_authorize_method :authorize!
85
+ assert @controller.class.authorize_method == :authorize!
86
+ end
87
+
88
+ test ".authorize=" do
89
+ @controller.class.authorize_method = :authorize!
90
+ assert @controller.class.authorize_method == :authorize!
91
+ end
92
+
93
+ test ".set_resourceful_model" do
94
+ model = Object.new
95
+ @controller.class.set_resourceful_model model
96
+ assert @controller.class.resourceful_model == model
97
+ end
98
+
99
+ test ".resourceful_model=" do
100
+ model = Object.new
101
+ @controller.class.resourceful_model = model
102
+ assert @controller.class.resourceful_model == model
103
+ end
104
+
105
+ test "set before callbacks" do
106
+ RESTFUL_METHODS.each do |method|
107
+ assert !@controller.respond_to?("before_#{method}")
108
+ @controller.class.before(method) {}
109
+ assert @controller.respond_to?("before_#{method}")
110
+ end
111
+ end
112
+
113
+ test "set respond_to callbacks" do
114
+ RESTFUL_METHODS.each do |method|
115
+ assert !@controller.respond_to?("respond_to_#{method}")
116
+ @controller.class.respond_to(method) {}
117
+ assert @controller.respond_to?("respond_to_#{method}")
118
+ end
119
+ end
120
+
121
+ test "set after callbacks" do
122
+ RESTFUL_METHODS.each do |method|
123
+ assert !@controller.respond_to?("after_#{method}")
124
+ @controller.class.after(method) {}
125
+ assert @controller.respond_to?("after_#{method}")
126
+ end
127
+ end
128
+
129
+ test "RESTful methods exist" do
130
+ RESTFUL_METHODS.each do |method|
131
+ assert @controller.respond_to?(method)
132
+ end
133
+ end
134
+
135
+ test "<create> flash message" do
136
+ @controller.create
137
+ assert @controller.flash[:notice].ends_with?("was successfully created.")
138
+ end
139
+
140
+ test "<create> localized flash message" do
141
+ @controller.class.localized = true
142
+ @controller.create
143
+ assert @controller.flash[:notice] =~ /translation missing: .+was_successfully_created/
144
+ end
145
+
146
+ test "<update> flash message" do
147
+ @controller.update
148
+ assert @controller.flash[:notice].ends_with?("was successfully updated.")
149
+ end
150
+
151
+ test "<update> localized flash message" do
152
+ @controller.class.localized = true
153
+ @controller.update
154
+ assert @controller.flash[:notice] =~ /translation missing: .+was_successfully_updated/
155
+ end
156
+
157
+ test "<destroy> flash message" do
158
+ @controller.destroy
159
+ assert @controller.flash[:notice].ends_with?("was successfully destroyed.")
160
+ end
161
+
162
+ test "<destroy> localized flash message" do
163
+ @controller.class.localized = true
164
+ @controller.destroy
165
+ assert @controller.flash[:notice] =~ /translation missing: .+was_successfully_destroyed/
166
+ end
167
+
168
+ RESTFUL_METHODS.each do |method|
169
+
170
+ test "<#{method}> responds and renders" do
171
+ @controller.send(method)
172
+ assert @controller.responded?
173
+ assert @controller.rendered?
174
+ end
175
+
176
+ test "<#{method}> renders for the formats html, xml, json" do
177
+ @controller.send(method)
178
+ assert(@controller.format.instance_eval { @html })
179
+ assert(@controller.format.instance_eval { @xml })
180
+ assert(@controller.format.instance_eval { @json })
181
+ end
182
+
183
+ test "<#{method}> invokes before, respond_to, after callbacks" do
184
+ callbacks = []
185
+ @controller.class.before(method) { callbacks << :before }
186
+ @controller.class.respond_to(method) { callbacks << :respond_to }
187
+ @controller.class.after(method) { callbacks << :after }
188
+ @controller.send(method)
189
+ assert callbacks.include?(:before)
190
+ assert callbacks.include?(:respond_to)
191
+ assert callbacks.include?(:after)
192
+ end
193
+
194
+ test "<#{method}> allows :respond_to callback to perform the render" do
195
+ @controller.class.respond_to(method) { @performed = true }
196
+ @controller.send(method)
197
+ assert @controller.performed?
198
+ assert !@controller.responded?
199
+ end
200
+
201
+ test "<#{method}> invokes the authorize_method when set" do
202
+ @controller.class.authorize_method = :authorize!
203
+ @controller.send(method)
204
+ assert @controller.authorize_invoked?
205
+ end
206
+
207
+ end
208
+
209
+ ITEM_METHODS.each do |method|
210
+ test "<#{method}> allows :before callback to set the resourceful_item" do
211
+ item = TestCoast.mock_model
212
+ @controller.class.before(method) { @resourceful_item = item }
213
+ @controller.send(method)
214
+ assert @controller.instance_eval { @resourceful_item.object_id } == item.object_id
215
+ end
216
+
217
+ test "<#{method}> sets a custom named instance variable for the item" do
218
+ item = TestCoast.mock_model
219
+ @controller.class.before(method) { @resourceful_item = item }
220
+ @controller.send(method)
221
+ variable = @controller.instance_eval { instance_variable_get(item_instance_var_name) }
222
+ assert variable.object_id == item.object_id
223
+ end
224
+ end
225
+
226
+ MUTATE_METHODS.each do |method|
227
+ test "<#{method}> redirects" do
228
+ @controller.send(method)
229
+ assert @controller.redirected?
230
+ end
231
+ end
232
+
233
+ test "<index> allows :before callback to set the list" do
234
+ list = TestCoast.mock_model.class.all
235
+ @controller.class.before(:index) { @resourceful_list = list }
236
+ @controller.index
237
+ assert @controller.instance_eval{ @resourceful_list }.object_id == list.object_id
238
+ end
239
+
240
+ test "<index> sets a custom named instance variable for the item" do
241
+ list = TestCoast.mock_model.class.all
242
+ @controller.class.before(:index) { @resourceful_list = list }
243
+ @controller.index
244
+ variable = @controller.instance_eval { instance_variable_get(list_instance_var_name) }
245
+ assert variable.object_id == list.object_id
246
+ end
247
+
248
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.9.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-06 00:00:00.000000000 Z
12
+ date: 2012-11-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
- requirement: &2160361220 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,16 +21,104 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2160361220
25
- description: Resourceful behavior for Rails controllers with a Sinatra like DSL.
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: micro_test
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - '='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.3.0.rc4
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.3.0.rc4
46
+ - !ruby/object:Gem::Dependency
47
+ name: micro_mock
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - '='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.0.5
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.5
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: pry-stack_explorer
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: awesome_print
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ description: Resourceful behavior for Rails controllers with a simple DSL.
26
111
  email:
27
- - nate.hop@gmail.com
112
+ - natehop@gmail.com
28
113
  executables: []
29
114
  extensions: []
30
115
  extra_rdoc_files: []
31
116
  files:
32
117
  - lib/coast.rb
33
- - spec/coast_spec.rb
118
+ - lib/coast/version.rb
119
+ - LICENSE.txt
120
+ - README.md
121
+ - test/test_coast.rb
34
122
  homepage: https://github.com/hopsoft/coast
35
123
  licenses:
36
124
  - MIT
@@ -52,9 +140,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
140
  version: '0'
53
141
  requirements: []
54
142
  rubyforge_project:
55
- rubygems_version: 1.8.10
143
+ rubygems_version: 1.8.23
56
144
  signing_key:
57
145
  specification_version: 3
58
- summary: Coast
146
+ summary: A small mixin for Rails controllers that provides restful behavior.
59
147
  test_files:
60
- - spec/coast_spec.rb
148
+ - test/test_coast.rb
149
+ has_rdoc:
@@ -1,245 +0,0 @@
1
- require "rubygems"
2
-
3
- # fix MiniTest issue with 1.9
4
- unless defined? Gem::Deprecate
5
- module Gem
6
- Deprecate = Module.new do
7
- include Deprecate
8
- end
9
- end
10
- end
11
-
12
- require "bundler/setup"
13
- require "minitest/autorun"
14
- require "active_support/all"
15
- require "turn"
16
- require "pry"
17
-
18
- dirname = File.dirname(__FILE__)
19
- require File.join(dirname, "mock")
20
- Dir.glob(File.join(dirname, "..", "lib", "*.rb")) { |f| require f }
21
- MODEL_PATH = File.join(dirname, "testable_model.rb")
22
- CONTROLLER_PATH = File.join(dirname, "testable_controller.rb")
23
- load MODEL_PATH
24
- load CONTROLLER_PATH
25
-
26
-
27
-
28
-
29
- describe Coast do
30
- RESTFUL_METHODS = %w(index show new edit create update destroy)
31
- ITEM_METHODS = %w(show new edit create update destroy)
32
- UI_METHODS = %w(new edit)
33
- READ_METHODS = %w(index show)
34
- MUTATE_METHODS = %w(create update destroy)
35
-
36
- # Resets the mock class defs.
37
- def reset
38
- Coast.send(:remove_const, :TestableController)
39
- Coast.send(:remove_const, :TestableModel)
40
- load MODEL_PATH
41
- load CONTROLLER_PATH
42
- Coast::TestableController.set_resourceful_model Coast::TestableModel
43
- end
44
-
45
- # class method tests ============================================================================
46
-
47
- describe :set_authorize_method do
48
- it "sets the method used to perform authorization checks" do
49
- reset
50
- Coast::TestableController.set_authorize_method :authorize!
51
- assert Coast::TestableController.authorize_method == :authorize!
52
- end
53
- end
54
-
55
- describe :authorize_method= do
56
- it "sets the method used to perform authorization checks" do
57
- reset
58
- Coast::TestableController.authorize_method = :authorize!
59
- assert Coast::TestableController.authorize_method == :authorize!
60
- end
61
- end
62
-
63
- describe :set_resourceful_model do
64
- it "sets the model that the controller manages" do
65
- reset
66
- model = Object.new
67
- Coast::TestableController.set_resourceful_model model
68
- assert Coast::TestableController.resourceful_model == model
69
- end
70
- end
71
-
72
- describe :resourceful_model= do
73
- it "sets the model that the controller manages" do
74
- reset
75
- model = Object.new
76
- Coast::TestableController.resourceful_model = model
77
- assert Coast::TestableController.resourceful_model == model
78
- end
79
- end
80
-
81
- def verify_callback_setter(event, action)
82
- reset
83
- Coast::TestableController.send(event, action, &(lambda {}))
84
- assert Coast::TestableController.new.respond_to?("#{event}_#{action}")
85
- end
86
-
87
- describe :before do
88
- it "stores a before callback for all RESTful actions" do
89
- RESTFUL_METHODS.each { |m| verify_callback_setter :before, m }
90
- end
91
- end
92
-
93
- describe :respond_to do
94
- it "stores a respond_to callback for all RESTful actions" do
95
- RESTFUL_METHODS.each { |m| verify_callback_setter :respond_to, m }
96
- end
97
- end
98
-
99
- describe :after do
100
- it "stores an after callback for all RESTful actions" do
101
- RESTFUL_METHODS.each { |m| verify_callback_setter :after, m }
102
- end
103
- end
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
- # instance method tests =========================================================================
116
-
117
-
118
- it "supports all RESTful methods" do
119
- reset
120
- controller = Coast::TestableController.new
121
- RESTFUL_METHODS.each { |m| controller.must_respond_to m }
122
- end
123
-
124
- # %w(index show new).each do |method|
125
- RESTFUL_METHODS.each do |method|
126
- describe "##{method}" do
127
- before do
128
- reset
129
- end
130
-
131
- it "responds and renders" do
132
- controller = Coast::TestableController.new
133
- controller.send(method)
134
- assert controller.responded?, "Did not respond"
135
- assert controller.rendered?, "Did not render"
136
- end
137
-
138
- it "renders for the formats html, xml, json" do
139
- controller = Coast::TestableController.new
140
- controller.send(method)
141
- assert controller.html, "Did not respond to the html format"
142
- assert controller.xml, "Did not respond to the xml format"
143
- assert controller.json, "Did not respond to the json format"
144
- end
145
-
146
- it "invokes the callbacks before, respond_to, after" do
147
- callbacks = []
148
-
149
- Coast::TestableController.class_eval do
150
- before(method) { callbacks << :before }
151
- respond_to(method) { callbacks << :respond_to }
152
- after(method) { callbacks << :after }
153
- end
154
-
155
- controller = Coast::TestableController.new
156
- controller.send(method)
157
- assert callbacks.include?(:before), "Did not invoke the before callback"
158
- assert callbacks.include?(:respond_to), "Did not invoke the respond_to callback"
159
- assert callbacks.include?(:after), "Did not invoke the after callback"
160
- end
161
-
162
- it "allows :respond_to callback to perform the render" do
163
- Coast::TestableController.respond_to(method) { @performed = true }
164
- controller = Coast::TestableController.new
165
- controller.send(method)
166
- assert controller.responded? == false, "Did not allow :respond_to callback to perform the render"
167
- end
168
-
169
- it "invokes the authorize_method when set" do
170
- Coast::TestableController.authorize_method = :authorize!
171
- controller = Coast::TestableController.new
172
- controller.send(:index)
173
- assert controller.authorize_invoked?, "Did not invoke the authorize_method"
174
- end
175
-
176
- end
177
- end
178
-
179
- ITEM_METHODS.each do |method|
180
- describe "##{method}" do
181
- before do
182
- reset
183
- end
184
-
185
- it "allows :before callback to set the item" do
186
- item = Object.new
187
- Coast::TestableController.before(:index) { @resourceful_item = item }
188
- controller = Coast::TestableController.new
189
- controller.index
190
- assert controller.instance_eval { @resourceful_item } == item, "Did not allow :before callback to set the resourceful_item"
191
- end
192
-
193
- it "sets a custom named instance variable for the item" do
194
- item = Object.new
195
- Coast::TestableController.before(:index) { @resourceful_item = item }
196
- controller = Coast::TestableController.new
197
- controller.index
198
- variable = controller.instance_eval { instance_variable_get(item_instance_var_name) }
199
- assert variable != nil, "Did not set a custom instance variable for the item"
200
- assert variable == item, "Did not set a custom instance variable for the item to the correct value"
201
- end
202
-
203
- end
204
- end
205
-
206
- MUTATE_METHODS.each do |method|
207
- describe "##{method}" do
208
- before do
209
- reset
210
- end
211
-
212
- it "redirects" do
213
- controller = Coast::TestableController.new
214
- controller.send(method)
215
- assert controller.redirected?, "Did not redirect"
216
- end
217
- end
218
- end
219
-
220
-
221
- describe "#index" do
222
- before do
223
- reset
224
- end
225
-
226
- it "allows :before callback to set the list" do
227
- list = [ Object.new ]
228
- Coast::TestableController.before(:index) { @resourceful_list = list }
229
- controller = Coast::TestableController.new
230
- controller.index
231
- assert controller.instance_eval { @resourceful_list } == list, "Did not allow :before callback to set the resourceful_list"
232
- end
233
-
234
- it "sets a custom named instance variable for the item" do
235
- list = [ Object.new ]
236
- Coast::TestableController.before(:index) { @resourceful_list = list }
237
- controller = Coast::TestableController.new
238
- controller.index
239
- variable = controller.instance_eval { instance_variable_get(list_instance_var_name) }
240
- assert variable != nil, "Did not set a custom instance variable for the item"
241
- assert variable == list, "Did not set a custom instance variable for the item to the correct value"
242
- end
243
- end
244
-
245
- end