responders 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +5 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +44 -0
- data/Rakefile +44 -0
- data/lib/generators/USAGE +11 -0
- data/lib/generators/responders_controller_generator.rb +15 -0
- data/lib/generators/responders_install_generator.rb +14 -0
- data/lib/generators/templates/controller.rb +53 -0
- data/lib/responders.rb +4 -0
- data/lib/responders/flash_responder.rb +102 -0
- data/lib/responders/http_cache_responder.rb +33 -0
- data/lib/responders/version.rb +3 -0
- data/test/flash_responder_test.rb +116 -0
- data/test/http_cache_responder_test.rb +104 -0
- data/test/test_helper.rb +49 -0
- metadata +68 -0
data/CHANGELOG.rdoc
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
== Responders
|
2
|
+
|
3
|
+
A set of responders to dry up your Rails 3 app:
|
4
|
+
|
5
|
+
* FlashResponder - Sets the flash based on the controller action and resource status.
|
6
|
+
For instance, if you do: respond_with(@post) on a POST request and the resource @post
|
7
|
+
does not contain errors, it will automatically set the flash message to
|
8
|
+
"Post was successfully created" as long as you configure your I18n file:
|
9
|
+
|
10
|
+
flash:
|
11
|
+
actions:
|
12
|
+
create:
|
13
|
+
success: "{resource_name} was successfully created"
|
14
|
+
update:
|
15
|
+
success: "{resource_name} was successfully updated"
|
16
|
+
|
17
|
+
In case the resource contains errors, you should use the failure key on I18n. This is
|
18
|
+
useful to dry up flash messages from your controllers. If you need a specific message
|
19
|
+
for a controller, let's say, for PostsController, you can also do:
|
20
|
+
|
21
|
+
flash:
|
22
|
+
posts:
|
23
|
+
create:
|
24
|
+
success: "Your post was created and will be published soon"
|
25
|
+
|
26
|
+
* HttpCacheResponder - Automatically adds Last-Modified headers to API requests. This
|
27
|
+
allows clients to easily query the server if a resource changed and if the client tries
|
28
|
+
to retrieve a resource that has not been modified, it returns not_modified status.
|
29
|
+
|
30
|
+
== Generator
|
31
|
+
|
32
|
+
This gem also includes a responders controller generator, so your scaffold can be customized to use respond_with instead of default respond_to blocks just by configuring your environment:
|
33
|
+
|
34
|
+
config.generators do |g|
|
35
|
+
g.scaffold_controller = :responders_controller
|
36
|
+
end
|
37
|
+
|
38
|
+
== Bugs and Feedback
|
39
|
+
|
40
|
+
If you discover any bugs or want to drop a line, feel free to create an issue on GitHub.
|
41
|
+
|
42
|
+
http://github.com/plataformatec/responders/issues
|
43
|
+
|
44
|
+
MIT License. Copyright 2009 Plataforma Tecnologia. http://blog.plataformatec.com.br
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/rdoctask'
|
6
|
+
require File.join(File.dirname(__FILE__), 'lib', 'responders', 'version')
|
7
|
+
|
8
|
+
desc 'Default: run unit tests'
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
desc 'Test Responders'
|
12
|
+
Rake::TestTask.new(:test) do |t|
|
13
|
+
t.libs << 'lib'
|
14
|
+
t.libs << 'test'
|
15
|
+
t.pattern = 'test/**/*_test.rb'
|
16
|
+
t.verbose = true
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Generate documentation for Responders'
|
20
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
21
|
+
rdoc.rdoc_dir = 'rdoc'
|
22
|
+
rdoc.title = 'Responders'
|
23
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
24
|
+
rdoc.rdoc_files.include('README.rdoc')
|
25
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'jeweler'
|
30
|
+
Jeweler::Tasks.new do |s|
|
31
|
+
s.name = "responders"
|
32
|
+
s.version = Responders::VERSION
|
33
|
+
s.summary = "A set of Rails 3 responders to dry up your application"
|
34
|
+
s.email = "contact@plataformatec.com.br"
|
35
|
+
s.homepage = "http://github.com/plataformatec/responders"
|
36
|
+
s.description = "A set of Rails 3 responders to dry up your application"
|
37
|
+
s.authors = ['José Valim']
|
38
|
+
s.files = FileList["[A-Z]*", "lib/**/*", "init.rb"]
|
39
|
+
end
|
40
|
+
|
41
|
+
Jeweler::GemcutterTasks.new
|
42
|
+
rescue LoadError
|
43
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
|
44
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
Description:
|
2
|
+
Stubs out a scaffolded controller and its views. Different from rails
|
3
|
+
scaffold_controller, it uses respond_with instead of respond_to blocks.
|
4
|
+
Pass the model name, either CamelCased or under_scored. The controller
|
5
|
+
name is retrieved as a pluralized version of the model name.
|
6
|
+
|
7
|
+
To create a controller within a module, specify the model name as a
|
8
|
+
path like 'parent_module/controller_name'.
|
9
|
+
|
10
|
+
This generates a controller class in app/controllers and invokes helper,
|
11
|
+
template engine and test framework generators.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module Generators
|
5
|
+
class RespondersControllerGenerator < ScaffoldControllerGenerator
|
6
|
+
def self.source_root
|
7
|
+
@source_root ||= File.expand_path("templates", File.dirname(__FILE__))
|
8
|
+
end
|
9
|
+
protected
|
10
|
+
def flash?
|
11
|
+
!ApplicationController.responder.ancestors.include?(Responders::FlashResponder)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class RespondersInstallGenerator < Rails::Generators::Base
|
2
|
+
desc "Creates an initializer file with default responder configuration"
|
3
|
+
|
4
|
+
def create_responder_initializer
|
5
|
+
create_file "config/initializers/responders.rb", <<-FILE
|
6
|
+
class #{Rails.application.class.name}Responder
|
7
|
+
include FlashResponder
|
8
|
+
include HttpCacheResponder
|
9
|
+
end
|
10
|
+
|
11
|
+
ApplicationController.responder = #{Rails.application.class.name}Responder
|
12
|
+
FILE
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
class <%= controller_class_name %>Controller < ApplicationController
|
2
|
+
<% unless options[:singleton] -%>
|
3
|
+
# GET /<%= table_name %>
|
4
|
+
# GET /<%= table_name %>.xml
|
5
|
+
def index
|
6
|
+
@<%= table_name %> = <%= orm_class.all(class_name) %>
|
7
|
+
respond_with(@<%= table_name %>)
|
8
|
+
end
|
9
|
+
<% end -%>
|
10
|
+
|
11
|
+
# GET /<%= table_name %>/1
|
12
|
+
# GET /<%= table_name %>/1.xml
|
13
|
+
def show
|
14
|
+
@<%= file_name %> = <%= orm_class.find(class_name, "params[:id]") %>
|
15
|
+
respond_with(@<%= file_name %>)
|
16
|
+
end
|
17
|
+
|
18
|
+
# GET /<%= table_name %>/new
|
19
|
+
# GET /<%= table_name %>/new.xml
|
20
|
+
def new
|
21
|
+
@<%= file_name %> = <%= orm_class.build(class_name) %>
|
22
|
+
respond_with(@<%= file_name %>)
|
23
|
+
end
|
24
|
+
|
25
|
+
# GET /<%= table_name %>/1/edit
|
26
|
+
def edit
|
27
|
+
@<%= file_name %> = <%= orm_class.find(class_name, "params[:id]") %>
|
28
|
+
end
|
29
|
+
|
30
|
+
# POST /<%= table_name %>
|
31
|
+
# POST /<%= table_name %>.xml
|
32
|
+
def create
|
33
|
+
@<%= file_name %> = <%= orm_class.build(class_name, "params[:#{file_name}]") %>
|
34
|
+
<%= "flash[:notice] = '#{class_name} was successfully created.' if " if flash? %>@<%= orm_instance.save %>
|
35
|
+
respond_with(@<%= file_name %>)
|
36
|
+
end
|
37
|
+
|
38
|
+
# PUT /<%= table_name %>/1
|
39
|
+
# PUT /<%= table_name %>/1.xml
|
40
|
+
def update
|
41
|
+
@<%= file_name %> = <%= orm_class.find(class_name, "params[:id]") %>
|
42
|
+
<%= "flash[:notice] = '#{class_name} was successfully updated.' if " if flash? %>@<%= orm_instance.update_attributes("params[:#{file_name}]") %>
|
43
|
+
respond_with(@<%= file_name %>)
|
44
|
+
end
|
45
|
+
|
46
|
+
# DELETE /<%= table_name %>/1
|
47
|
+
# DELETE /<%= table_name %>/1.xml
|
48
|
+
def destroy
|
49
|
+
@<%= file_name %> = <%= orm_class.find(class_name, "params[:id]") %>
|
50
|
+
@<%= orm_instance.destroy %>
|
51
|
+
respond_with(@<%= file_name %>)
|
52
|
+
end
|
53
|
+
end
|
data/lib/responders.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
module Responders
|
2
|
+
# Responder to automatically set flash messages based on I18n API. It checks for
|
3
|
+
# message based on the current action, but also allows defaults to be set, using
|
4
|
+
# the following order:
|
5
|
+
#
|
6
|
+
# flash.controller_name.action_name.status
|
7
|
+
# flash.actions.action_name.status
|
8
|
+
#
|
9
|
+
# So, if you have a CarsController, create action, it will check for:
|
10
|
+
#
|
11
|
+
# flash.cars.create.status
|
12
|
+
# flash.actions.create.status
|
13
|
+
#
|
14
|
+
# The statuses can be :success (when the object can be created, updated
|
15
|
+
# or destroyed with success) or :failure (when the objecy cannot be created
|
16
|
+
# or updated).
|
17
|
+
#
|
18
|
+
# The resource_name given is available as interpolation option, this means you can set:
|
19
|
+
#
|
20
|
+
# flash:
|
21
|
+
# actions:
|
22
|
+
# create:
|
23
|
+
# success: "Hooray! {{resource_name}} was successfully created!"
|
24
|
+
#
|
25
|
+
# But sometimes, flash messages are not that simple. Going back
|
26
|
+
# to cars example, you might want to say the brand of the car when it's
|
27
|
+
# updated. Well, that's easy also:
|
28
|
+
#
|
29
|
+
# flash:
|
30
|
+
# cars:
|
31
|
+
# update:
|
32
|
+
# success: "Hooray! You just tuned your {{car_brand}}!"
|
33
|
+
#
|
34
|
+
# Since :car_name is not available for interpolation by default, you have
|
35
|
+
# to overwrite interpolation_options in your controller.
|
36
|
+
#
|
37
|
+
# def interpolation_options
|
38
|
+
# { :car_brand => @car.brand }
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# Then you will finally have:
|
42
|
+
#
|
43
|
+
# 'Hooray! You just tuned your Aston Martin!'
|
44
|
+
#
|
45
|
+
# If your controller is namespaced, for example Admin::CarsController,
|
46
|
+
# the messages will be checked in the following order:
|
47
|
+
#
|
48
|
+
# flash.admin.cars.create.status
|
49
|
+
# flash.admin.actions.create.status
|
50
|
+
# flash.cars.create.status
|
51
|
+
# flash.actions.create.status
|
52
|
+
#
|
53
|
+
module FlashResponder
|
54
|
+
def initialize(controller, resources, options={})
|
55
|
+
super
|
56
|
+
@flash = options.delete(:flash)
|
57
|
+
end
|
58
|
+
|
59
|
+
def navigation_behavior(error)
|
60
|
+
super
|
61
|
+
|
62
|
+
unless get? || @flash == false
|
63
|
+
status = has_errors? ? :failure : :success
|
64
|
+
return if controller.send(:flash)[status].present?
|
65
|
+
|
66
|
+
resource_name = if resource.class.respond_to?(:human_name)
|
67
|
+
resource.class.human_name
|
68
|
+
else
|
69
|
+
resource.class.name.underscore.humanize
|
70
|
+
end
|
71
|
+
|
72
|
+
options = {
|
73
|
+
:default => flash_defaults_by_namespace(status),
|
74
|
+
:resource_name => resource_name,
|
75
|
+
:resource_sym => resource_name.downcase
|
76
|
+
}
|
77
|
+
|
78
|
+
if controller.respond_to?(:interpolation_options, true)
|
79
|
+
options.merge!(controller.send(:interpolation_options))
|
80
|
+
end
|
81
|
+
|
82
|
+
message = ::I18n.t options[:default].shift, options
|
83
|
+
controller.send(:flash)[status] = message unless message.blank?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
protected
|
88
|
+
|
89
|
+
def flash_defaults_by_namespace(status)
|
90
|
+
defaults = []
|
91
|
+
slices = controller.controller_path.split('/')
|
92
|
+
|
93
|
+
while slices.size > 0
|
94
|
+
defaults << :"flash.#{slices.fill(controller.controller_name, -1).join('.')}.#{controller.action_name}.#{status}"
|
95
|
+
defaults << :"flash.#{slices.fill(:actions, -1).join('.')}.#{controller.action_name}.#{status}"
|
96
|
+
slices.shift
|
97
|
+
end
|
98
|
+
|
99
|
+
defaults << ""
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Responders
|
2
|
+
# Set HTTP Last-Modified headers based on the given resource. It's used only
|
3
|
+
# on API behavior (to_format) and is useful for a client to check in the server
|
4
|
+
# if a resource changed after a specific date or not.
|
5
|
+
#
|
6
|
+
# This is not usually not used in html requests because pages contains a lot
|
7
|
+
# information besides the resource information, as current_user, flash messages,
|
8
|
+
# widgets... that are better handled with other strategies, as fragment caches and
|
9
|
+
# the digest of the body.
|
10
|
+
#
|
11
|
+
module HttpCacheResponder
|
12
|
+
def initialize(controller, resources, options={})
|
13
|
+
super
|
14
|
+
@http_cache = options.delete(:http_cache)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_format
|
18
|
+
if get? && @http_cache != false && controller.response.last_modified.nil?
|
19
|
+
timestamp = resources.flatten.map do |resource|
|
20
|
+
resource.updated_at.utc if resource.respond_to?(:updated_at)
|
21
|
+
end.compact.max
|
22
|
+
|
23
|
+
controller.response.last_modified = timestamp if timestamp
|
24
|
+
if request.fresh?(controller.response)
|
25
|
+
head :not_modified
|
26
|
+
return
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
super
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class Address
|
4
|
+
attr_accessor :errors
|
5
|
+
def self.human_name; 'Address'; end
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@errors = {}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class FlashResponder < ActionController::Responder
|
13
|
+
include Responders::FlashResponder
|
14
|
+
end
|
15
|
+
|
16
|
+
class AddressesController < ApplicationController
|
17
|
+
before_filter :set_resource
|
18
|
+
self.responder = FlashResponder
|
19
|
+
|
20
|
+
def action
|
21
|
+
options = params.slice(:flash)
|
22
|
+
flash[:success] = "Flash is set" if params[:set_flash]
|
23
|
+
respond_with(@resource, options)
|
24
|
+
end
|
25
|
+
alias :new :action
|
26
|
+
alias :create :action
|
27
|
+
alias :update :action
|
28
|
+
alias :destroy :action
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def interpolation_options
|
33
|
+
{ :reference => 'Ocean Avenue' }
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_resource
|
37
|
+
@resource = Address.new
|
38
|
+
@resource.errors[:fail] = true if params[:fail]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module Admin
|
43
|
+
class AddressesController < ::AddressesController
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class FlashResponderTest < ActionController::TestCase
|
48
|
+
tests AddressesController
|
49
|
+
|
50
|
+
def setup
|
51
|
+
@controller.stubs(:polymorphic_url).returns("/")
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_sets_success_flash_message_on_non_get_requests
|
55
|
+
post :create
|
56
|
+
assert_equal "Resource created with success", flash[:success]
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_sets_failure_flash_message_on_not_get_requests
|
60
|
+
post :create, :fail => true
|
61
|
+
assert_equal "Resource could not be created", flash[:failure]
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_does_not_set_flash_message_on_get_requests
|
65
|
+
get :new
|
66
|
+
assert flash.empty?
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_sets_flash_message_for_the_current_controller
|
70
|
+
put :update, :fail => true
|
71
|
+
assert_equal "Oh no! We could not update your address!", flash[:failure]
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_sets_flash_message_with_resource_name
|
75
|
+
put :update
|
76
|
+
assert_equal "Nice! Address was updated with success!", flash[:success]
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_sets_flash_message_with_interpolation_options
|
80
|
+
delete :destroy
|
81
|
+
assert_equal "Successfully deleted the address at Ocean Avenue", flash[:success]
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_does_not_set_flash_if_flash_false_is_given
|
85
|
+
post :create, :flash => false
|
86
|
+
assert flash.empty?
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_does_not_overwrite_the_flash_if_already_set
|
90
|
+
post :create, :set_flash => true
|
91
|
+
assert_equal "Flash is set", flash[:success]
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class NamespacedFlashResponderTest < ActionController::TestCase
|
96
|
+
tests Admin::AddressesController
|
97
|
+
|
98
|
+
def setup
|
99
|
+
@controller.stubs(:polymorphic_url).returns("/")
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_sets_the_flash_message_based_on_the_current_controller
|
103
|
+
put :update
|
104
|
+
assert_equal "Admin updated address with success", flash[:success]
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_sets_the_flash_message_based_on_namespace_actions
|
108
|
+
post :create
|
109
|
+
assert_equal "Admin created address with success", flash[:success]
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_fallbacks_to_non_namespaced_controller_flash_message
|
113
|
+
delete :destroy
|
114
|
+
assert_equal "Successfully deleted the address at Ocean Avenue", flash[:success]
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class HttpCacheResponder < ActionController::Responder
|
4
|
+
include Responders::HttpCacheResponder
|
5
|
+
end
|
6
|
+
|
7
|
+
class HttpCacheController < ApplicationController
|
8
|
+
self.responder = HttpCacheResponder
|
9
|
+
|
10
|
+
def single
|
11
|
+
options = params.slice(:http_cache)
|
12
|
+
response.last_modified = Time.utc(2008) if params[:last_modified]
|
13
|
+
respond_with(Model.new(Time.utc(2009)), options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def collection
|
17
|
+
respond_with [Model.new(Time.utc(2009)), Model.new(Time.utc(2008))]
|
18
|
+
end
|
19
|
+
|
20
|
+
def empty
|
21
|
+
respond_with []
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class HttpCacheResponderTest < ActionController::TestCase
|
26
|
+
tests HttpCacheController
|
27
|
+
|
28
|
+
def setup
|
29
|
+
@request.accept = "application/xml"
|
30
|
+
@controller.stubs(:polymorphic_url).returns("/")
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_last_modified_at_is_set_with_single_resource_on_get
|
34
|
+
get :single
|
35
|
+
assert_equal Time.utc(2009).httpdate, @response.headers["Last-Modified"]
|
36
|
+
assert_equal "<xml />", @response.body
|
37
|
+
assert_equal 200, @response.status
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_returns_not_modified_if_return_is_cache_is_still_valid
|
41
|
+
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2009, 6).httpdate
|
42
|
+
get :single
|
43
|
+
assert_equal 304, @response.status
|
44
|
+
assert_equal " ", @response.body
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_refreshes_last_modified_if_cache_is_expired
|
48
|
+
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2008, 6).httpdate
|
49
|
+
get :single
|
50
|
+
assert_equal Time.utc(2009).httpdate, @response.headers["Last-Modified"]
|
51
|
+
assert_equal "<xml />", @response.body
|
52
|
+
assert_equal 200, @response.status
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_does_not_set_cache_unless_get_requests
|
56
|
+
put :single
|
57
|
+
assert_nil @response.headers["Last-Modified"]
|
58
|
+
assert_equal 200, @response.status
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_does_not_use_cache_unless_get_requests
|
62
|
+
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2009, 6).httpdate
|
63
|
+
put :single
|
64
|
+
assert_equal 200, @response.status
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_does_not_set_cache_if_http_cache_is_false
|
68
|
+
get :single, :http_cache => false
|
69
|
+
assert_nil @response.headers["Last-Modified"]
|
70
|
+
assert_equal 200, @response.status
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_does_not_use_cache_if_http_cache_is_false
|
74
|
+
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2009, 6).httpdate
|
75
|
+
get :single, :http_cache => false
|
76
|
+
assert_equal 200, @response.status
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_does_not_set_cache_if_last_modified_already_set_in_response
|
80
|
+
get :single, :last_modified => true
|
81
|
+
assert_equal Time.utc(2008).httpdate, @response.headers["Last-Modified"]
|
82
|
+
assert_equal 200, @response.status
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_does_not_use_cache_if_last_modified_already_set_in_response
|
86
|
+
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2009, 6).httpdate
|
87
|
+
get :single, :last_modified => true
|
88
|
+
assert_equal 200, @response.status
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_collection_chooses_the_latest_timestamp
|
92
|
+
get :collection
|
93
|
+
assert_equal Time.utc(2009).httpdate, @response.headers["Last-Modified"]
|
94
|
+
assert_match /xml/, @response.body
|
95
|
+
assert_equal 200, @response.status
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_work_with_an_empty_array
|
99
|
+
get :empty
|
100
|
+
assert_nil @response.headers["Last-Modified"]
|
101
|
+
assert_match /xml/, @response.body
|
102
|
+
assert_equal 200, @response.status
|
103
|
+
end
|
104
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
begin
|
4
|
+
gem "test-unit"
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
gem "ruby-debug"
|
10
|
+
require 'ruby-debug'
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'test/unit'
|
15
|
+
require 'mocha'
|
16
|
+
|
17
|
+
# Configure Rails
|
18
|
+
ENV["RAILS_ENV"] = "test"
|
19
|
+
RAILS_ROOT = "anywhere"
|
20
|
+
|
21
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../../rails/vendor/gems/environment")
|
22
|
+
require 'active_support'
|
23
|
+
require 'action_controller'
|
24
|
+
require 'action_controller/testing/test_case'
|
25
|
+
|
26
|
+
class ApplicationController < ActionController::Base
|
27
|
+
respond_to :html, :xml
|
28
|
+
end
|
29
|
+
|
30
|
+
# Add IR to load path and load the main file
|
31
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
32
|
+
require 'responders'
|
33
|
+
|
34
|
+
I18n.load_path << File.join(File.dirname(__FILE__), 'locales', 'en.yml')
|
35
|
+
I18n.reload!
|
36
|
+
|
37
|
+
ActionController::Base.view_paths = File.join(File.dirname(__FILE__), 'views')
|
38
|
+
|
39
|
+
ActionController::Routing::Routes.draw do |map|
|
40
|
+
map.connect 'admin/:action', :controller => "admin/addresses"
|
41
|
+
map.connect ':controller/:action/:id'
|
42
|
+
map.connect ':controller/:action'
|
43
|
+
end
|
44
|
+
|
45
|
+
class Model < Struct.new(:updated_at)
|
46
|
+
def to_xml(*args)
|
47
|
+
"<xml />"
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: responders
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Jos\xC3\xA9 Valim"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-04 00:00:00 -02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: A set of Rails 3 responders to dry up your application
|
17
|
+
email: contact@plataformatec.com.br
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- CHANGELOG.rdoc
|
26
|
+
- MIT-LICENSE
|
27
|
+
- README.rdoc
|
28
|
+
- Rakefile
|
29
|
+
- lib/generators/USAGE
|
30
|
+
- lib/generators/responders_controller_generator.rb
|
31
|
+
- lib/generators/responders_install_generator.rb
|
32
|
+
- lib/generators/templates/controller.rb
|
33
|
+
- lib/responders.rb
|
34
|
+
- lib/responders/flash_responder.rb
|
35
|
+
- lib/responders/http_cache_responder.rb
|
36
|
+
- lib/responders/version.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/plataformatec/responders
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options:
|
43
|
+
- --charset=UTF-8
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.3.5
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: A set of Rails 3 responders to dry up your application
|
65
|
+
test_files:
|
66
|
+
- test/flash_responder_test.rb
|
67
|
+
- test/http_cache_responder_test.rb
|
68
|
+
- test/test_helper.rb
|