pax_global_header 0000666 0000000 0000000 00000000064 13664214554 0014524 g ustar 00root root 0000000 0000000 52 comment=5509904ce5e1f431f0856e14546380756c5f9329
responders-3.0.1/ 0000775 0000000 0000000 00000000000 13664214554 0013711 5 ustar 00root root 0000000 0000000 responders-3.0.1/.gitignore 0000664 0000000 0000000 00000000044 13664214554 0015677 0 ustar 00root root 0000000 0000000 *.gem
.bundle
gemfiles/*.lock
pkg/*
responders-3.0.1/.rubocop.yml 0000664 0000000 0000000 00000010350 13664214554 0016162 0 ustar 00root root 0000000 0000000 require:
- rubocop-performance
AllCops:
TargetRubyVersion: 2.4
# RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
# to ignore them, so only the ones explicitly set in this file are enabled.
DisabledByDefault: true
Performance:
Exclude:
- '**/test/**/*'
# Prefer &&/|| over and/or.
Style/AndOr:
Enabled: true
# Do not use braces for hash literals when they are the last argument of a
# method call.
Style/BracesAroundHashParameters:
Enabled: true
EnforcedStyle: context_dependent
# Align `when` with `case`.
Layout/CaseIndentation:
Enabled: true
# Align comments with method definitions.
Layout/CommentIndentation:
Enabled: true
Layout/ElseAlignment:
Enabled: true
# Align `end` with the matching keyword or starting expression except for
# assignments, where it should be aligned with the LHS.
Layout/EndAlignment:
Enabled: true
EnforcedStyleAlignWith: variable
AutoCorrect: true
Layout/EmptyLineAfterMagicComment:
Enabled: true
Layout/EmptyLinesAroundAccessModifier:
Enabled: true
Layout/EmptyLinesAroundBlockBody:
Enabled: true
# In a regular class definition, no empty lines around the body.
Layout/EmptyLinesAroundClassBody:
Enabled: true
# In a regular method definition, no empty lines around the body.
Layout/EmptyLinesAroundMethodBody:
Enabled: true
# In a regular module definition, no empty lines around the body.
Layout/EmptyLinesAroundModuleBody:
Enabled: true
# Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }.
Style/HashSyntax:
Enabled: true
Layout/IndentFirstArgument:
Enabled: true
Layout/IndentationConsistency:
Enabled: true
# Two spaces, no tabs (for indentation).
Layout/IndentationWidth:
Enabled: true
Layout/LeadingCommentSpace:
Enabled: true
Layout/SpaceAfterColon:
Enabled: true
Layout/SpaceAfterComma:
Enabled: true
Layout/SpaceAfterSemicolon:
Enabled: true
Layout/SpaceAroundEqualsInParameterDefault:
Enabled: true
Layout/SpaceAroundKeyword:
Enabled: true
Layout/SpaceAroundOperators:
Enabled: true
Layout/SpaceBeforeComma:
Enabled: true
Layout/SpaceBeforeComment:
Enabled: true
Layout/SpaceBeforeFirstArg:
Enabled: true
Style/DefWithParentheses:
Enabled: true
# Defining a method with parameters needs parentheses.
Style/MethodDefParentheses:
Enabled: true
Style/FrozenStringLiteralComment:
Enabled: true
EnforcedStyle: always
Style/RedundantFreeze:
Enabled: true
# Use `foo {}` not `foo{}`.
Layout/SpaceBeforeBlockBraces:
Enabled: true
# Use `foo { bar }` not `foo {bar}`.
Layout/SpaceInsideBlockBraces:
Enabled: true
EnforcedStyleForEmptyBraces: space
# Use `{ a: 1 }` not `{a:1}`.
Layout/SpaceInsideHashLiteralBraces:
Enabled: true
Layout/SpaceInsideParens:
Enabled: true
# Check quotes usage according to lint rule below.
Style/StringLiterals:
Enabled: true
EnforcedStyle: double_quotes
# Detect hard tabs, no hard tabs.
Layout/Tab:
Enabled: true
# Blank lines should not have any spaces.
Layout/TrailingBlankLines:
Enabled: true
# No trailing whitespace.
Layout/TrailingWhitespace:
Enabled: true
# Use quotes for string literals when they are enough.
Style/UnneededPercentQ:
Enabled: true
Lint/AmbiguousOperator:
Enabled: true
Lint/AmbiguousRegexpLiteral:
Enabled: true
Lint/ErbNewArguments:
Enabled: true
# Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
Lint/RequireParentheses:
Enabled: true
Lint/ShadowingOuterLocalVariable:
Enabled: true
Lint/StringConversionInInterpolation:
Enabled: true
Lint/UriEscapeUnescape:
Enabled: true
Lint/UselessAssignment:
Enabled: true
Lint/DeprecatedClassMethods:
Enabled: true
Style/ParenthesesAroundCondition:
Enabled: true
Style/RedundantBegin:
Enabled: true
Style/RedundantReturn:
Enabled: true
AllowMultipleReturnValues: true
Style/Semicolon:
Enabled: true
AllowAsExpressionSeparator: true
# Prefer Foo.method over Foo::method
Style/ColonMethodCall:
Enabled: true
Style/TrivialAccessors:
Enabled: true
Performance/FlatMap:
Enabled: true
Performance/RedundantMerge:
Enabled: true
Performance/StartWith:
Enabled: true
Performance/EndWith:
Enabled: true
Performance/RegexpMatch:
Enabled: true
Performance/ReverseEach:
Enabled: true
Performance/UnfreezeString:
Enabled: true
responders-3.0.1/.travis.yml 0000664 0000000 0000000 00000001711 13664214554 0016022 0 ustar 00root root 0000000 0000000 sudo: false
cache: bundler
language: ruby
rvm:
- '2.4'
- '2.5'
- '2.6'
- '2.7'
- ruby-head
gemfile:
- Gemfile
- gemfiles/Gemfile-rails.head
- gemfiles/Gemfile-rails.6.0.x
- gemfiles/Gemfile-rails.5.2.x
- gemfiles/Gemfile-rails.5.1.x
- gemfiles/Gemfile-rails.5.0.x
matrix:
exclude:
- rvm: '2.4'
gemfile: gemfiles/Gemfile-rails.6.0.x
- rvm: '2.4'
gemfile: gemfiles/Gemfile-rails.head
- rvm: '2.7'
gemfile: gemfiles/Gemfile-rails.5.0.x
- rvm: '2.7'
gemfile: gemfiles/Gemfile-rails.5.1.x
- rvm: '2.7'
gemfile: gemfiles/Gemfile-rails.5.2.x
allow_failures:
- rvm: ruby-head
- gemfile: gemfiles/Gemfile-rails.head
notifications:
email: false
slack:
on_pull_requests: false
on_success: change
on_failure: always
secure: Qr9/3LRW22qAoJ/9mynVKiI1p/AVIdW4GqcaymMjC6KH46EUwtbB4DxBa3K+gfBYOcfDKDe0vt3TUL/FMCgchqHum5QaNrAfSLj6k363sZqqW+dEuEMJO2e+QsIQUexBnDDQIJNSnr5DqoQ5+npZ8YwzWeAp8nRUs5uYI/RlXXo=
responders-3.0.1/CHANGELOG.md 0000664 0000000 0000000 00000006506 13664214554 0015531 0 ustar 00root root 0000000 0000000 ## 3.0.1
* Add support to Ruby 2.7
## 3.0.0
* Remove support for Rails 4.2
* Remove support for Ruby < 2.4
## 2.4.1
* Add support for Rails 6 beta
## 2.4.0
* `respond_with` now accepts a new kwargs called `:render` which goes straight to the `render`
call after an unsuccessful post request. Usefull if for example you need to render a template
which is outside of controller's path eg:
`respond_with resource, render: { template: 'path/to/template' }`
## 2.3.0
* `verify_request_format!` is aliased to `verify_requested_format!` now.
* Implementing the `interpolation_options` method on your controller is deprecated
in favor of naming it `flash_interpolation_options` instead.
## 2.2.0
* Added the `verify_request_format!` method, that can be used as a `before_action`
callback to prevent your actions from being invoked when the controller does
not respond to the request mime type, preventing the execution of complex
queries or creating/deleting records from your app.
## 2.1.2
* Fix rendering when using `ActionController::API`. (by @eLod)
* Added API controller template for the controller generator. (by @vestimir)
## 2.1.1
* Added support for Rails 5.
## 2.1.0
* No longer automatically set the responders generator as many projects may use this gem as a dependency. When upgrading, users will need to add `config.app_generators.scaffold_controller :responders_controller` to their application. The `responders:install` generator has been updated to automatically insert it in new applications
## 2.0.1
* Require `rails/railtie` explicitly before using it
* Require `action_controller` explicitly before using it
* Remove unnecessary and limiting `resourceful?` check that required models to implement `to_#{format}` (such checks are responsibility of the rendering layer)
## 2.0.0
* Import `respond_with` and class-level `respond_to` from Rails
* Support only Rails ~> 4.2
* `Responders::LocationResponder` is now included by the default responder (and therefore deprecated)
## 1.1.0
* Support Rails 4.1.
* Allow callable objects as the location.
## 1.0.0
* Improve controller generator to work closer to the Rails 4 one, and make it
compatible with strong parameters.
* Drop support for Rails 3.1 and Ruby 1.8, keep support for Rails 3.2
* Support for Rails 4.0 onward
* Fix flash message on destroy failure. Fixes #61
## 0.9.3
* Fix url generation for namespaced models
## 0.9.2
* Properly inflect custom responders names
## 0.9.1
* Fix bug with namespace lookup
## 0.9.0
* Disable namespace lookup by default
## 0.8
* Allow embedded HTML in flash messages
## 0.7
* Support Rails 3.1 onward
* Support namespaced engines
## 0.6
* Allow engine detection in generators
* HTTP Cache is no longer triggered for collections
* `:js` now sets the `flash.now` by default, instead of `flash`
* Renamed `responders_install` generator to `responders:install`
* Added `CollectionResponder` which allows you to always redirect to the collection path
(index action) after POST/PUT/DELETE
## 0.5
* Added Railtie and better Rails 3 support
* Added `:flash_now` as option
## 0.4
* Added `Responders::FlashResponder.flash_keys` and default to `[ :notice, :alert ]`
* Added support to `respond_with(@resource, :notice => "Yes!", :alert => "No!")``
## 0.1
* Added `FlashResponder`
* Added `HttpCacheResponder`
* Added responders generators
responders-3.0.1/Gemfile 0000664 0000000 0000000 00000000254 13664214554 0015205 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
source "https://rubygems.org"
gemspec
gem "activemodel"
gem "mocha"
gem "rails-controller-testing"
gem "rubocop"
gem "rubocop-performance"
responders-3.0.1/Gemfile.lock 0000664 0000000 0000000 00000004544 13664214554 0016142 0 ustar 00root root 0000000 0000000 PATH
remote: .
specs:
responders (3.0.1)
actionpack (>= 5.0)
railties (>= 5.0)
GEM
remote: https://rubygems.org/
specs:
actionpack (6.0.3.1)
actionview (= 6.0.3.1)
activesupport (= 6.0.3.1)
rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (6.0.3.1)
activesupport (= 6.0.3.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activemodel (6.0.3.1)
activesupport (= 6.0.3.1)
activesupport (6.0.3.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
ast (2.4.0)
builder (3.2.4)
concurrent-ruby (1.1.6)
crass (1.0.6)
erubi (1.9.0)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
loofah (2.5.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
method_source (1.0.0)
mini_portile2 (2.4.0)
minitest (5.14.1)
mocha (1.11.2)
nokogiri (1.10.9)
mini_portile2 (~> 2.4.0)
parallel (1.19.1)
parser (2.7.1.3)
ast (~> 2.4.0)
rack (2.2.2)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails-controller-testing (1.0.4)
actionpack (>= 5.0.1.x)
actionview (>= 5.0.1.x)
activesupport (>= 5.0.1.x)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
railties (6.0.3.1)
actionpack (= 6.0.3.1)
activesupport (= 6.0.3.1)
method_source
rake (>= 0.8.7)
thor (>= 0.20.3, < 2.0)
rainbow (3.0.0)
rake (13.0.1)
rexml (3.2.4)
rubocop (0.84.0)
parallel (~> 1.10)
parser (>= 2.7.0.1)
rainbow (>= 2.2.2, < 4.0)
rexml
rubocop-ast (>= 0.0.3)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 2.0)
rubocop-ast (0.0.3)
parser (>= 2.7.0.1)
rubocop-performance (1.6.0)
rubocop (>= 0.71.0)
ruby-progressbar (1.10.1)
thor (1.0.1)
thread_safe (0.3.6)
tzinfo (1.2.7)
thread_safe (~> 0.1)
unicode-display_width (1.7.0)
zeitwerk (2.3.0)
PLATFORMS
ruby
DEPENDENCIES
activemodel
mocha
rails-controller-testing
responders!
rubocop
rubocop-performance
BUNDLED WITH
2.1.4
responders-3.0.1/MIT-LICENSE 0000664 0000000 0000000 00000002173 13664214554 0015350 0 ustar 00root root 0000000 0000000 Copyright (c) 2020 Rafael França, Carlos Antônio da Silva
Copyright 2009-2019 Plataformatec. http://plataformatec.com.br
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
responders-3.0.1/README.md 0000664 0000000 0000000 00000017543 13664214554 0015202 0 ustar 00root root 0000000 0000000 # Responders
[](http://badge.fury.io/rb/responders)
[](http://travis-ci.org/heartcombo/responders)
[](https://codeclimate.com/github/heartcombo/responders)
A set of responders modules to dry up your Rails app.
## Installation
Add the responders gem to your Gemfile:
gem "responders"
Update your bundle and run the install generator:
$ bundle install
$ rails g responders:install
If you are including this gem to support backwards compatibilty for responders in previous releases of Rails, you only need to include the gem and bundle.
$ bundle install
## Responders Types
### FlashResponder
Sets the flash based on the controller action and resource status.
For instance, if you do: `respond_with(@post)` on a POST request and the resource `@post`
does not contain errors, it will automatically set the flash message to
`"Post was successfully created"` as long as you configure your I18n file:
```yaml
flash:
actions:
create:
notice: "%{resource_name} was successfully created."
update:
notice: "%{resource_name} was successfully updated."
destroy:
notice: "%{resource_name} was successfully destroyed."
alert: "%{resource_name} could not be destroyed."
```
In case the resource contains errors, you should use the failure key on I18n. This is
useful to dry up flash messages from your controllers. Note: by default alerts for `update`
and `destroy` actions are commented in generated I18n file. If you need a specific message
for a controller, let's say, for `PostsController`, you can also do:
```yaml
flash:
posts:
create:
notice: "Your post was created and will be published soon"
```
This responder is activated in all non get requests. By default it will use the keys
`:notice` and `:alert`, but they can be changed in your application:
```ruby
config.responders.flash_keys = [ :success, :failure ]
```
You can also have embedded HTML. Just create a `_html` scope.
```yaml
flash:
actions:
create:
alert_html: "OH NOES! You did it wrong!"
posts:
create:
notice_html: "Yay! You did it!"
```
See also the `namespace_lookup` option to search the full hierarchy of possible keys.
### HttpCacheResponder
Automatically adds Last-Modified headers to API requests. This
allows clients to easily query the server if a resource changed and if the client tries
to retrieve a resource that has not been modified, it returns not_modified status.
### CollectionResponder
Makes your create and update action redirect to the collection on success.
### LocationResponder
This responder allows you to use callable objects as the redirect location.
Useful when you want to use the `respond_with` method with
a custom route that requires persisted objects, but the validation may fail.
Note: this responder is included by default, and doesn't need to be included
on the top of your controller (including it will issue a deprecation warning).
```ruby
class ThingsController < ApplicationController
respond_to :html
def create
@thing = Thing.create(params[:thing])
respond_with @thing, location: -> { thing_path(@thing) }
end
end
```
**Dealing with namespaced routes**
In order for the LocationResponder to find the correct route helper for namespaced routes you need to pass the namespaces to `respond_with`:
```ruby
class Api::V1::ThingsController < ApplicationController
respond_to :json
# POST /api/v1/things
def create
@thing = Thing.create(thing_params)
respond_with :api, :v1, @thing
end
end
```
## Configuring your own responder
Responders only provides a set of modules and to use them you have to create your own
responder. After you run the install command, the following responder will be
generated in your application:
```ruby
# lib/application_responder.rb
class ApplicationResponder < ActionController::Responder
include Responders::FlashResponder
include Responders::HttpCacheResponder
end
```
Your application also needs to be configured to use it:
```ruby
# app/controllers/application_controller.rb
require "application_responder"
class ApplicationController < ActionController::Base
self.responder = ApplicationResponder
respond_to :html
end
```
## Controller method
This gem also includes the controller method `responders`, which allows you to cherry-pick which
responders you want included in your controller.
```ruby
class InvitationsController < ApplicationController
responders :flash, :http_cache
end
```
## Interpolation Options
You can pass in extra interpolation options for the translation by adding an `flash_interpolation_options` method to your controller:
```ruby
class InvitationsController < ApplicationController
responders :flash, :http_cache
def create
@invitation = Invitation.create(params[:invitation])
respond_with @invitation
end
private
def flash_interpolation_options
{ resource_name: @invitation.email }
end
end
```
Now you would see the message `"name@example.com was successfully created"` instead of the default `"Invitation was successfully created."`
## Generator
This gem also includes a responders controller generator, so your scaffold can be customized
to use `respond_with` instead of default `respond_to` blocks. From 2.1, you need to explicitly opt-in to use this generator by adding the following to your `config/application.rb`:
```ruby
config.app_generators.scaffold_controller :responders_controller
```
## Failure handling
Responders don't use `valid?` to check for errors in models to figure out if
the request was successful or not, and relies on your controllers to call
`save` or `create` to trigger the validations.
```ruby
def create
@widget = Widget.new(widget_params)
# @widget will be a valid record for responders, as we haven't called `save`
# on it, and will always redirect to the `widgets_path`.
respond_with @widget, location: -> { widgets_path }
end
```
Responders will check if the `errors` object in your model is empty or not. Take
this in consideration when implementing different actions or writing test
assertions on this behavior for your controllers.
```ruby
def create
@widget = Widget.new(widget_params)
@widget.errors.add(:base, :invalid)
# `respond_with` will render the `new` template again.
respond_with @widget
end
```
## Verifying request formats
`respond_with` will raise an `ActionController::UnknownFormat` if the request
MIME type was not configured through the class level `respond_to`, but the
action will still be executed and any side effects (like creating a new record)
will still occur. To raise the `UnknownFormat` exception before your action
is invoked you can set the `verify_requested_format!` method as a `before_action`
on your controller.
```ruby
class WidgetsController < ApplicationController
respond_to :json
before_action :verify_requested_format!
# POST /widgets.html won't reach the `create` action.
def create
widget = Widget.create(widget_params)
respond_with widget
end
end
```
## Examples
Want more examples ? Check out these blog posts:
* [Embracing REST with mind, body and soul](http://blog.plataformatec.com.br/2009/08/embracing-rest-with-mind-body-and-soul/)
* [Three reasons to love ActionController::Responder](http://weblog.rubyonrails.org/2009/8/31/three-reasons-love-responder/)
* [My five favorite things about Rails 3](http://www.engineyard.com/blog/2009/my-five-favorite-things-about-rails-3)
## Bugs and Feedback
If you discover any bugs or want to drop a line, feel free to create an issue on GitHub.
http://github.com/heartcombo/responders/issues
MIT License. Copyright 2020 Rafael França, Carlos Antônio da Silva. Copyright 2009-2019 Plataformatec.
responders-3.0.1/Rakefile 0000664 0000000 0000000 00000001225 13664214554 0015356 0 ustar 00root root 0000000 0000000 # encoding: UTF-8
# frozen_string_literal: true
require "bundler/gem_tasks"
require "rake/testtask"
require "rdoc/task"
require File.join(File.dirname(__FILE__), "lib", "responders", "version")
desc "Default: run unit tests"
task default: :test
desc "Test Responders"
Rake::TestTask.new(:test) do |t|
t.libs << "test"
t.pattern = "test/**/*_test.rb"
t.verbose = true
end
desc "Generate documentation for Responders"
Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = "rdoc"
rdoc.title = "Responders"
rdoc.options << "--line-numbers" << "--inline-source"
rdoc.rdoc_files.include("README.rdoc")
rdoc.rdoc_files.include("lib/**/*.rb")
end
responders-3.0.1/gemfiles/ 0000775 0000000 0000000 00000000000 13664214554 0015504 5 ustar 00root root 0000000 0000000 responders-3.0.1/gemfiles/Gemfile-rails.5.0.x 0000664 0000000 0000000 00000000331 13664214554 0020653 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gemspec path: '..'
gem 'activemodel', github: 'rails/rails', branch: '5-0-stable'
gem 'railties', github: 'rails/rails', branch: '5-0-stable'
gem 'mocha'
gem 'rails-controller-testing'
responders-3.0.1/gemfiles/Gemfile-rails.5.1.x 0000664 0000000 0000000 00000000331 13664214554 0020654 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gemspec path: '..'
gem 'activemodel', github: 'rails/rails', branch: '5-1-stable'
gem 'railties', github: 'rails/rails', branch: '5-1-stable'
gem 'mocha'
gem 'rails-controller-testing'
responders-3.0.1/gemfiles/Gemfile-rails.5.2.x 0000664 0000000 0000000 00000000331 13664214554 0020655 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gemspec path: '..'
gem 'activemodel', github: 'rails/rails', branch: '5-2-stable'
gem 'railties', github: 'rails/rails', branch: '5-2-stable'
gem 'mocha'
gem 'rails-controller-testing'
responders-3.0.1/gemfiles/Gemfile-rails.6.0.x 0000664 0000000 0000000 00000000227 13664214554 0020660 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gemspec path: '..'
gem 'activemodel', '~> 6.0.0'
gem 'railties', '~> 6.0.0'
gem 'mocha'
gem 'rails-controller-testing'
responders-3.0.1/gemfiles/Gemfile-rails.head 0000664 0000000 0000000 00000000255 13664214554 0021011 0 ustar 00root root 0000000 0000000 source 'https://rubygems.org'
gemspec path: '..'
gem 'activemodel', github: 'rails/rails'
gem 'railties', github: 'rails/rails'
gem 'mocha'
gem 'rails-controller-testing'
responders-3.0.1/lib/ 0000775 0000000 0000000 00000000000 13664214554 0014457 5 ustar 00root root 0000000 0000000 responders-3.0.1/lib/action_controller/ 0000775 0000000 0000000 00000000000 13664214554 0020177 5 ustar 00root root 0000000 0000000 responders-3.0.1/lib/action_controller/respond_with.rb 0000664 0000000 0000000 00000024115 13664214554 0023234 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "active_support/core_ext/array/extract_options"
require "action_controller/metal/mime_responds"
module ActionController #:nodoc:
module RespondWith
extend ActiveSupport::Concern
included do
class_attribute :responder, :mimes_for_respond_to
self.responder = ActionController::Responder
clear_respond_to
end
module ClassMethods
# Defines mime types that are rendered by default when invoking
# respond_with.
#
# respond_to :html, :xml, :json
#
# Specifies that all actions in the controller respond to requests
# for :html, :xml and :json.
#
# To specify on per-action basis, use :only and
# :except with an array of actions or a single action:
#
# respond_to :html
# respond_to :xml, :json, except: [ :edit ]
#
# This specifies that all actions respond to :html
# and all actions except :edit respond to :xml and
# :json.
#
# respond_to :json, only: :create
#
# This specifies that the :create action and no other responds
# to :json.
def respond_to(*mimes)
options = mimes.extract_options!
only_actions = Array(options.delete(:only)).map(&:to_sym)
except_actions = Array(options.delete(:except)).map(&:to_sym)
hash = mimes_for_respond_to.dup
mimes.each do |mime|
mime = mime.to_sym
hash[mime] = {}
hash[mime][:only] = only_actions unless only_actions.empty?
hash[mime][:except] = except_actions unless except_actions.empty?
end
self.mimes_for_respond_to = hash.freeze
end
# Clear all mime types in respond_to.
#
def clear_respond_to
self.mimes_for_respond_to = Hash.new.freeze
end
end
# For a given controller action, respond_with generates an appropriate
# response based on the mime-type requested by the client.
#
# If the method is called with just a resource, as in this example -
#
# class PeopleController < ApplicationController
# respond_to :html, :xml, :json
#
# def index
# @people = Person.all
# respond_with @people
# end
# end
#
# then the mime-type of the response is typically selected based on the
# request's Accept header and the set of available formats declared
# by previous calls to the controller's class method +respond_to+. Alternatively
# the mime-type can be selected by explicitly setting request.format in
# the controller.
#
# If an acceptable format is not identified, the application returns a
# '406 - not acceptable' status. Otherwise, the default response is to render
# a template named after the current action and the selected format,
# e.g. index.html.erb. If no template is available, the behavior
# depends on the selected format:
#
# * for an html response - if the request method is +get+, an exception
# is raised but for other requests such as +post+ the response
# depends on whether the resource has any validation errors (i.e.
# assuming that an attempt has been made to save the resource,
# e.g. by a +create+ action) -
# 1. If there are no errors, i.e. the resource
# was saved successfully, the response +redirect+'s to the resource
# i.e. its +show+ action.
# 2. If there are validation errors, the response
# renders a default action, which is :new for a
# +post+ request or :edit for +patch+ or +put+.
# Thus an example like this -
#
# respond_to :html, :xml
#
# def create
# @user = User.new(params[:user])
# flash[:notice] = 'User was successfully created.' if @user.save
# respond_with(@user)
# end
#
# is equivalent, in the absence of create.html.erb, to -
#
# def create
# @user = User.new(params[:user])
# respond_to do |format|
# if @user.save
# flash[:notice] = 'User was successfully created.'
# format.html { redirect_to(@user) }
# format.xml { render xml: @user }
# else
# format.html { render action: "new" }
# format.xml { render xml: @user }
# end
# end
# end
#
# * for a JavaScript request - if the template isn't found, an exception is
# raised.
# * for other requests - i.e. data formats such as xml, json, csv etc, if
# the resource passed to +respond_with+ responds to to_
,
# the method attempts to render the resource in the requested format
# directly, e.g. for an xml request, the response is equivalent to calling
# render xml: resource
.
#
# === Nested resources
#
# As outlined above, the +resources+ argument passed to +respond_with+
# can play two roles. It can be used to generate the redirect url
# for successful html requests (e.g. for +create+ actions when
# no template exists), while for formats other than html and JavaScript
# it is the object that gets rendered, by being converted directly to the
# required format (again assuming no template exists).
#
# For redirecting successful html requests, +respond_with+ also supports
# the use of nested resources, which are supplied in the same way as
# in form_for
and polymorphic_url
. For example -
#
# def create
# @project = Project.find(params[:project_id])
# @task = @project.comments.build(params[:task])
# flash[:notice] = 'Task was successfully created.' if @task.save
# respond_with(@project, @task)
# end
#
# This would cause +respond_with+ to redirect to project_task_url
# instead of task_url
. For request formats other than html or
# JavaScript, if multiple resources are passed in this way, it is the last
# one specified that is rendered.
#
# === Customizing response behavior
#
# Like +respond_to+, +respond_with+ may also be called with a block that
# can be used to overwrite any of the default responses, e.g. -
#
# def create
# @user = User.new(params[:user])
# flash[:notice] = "User was successfully created." if @user.save
#
# respond_with(@user) do |format|
# format.html { render }
# end
# end
#
# The argument passed to the block is an ActionController::MimeResponds::Collector
# object which stores the responses for the formats defined within the
# block. Note that formats with responses defined explicitly in this way
# do not have to first be declared using the class method +respond_to+.
#
# Also, a hash passed to +respond_with+ immediately after the specified
# resource(s) is interpreted as a set of options relevant to all
# formats. Any option accepted by +render+ can be used, e.g.
#
# respond_with @people, status: 200
#
# However, note that these options are ignored after an unsuccessful attempt
# to save a resource, e.g. when automatically rendering :new
# after a post request.
#
# Three additional options are relevant specifically to +respond_with+ -
# 1. :location - overwrites the default redirect location used after
# a successful html +post+ request.
# 2. :action - overwrites the default render action used after an
# unsuccessful html +post+ request.
# 3. :render - allows to pass any options directly to the :render
# call after unsuccessful html +post+ request. Useful if for example you
# need to render a template which is outside of controller's path or you
# want to override the default http :status code, e.g.
#
# respond_with(resource, render: { template: 'path/to/template', status: 422 })
def respond_with(*resources, &block)
if self.class.mimes_for_respond_to.empty?
raise "In order to use respond_with, first you need to declare the " \
"formats your controller responds to in the class level."
end
mimes = collect_mimes_from_class_level
collector = ActionController::MimeResponds::Collector.new(mimes, request.variant)
block.call(collector) if block_given?
if format = collector.negotiate_format(request)
_process_format(format)
options = resources.size == 1 ? {} : resources.extract_options!
options = options.clone
options[:default_response] = collector.response
(options.delete(:responder) || self.class.responder).call(self, resources, options)
else
raise ActionController::UnknownFormat
end
end
protected
# Before action callback that can be used to prevent requests that do not
# match the mime types defined through respond_to from being executed.
#
# class PeopleController < ApplicationController
# respond_to :html, :xml, :json
#
# before_action :verify_requested_format!
# end
def verify_requested_format!
mimes = collect_mimes_from_class_level
collector = ActionController::MimeResponds::Collector.new(mimes, request.variant)
unless collector.negotiate_format(request)
raise ActionController::UnknownFormat
end
end
alias :verify_request_format! :verify_requested_format!
# Collect mimes declared in the class method respond_to valid for the
# current action.
def collect_mimes_from_class_level #:nodoc:
action = action_name.to_sym
self.class.mimes_for_respond_to.keys.select do |mime|
config = self.class.mimes_for_respond_to[mime]
if config[:except]
!config[:except].include?(action)
elsif config[:only]
config[:only].include?(action)
else
true
end
end
end
end
end
responders-3.0.1/lib/action_controller/responder.rb 0000664 0000000 0000000 00000022554 13664214554 0022535 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "active_support/json"
module ActionController #:nodoc:
# Responsible for exposing a resource to different mime requests,
# usually depending on the HTTP verb. The responder is triggered when
# respond_with
is called. The simplest case to study is a GET request:
#
# class PeopleController < ApplicationController
# respond_to :html, :xml, :json
#
# def index
# @people = Person.all
# respond_with(@people)
# end
# end
#
# When a request comes in, for example for an XML response, three steps happen:
#
# 1) the responder searches for a template at people/index.xml;
#
# 2) if the template is not available, it will invoke #to_xml
on the given resource;
#
# 3) if the responder does not respond_to :to_xml
, call #to_format
on it.
#
# === Built-in HTTP verb semantics
#
# The default \Rails responder holds semantics for each HTTP verb. Depending on the
# content type, verb and the resource status, it will behave differently.
#
# Using \Rails default responder, a POST request for creating an object could
# be written as:
#
# def create
# @user = User.new(params[:user])
# flash[:notice] = 'User was successfully created.' if @user.save
# respond_with(@user)
# end
#
# Which is exactly the same as:
#
# def create
# @user = User.new(params[:user])
#
# respond_to do |format|
# if @user.save
# flash[:notice] = 'User was successfully created.'
# format.html { redirect_to(@user) }
# format.xml { render xml: @user, status: :created, location: @user }
# else
# format.html { render action: "new" }
# format.xml { render xml: @user.errors, status: :unprocessable_entity }
# end
# end
# end
#
# The same happens for PATCH/PUT and DELETE requests.
#
# === Nested resources
#
# You can supply nested resources as you do in form_for
and polymorphic_url
.
# Consider the project has many tasks example. The create action for
# TasksController would be like:
#
# def create
# @project = Project.find(params[:project_id])
# @task = @project.tasks.build(params[:task])
# flash[:notice] = 'Task was successfully created.' if @task.save
# respond_with(@project, @task)
# end
#
# Giving several resources ensures that the responder will redirect to
# project_task_url
instead of task_url
.
#
# Namespaced and singleton resources require a symbol to be given, as in
# polymorphic urls. If a project has one manager which has many tasks, it
# should be invoked as:
#
# respond_with(@project, :manager, @task)
#
# Note that if you give an array, it will be treated as a collection,
# so the following is not equivalent:
#
# respond_with [@project, :manager, @task]
#
# === Custom options
#
# respond_with
also allows you to pass options that are forwarded
# to the underlying render call. Those options are only applied for success
# scenarios. For instance, you can do the following in the create method above:
#
# def create
# @project = Project.find(params[:project_id])
# @task = @project.tasks.build(params[:task])
# flash[:notice] = 'Task was successfully created.' if @task.save
# respond_with(@project, @task, status: 201)
# end
#
# This will return status 201 if the task was saved successfully. If not,
# it will simply ignore the given options and return status 422 and the
# resource errors. You can also override the location to redirect to:
#
# respond_with(@project, location: root_path)
#
# To customize the failure scenario, you can pass a block to
# respond_with
:
#
# def create
# @project = Project.find(params[:project_id])
# @task = @project.tasks.build(params[:task])
# respond_with(@project, @task, status: 201) do |format|
# if @task.save
# flash[:notice] = 'Task was successfully created.'
# else
# format.html { render "some_special_template" }
# end
# end
# end
#
# Using respond_with
with a block follows the same syntax as respond_to
.
class Responder
attr_reader :controller, :request, :format, :resource, :resources, :options
DEFAULT_ACTIONS_FOR_VERBS = {
post: :new,
patch: :edit,
put: :edit
}
def initialize(controller, resources, options = {})
@controller = controller
@request = @controller.request
@format = @controller.formats.first
@resource = resources.last
@resources = resources
@options = options
@action = options.delete(:action)
@default_response = options.delete(:default_response)
if options[:location].respond_to?(:call)
location = options.delete(:location)
options[:location] = location.call unless has_errors?
end
end
delegate :head, :render, :redirect_to, to: :controller
delegate :get?, :post?, :patch?, :put?, :delete?, to: :request
# Undefine :to_json and :to_yaml since it's defined on Object
undef_method(:to_json) if method_defined?(:to_json)
undef_method(:to_yaml) if method_defined?(:to_yaml)
# Initializes a new responder and invokes the proper format. If the format is
# not defined, call to_format.
#
def self.call(*args)
new(*args).respond
end
# Main entry point for responder responsible to dispatch to the proper format.
#
def respond
method = "to_#{format}"
respond_to?(method) ? send(method) : to_format
end
# HTML format does not render the resource, it always attempt to render a
# template.
#
def to_html
default_render
rescue ActionView::MissingTemplate => e
navigation_behavior(e)
end
# to_js simply tries to render a template. If no template is found, raises the error.
def to_js
default_render
end
# All other formats follow the procedure below. First we try to render a
# template, if the template is not available, we verify if the resource
# responds to :to_format and display it.
#
def to_format
if !get? && has_errors? && !response_overridden?
display_errors
elsif has_view_rendering? || response_overridden?
default_render
else
api_behavior
end
rescue ActionView::MissingTemplate
api_behavior
end
protected
# This is the common behavior for formats associated with browsing, like :html, :iphone and so forth.
def navigation_behavior(error)
if get?
raise error
elsif has_errors? && default_action
render rendering_options
else
redirect_to navigation_location
end
end
# This is the common behavior for formats associated with APIs, such as :xml and :json.
def api_behavior
raise MissingRenderer.new(format) unless has_renderer?
if get?
display resource
elsif post?
display resource, status: :created, location: api_location
else
head :no_content
end
end
# Returns the resource location by retrieving it from the options or
# returning the resources array.
#
def resource_location
options[:location] || resources
end
alias :navigation_location :resource_location
alias :api_location :resource_location
# If a response block was given, use it, otherwise call render on
# controller.
#
def default_render
if @default_response
@default_response.call(options)
else
controller.render(options)
end
end
# Display is just a shortcut to render a resource with the current format.
#
# display @user, status: :ok
#
# For XML requests it's equivalent to:
#
# render xml: @user, status: :ok
#
# Options sent by the user are also used:
#
# respond_with(@user, status: :created)
# display(@user, status: :ok)
#
# Results in:
#
# render xml: @user, status: :created
#
def display(resource, given_options = {})
controller.render given_options.merge!(options).merge!(format => resource)
end
def display_errors
controller.render format => resource_errors, :status => :unprocessable_entity
end
# Check whether the resource has errors.
#
def has_errors?
resource.respond_to?(:errors) && !resource.errors.empty?
end
# Check whether the necessary Renderer is available
def has_renderer?
Renderers::RENDERERS.include?(format)
end
def has_view_rendering?
controller.class.include? ActionView::Rendering
end
# By default, render the :edit
action for HTML requests with errors, unless
# the verb was POST.
#
def default_action
@action ||= DEFAULT_ACTIONS_FOR_VERBS[request.request_method_symbol]
end
def resource_errors
respond_to?("#{format}_resource_errors", true) ? send("#{format}_resource_errors") : resource.errors
end
def json_resource_errors
{ errors: resource.errors }
end
def response_overridden?
@default_response.present?
end
def rendering_options
if options[:render]
options[:render]
else
{ action: default_action }
end
end
end
end
responders-3.0.1/lib/generators/ 0000775 0000000 0000000 00000000000 13664214554 0016630 5 ustar 00root root 0000000 0000000 responders-3.0.1/lib/generators/rails/ 0000775 0000000 0000000 00000000000 13664214554 0017742 5 ustar 00root root 0000000 0000000 responders-3.0.1/lib/generators/rails/USAGE 0000664 0000000 0000000 00000001050 13664214554 0020525 0 ustar 00root root 0000000 0000000 Description:
Stubs out a scaffolded controller and its views. Different from rails
scaffold_controller, it uses respond_with instead of respond_to blocks.
Pass the model name, either CamelCased or under_scored. The controller
name is retrieved as a pluralized version of the model name.
To create a controller within a module, specify the model name as a
path like 'parent_module/controller_name'.
This generates a controller class in app/controllers and invokes helper,
template engine and test framework generators.
responders-3.0.1/lib/generators/rails/responders_controller_generator.rb 0000664 0000000 0000000 00000001203 13664214554 0026760 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "rails/generators/rails/scaffold_controller/scaffold_controller_generator"
module Rails
module Generators
class RespondersControllerGenerator < ScaffoldControllerGenerator
source_root File.expand_path("../templates", __FILE__)
protected
def flash?
if defined?(ApplicationController)
!ApplicationController.responder.ancestors.include?(Responders::FlashResponder)
else
Rails.application.config.responders.flash_keys.blank?
end
end
def attributes_params
"#{singular_table_name}_params"
end
end
end
end
responders-3.0.1/lib/generators/rails/templates/ 0000775 0000000 0000000 00000000000 13664214554 0021740 5 ustar 00root root 0000000 0000000 responders-3.0.1/lib/generators/rails/templates/api_controller.rb.tt 0000664 0000000 0000000 00000003027 13664214554 0025731 0 ustar 00root root 0000000 0000000 <% if namespaced? -%>
require_dependency "<%= namespaced_file_path %>/application_controller"
<% end -%>
<% module_namespacing do -%>
class <%= controller_class_name %>Controller < ApplicationController
before_action :set_<%= singular_table_name %>, only: [:show, :update, :destroy]
respond_to :json
<% unless options[:singleton] -%>
def index
@<%= plural_table_name %> = <%= orm_class.all(class_name) %>
respond_with(@<%= plural_table_name %>)
end
<% end -%>
def show
respond_with(@<%= singular_table_name %>)
end
def create
@<%= singular_table_name %> = <%= orm_class.build(class_name, attributes_params) %>
<%= "flash[:notice] = '#{class_name} was successfully created.' if " if flash? %>@<%= orm_instance.save %>
respond_with(@<%= singular_table_name %>)
end
def update
<%= "flash[:notice] = '#{class_name} was successfully updated.' if " if flash? %>@<%= orm_instance.update(attributes_params) %>
respond_with(@<%= singular_table_name %>)
end
def destroy
@<%= orm_instance.destroy %>
respond_with(@<%= singular_table_name %>)
end
private
def set_<%= singular_table_name %>
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
end
def <%= "#{singular_table_name}_params" %>
<%- if attributes_names.empty? -%>
params[:<%= singular_table_name %>]
<%- else -%>
params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
<%- end -%>
end
end
<% end -%>
responders-3.0.1/lib/generators/rails/templates/controller.rb.tt 0000664 0000000 0000000 00000003264 13664214554 0025103 0 ustar 00root root 0000000 0000000 <% if namespaced? -%>
require_dependency "<%= namespaced_file_path %>/application_controller"
<% end -%>
<% module_namespacing do -%>
class <%= controller_class_name %>Controller < ApplicationController
before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
respond_to :html
<% unless options[:singleton] -%>
def index
@<%= plural_table_name %> = <%= orm_class.all(class_name) %>
respond_with(@<%= plural_table_name %>)
end
<% end -%>
def show
respond_with(@<%= singular_table_name %>)
end
def new
@<%= singular_table_name %> = <%= orm_class.build(class_name) %>
respond_with(@<%= singular_table_name %>)
end
def edit
end
def create
@<%= singular_table_name %> = <%= orm_class.build(class_name, attributes_params) %>
<%= "flash[:notice] = '#{class_name} was successfully created.' if " if flash? %>@<%= orm_instance.save %>
respond_with(@<%= singular_table_name %>)
end
def update
<%= "flash[:notice] = '#{class_name} was successfully updated.' if " if flash? %>@<%= orm_instance.update(attributes_params) %>
respond_with(@<%= singular_table_name %>)
end
def destroy
@<%= orm_instance.destroy %>
respond_with(@<%= singular_table_name %>)
end
private
def set_<%= singular_table_name %>
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
end
def <%= "#{singular_table_name}_params" %>
<%- if attributes_names.empty? -%>
params[:<%= singular_table_name %>]
<%- else -%>
params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
<%- end -%>
end
end
<% end -%>
responders-3.0.1/lib/generators/responders/ 0000775 0000000 0000000 00000000000 13664214554 0021014 5 ustar 00root root 0000000 0000000 responders-3.0.1/lib/generators/responders/install_generator.rb 0000664 0000000 0000000 00000002634 13664214554 0025062 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Responders
module Generators
class InstallGenerator < Rails::Generators::Base
source_root File.expand_path("..", __FILE__)
desc "Creates an initializer with default responder configuration and copy locale file"
def create_responder_file
create_file "lib/application_responder.rb", <<-RUBY
class ApplicationResponder < ActionController::Responder
include Responders::FlashResponder
include Responders::HttpCacheResponder
# Redirects resources to the collection path (index action) instead
# of the resource path (show action) for POST/PUT/DELETE requests.
# include Responders::CollectionResponder
end
RUBY
end
def update_application
inject_into_class "config/application.rb", "Application", <<-RUBY
# Use the responders controller from the responders gem
config.app_generators.scaffold_controller :responders_controller
RUBY
end
def update_application_controller
prepend_file "app/controllers/application_controller.rb", %{require "application_responder"\n\n}
inject_into_class "app/controllers/application_controller.rb", "ApplicationController", <<-RUBY
self.responder = ApplicationResponder
respond_to :html
RUBY
end
def copy_locale
copy_file "../../responders/locales/en.yml", "config/locales/responders.en.yml"
end
end
end
end
responders-3.0.1/lib/responders.rb 0000664 0000000 0000000 00000002370 13664214554 0017172 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "action_controller"
require "rails/railtie"
module ActionController
autoload :Responder, "action_controller/responder"
autoload :RespondWith, "action_controller/respond_with"
end
module Responders
autoload :FlashResponder, "responders/flash_responder"
autoload :HttpCacheResponder, "responders/http_cache_responder"
autoload :CollectionResponder, "responders/collection_responder"
autoload :LocationResponder, "responders/location_responder"
require "responders/controller_method"
class Railtie < ::Rails::Railtie
config.responders = ActiveSupport::OrderedOptions.new
config.responders.flash_keys = [:notice, :alert]
config.responders.namespace_lookup = false
# Add load paths straight to I18n, so engines and application can overwrite it.
require "active_support/i18n"
I18n.load_path << File.expand_path("../responders/locales/en.yml", __FILE__)
initializer "responders.flash_responder" do |app|
Responders::FlashResponder.flash_keys = app.config.responders.flash_keys
Responders::FlashResponder.namespace_lookup = app.config.responders.namespace_lookup
end
end
end
ActiveSupport.on_load(:action_controller) do
include ActionController::RespondWith
end
responders-3.0.1/lib/responders/ 0000775 0000000 0000000 00000000000 13664214554 0016643 5 ustar 00root root 0000000 0000000 responders-3.0.1/lib/responders/collection_responder.rb 0000664 0000000 0000000 00000001714 13664214554 0023407 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Responders
# This responder modifies your current responder to redirect
# to the collection page on POST/PUT/DELETE.
module CollectionResponder
protected
# Returns the collection location for redirecting after POST/PUT/DELETE.
# This method, converts the following resources array to the following:
#
# [:admin, @post] #=> [:admin, :posts]
# [@user, @post] #=> [@user, :posts]
#
# When these new arrays are given to redirect_to, it will generate the
# proper URL pointing to the index action.
#
# [:admin, @post] #=> admin_posts_url
# [@user, @post] #=> user_posts_url(@user.to_param)
#
def navigation_location
return options[:location] if options[:location]
klass = resources.last.class
if klass.respond_to?(:model_name)
resources[0...-1] << klass.model_name.route_key.to_sym
else
resources
end
end
end
end
responders-3.0.1/lib/responders/controller_method.rb 0000664 0000000 0000000 00000002424 13664214554 0022715 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Responders
module ControllerMethod
# Adds the given responders to the current controller's responder, allowing you to cherry-pick
# which responders you want per controller.
#
# class InvitationsController < ApplicationController
# responders :flash, :http_cache
# end
#
# Takes symbols and strings and translates them to VariableResponder (eg. :flash becomes FlashResponder).
# Also allows passing in the responders modules in directly, so you could do:
#
# responders FlashResponder, HttpCacheResponder
#
# Or a mix of both methods:
#
# responders :flash, MyCustomResponder
#
def responders(*responders)
self.responder = responders.inject(Class.new(responder)) do |klass, responder|
responder = \
case responder
when Module
responder
when String, Symbol
Responders.const_get("#{responder.to_s.camelize}Responder")
else
raise "responder has to be a string, a symbol or a module"
end
klass.send(:include, responder)
klass
end
end
end
end
ActiveSupport.on_load(:action_controller) do
ActionController::Base.extend Responders::ControllerMethod
end
responders-3.0.1/lib/responders/flash_responder.rb 0000664 0000000 0000000 00000014363 13664214554 0022355 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Responders
# Responder to automatically set flash messages based on I18n API. It checks for
# message based on the current action, but also allows defaults to be set, using
# the following order:
#
# flash.controller_name.action_name.status
# flash.actions.action_name.status
#
# So, if you have a CarsController, create action, it will check for:
#
# flash.cars.create.status
# flash.actions.create.status
#
# The statuses by default are :notice (when the object can be created, updated
# or destroyed with success) and :alert (when the object cannot be created
# or updated).
#
# On I18n, the resource_name given is available as interpolation option,
# this means you can set:
#
# flash:
# actions:
# create:
# notice: "Hooray! %{resource_name} was successfully created!"
#
# But sometimes, flash messages are not that simple. Going back
# to cars example, you might want to say the brand of the car when it's
# updated. Well, that's easy also:
#
# flash:
# cars:
# update:
# notice: "Hooray! You just tuned your %{car_brand}!"
#
# Since :car_name is not available for interpolation by default, you have
# to overwrite `flash_interpolation_options` in your controller.
#
# def flash_interpolation_options
# { :car_brand => @car.brand }
# end
#
# Then you will finally have:
#
# 'Hooray! You just tuned your Aston Martin!'
#
# If your controller is namespaced, for example Admin::CarsController,
# the messages will be checked in the following order:
#
# flash.admin.cars.create.status
# flash.admin.actions.create.status
# flash.cars.create.status
# flash.actions.create.status
#
# You can also have flash messages with embedded HTML. Just create a scope that
# ends with _html as the scopes below:
#
# flash.actions.create.notice_html
# flash.cars.create.notice_html
#
# == Options
#
# FlashResponder also accepts some options through respond_with API.
#
# * :flash - When set to false, no flash message is set.
#
# respond_with(@user, :flash => true)
#
# * :notice - Supply the message to be set if the record has no errors.
# * :alert - Supply the message to be set if the record has errors.
#
# respond_with(@user, :notice => "Hooray! Welcome!", :alert => "Woot! You failed.")
#
# * :flash_now - Sets the flash message using flash.now. Accepts true, :on_failure or :on_sucess.
#
# == Configure status keys
#
# As said previously, FlashResponder by default use :notice and :alert
# keys. You can change that by setting the status_keys:
#
# Responders::FlashResponder.flash_keys = [ :success, :failure ]
#
# However, the options :notice and :alert to respond_with are kept :notice
# and :alert.
#
module FlashResponder
class << self
attr_accessor :flash_keys, :namespace_lookup, :helper
end
self.flash_keys = [ :notice, :alert ]
self.namespace_lookup = false
self.helper = Object.new.extend(
ActionView::Helpers::TranslationHelper,
ActionView::Helpers::TagHelper
)
def initialize(controller, resources, options = {})
super
@flash = options.delete(:flash)
@notice = options.delete(:notice)
@alert = options.delete(:alert)
@flash_now = options.delete(:flash_now) { :on_failure }
end
def to_html
set_flash_message! if set_flash_message?
super
end
def to_js
set_flash_message! if set_flash_message?
defined?(super) ? super : to_format
end
protected
def set_flash_message!
if has_errors?
status = Responders::FlashResponder.flash_keys.last
set_flash(status, @alert)
else
status = Responders::FlashResponder.flash_keys.first
set_flash(status, @notice)
end
return if controller.flash[status].present?
options = mount_i18n_options(status)
message = Responders::FlashResponder.helper.t options[:default].shift, **options
set_flash(status, message)
end
def set_flash(key, value)
return if value.blank?
flash = controller.flash
flash = flash.now if set_flash_now?
flash[key] ||= value
end
def set_flash_now?
@flash_now == true || format == :js ||
(default_action && (has_errors? ? @flash_now == :on_failure : @flash_now == :on_success))
end
def set_flash_message? #:nodoc:
!get? && @flash != false
end
def mount_i18n_options(status) #:nodoc:
options = {
default: flash_defaults_by_namespace(status),
resource_name: resource_name,
downcase_resource_name: resource_name.downcase
}
controller_options = controller_interpolation_options
if controller_options
options.merge!(controller_options)
end
options
end
def controller_interpolation_options
if controller.respond_to?(:flash_interpolation_options, true)
controller.send(:flash_interpolation_options)
elsif controller.respond_to?(:interpolation_options, true)
ActiveSupport::Deprecation.warn("[responders] `#{controller.class}#interpolation_options` is deprecated, please rename it to `flash_interpolation_options`.")
controller.send(:interpolation_options)
end
end
def resource_name
if resource.class.respond_to?(:model_name)
resource.class.model_name.human
else
resource.class.name.underscore.humanize
end
end
def flash_defaults_by_namespace(status) #:nodoc:
defaults = []
slices = controller.controller_path.split("/")
lookup = Responders::FlashResponder.namespace_lookup
begin
controller_scope = :"flash.#{slices.fill(controller.controller_name, -1).join(".")}.#{controller.action_name}.#{status}"
actions_scope = lookup ? slices.fill("actions", -1).join(".") : :actions
actions_scope = :"flash.#{actions_scope}.#{controller.action_name}.#{status}"
defaults << :"#{controller_scope}_html"
defaults << controller_scope
defaults << :"#{actions_scope}_html"
defaults << actions_scope
slices.shift
end while slices.size > 0 && lookup
defaults << ""
end
end
end
responders-3.0.1/lib/responders/http_cache_responder.rb 0000664 0000000 0000000 00000002575 13664214554 0023364 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Responders
# Set HTTP Last-Modified headers based on the given resource. It's used only
# on API behavior (to_format) and is useful for a client to check in the server
# if a resource changed after a specific date or not.
#
# This is not usually not used in html requests because pages contains a lot
# information besides the resource information, as current_user, flash messages,
# widgets... that are better handled with other strategies, as fragment caches and
# the digest of the body.
#
module HttpCacheResponder
def initialize(controller, resources, options = {})
super
@http_cache = options.delete(:http_cache)
end
def to_format
return if do_http_cache? && do_http_cache!
super
end
protected
def do_http_cache!
timestamp = resources.map do |resource|
resource.updated_at.try(:utc) if resource.respond_to?(:updated_at)
end.compact.max
controller.response.last_modified ||= timestamp if timestamp
head :not_modified if fresh = request.fresh?(controller.response)
fresh
end
def do_http_cache?
get? && @http_cache != false && ActionController::Base.perform_caching &&
persisted? && resource.respond_to?(:updated_at)
end
def persisted?
resource.respond_to?(:persisted?) ? resource.persisted? : true
end
end
end
responders-3.0.1/lib/responders/locales/ 0000775 0000000 0000000 00000000000 13664214554 0020265 5 ustar 00root root 0000000 0000000 responders-3.0.1/lib/responders/locales/en.yml 0000664 0000000 0000000 00000000654 13664214554 0021417 0 ustar 00root root 0000000 0000000 en:
flash:
actions:
create:
notice: '%{resource_name} was successfully created.'
# alert: '%{resource_name} could not be created.'
update:
notice: '%{resource_name} was successfully updated.'
# alert: '%{resource_name} could not be updated.'
destroy:
notice: '%{resource_name} was successfully destroyed.'
alert: '%{resource_name} could not be destroyed.'
responders-3.0.1/lib/responders/location_responder.rb 0000664 0000000 0000000 00000000441 13664214554 0023060 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Responders
module LocationResponder
def self.included(_base)
ActiveSupport::Deprecation.warn "Responders::LocationResponder is enabled by default, " \
"no need to include it", caller
end
end
end
responders-3.0.1/lib/responders/version.rb 0000664 0000000 0000000 00000000111 13664214554 0020646 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
module Responders
VERSION = "3.0.1"
end
responders-3.0.1/responders.gemspec 0000664 0000000 0000000 00000001472 13664214554 0017446 0 ustar 00root root 0000000 0000000 # -*- encoding: utf-8 -*-
# frozen_string_literal: true
$:.unshift File.expand_path("../lib", __FILE__)
require "responders/version"
Gem::Specification.new do |s|
s.name = "responders"
s.version = Responders::VERSION.dup
s.platform = Gem::Platform::RUBY
s.summary = "A set of Rails responders to dry up your application"
s.email = "heartcombo@googlegroups.com"
s.homepage = "https://github.com/heartcombo/responders"
s.description = "A set of Rails responders to dry up your application"
s.authors = ["José Valim"]
s.license = "MIT"
s.required_ruby_version = ">= 2.4.0"
s.files = Dir["CHANGELOG.md", "MIT-LICENSE", "README.md", "lib/**/*"]
s.require_paths = ["lib"]
s.add_dependency "railties", ">= 5.0"
s.add_dependency "actionpack", ">= 5.0"
end
responders-3.0.1/test/ 0000775 0000000 0000000 00000000000 13664214554 0014670 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/action_controller/ 0000775 0000000 0000000 00000000000 13664214554 0020410 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/action_controller/respond_with_api_test.rb 0000664 0000000 0000000 00000002247 13664214554 0025337 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "test_helper"
require "support/models"
if defined?(ActionController::API)
class ApiRespondWithController < ActionController::API
respond_to :json
def index
respond_with [
Customer.new("Foo", 1),
Customer.new("Bar", 2),
]
end
def create
respond_with Customer.new("Foo", 1), location: "http://test.host/"
end
end
class RespondWithAPITest < ActionController::TestCase
tests ApiRespondWithController
def test_api_controller_without_view_rendering
@request.accept = "application/json"
get :index
assert_equal 200, @response.status
expected = [{ name: "Foo", id: 1 }, { name: "Bar", id: 2 }]
assert_equal expected.to_json, @response.body
post :create
assert_equal 201, @response.status
expected = { name: "Foo", id: 1 }
assert_equal expected.to_json, @response.body
errors = { name: ["invalid"] }
Customer.any_instance.stubs(:errors).returns(errors)
post :create
assert_equal 422, @response.status
expected = { errors: errors }
assert_equal expected.to_json, @response.body
end
end
end
responders-3.0.1/test/action_controller/respond_with_test.rb 0000664 0000000 0000000 00000051067 13664214554 0024512 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "test_helper"
require "support/models"
class RespondWithController < ApplicationController
class CustomerWithJson < Customer
def to_json(*); super; end
end
respond_to :html, :json, :touch
respond_to :xml, except: :using_resource_with_block
respond_to :js, only: [ :using_resource_with_block, :using_resource, "using_hash_resource" ]
def using_resource
respond_with(resource)
end
def using_hash_resource
respond_with(result: resource)
end
def using_resource_with_block
respond_with(resource) do |format|
format.csv { render body: "CSV", content_type: "text/csv" }
end
end
def using_resource_with_overwrite_block
respond_with(resource) do |format|
format.html { render html: "HTML" }
end
end
def using_resource_with_collection
respond_with([resource, Customer.new("jamis", 9)])
end
def using_resource_with_parent
respond_with(Quiz::Store.new("developer?", 11), Customer.new("david", 13))
end
def using_resource_with_status_and_location
respond_with(resource, location: "http://test.host/", status: :created)
end
def using_resource_with_json
respond_with(CustomerWithJson.new("david", request.delete? ? nil : 13))
end
def using_invalid_resource_with_template
respond_with(resource)
end
def using_options_with_template
@customer = resource
respond_with(@customer, status: 123, location: "http://test.host/")
end
def using_resource_with_responder
responder = proc { |c, r, o| c.render body: "Resource name is #{r.first.name}" }
respond_with(resource, responder: responder)
end
def using_resource_with_action
respond_with(resource, action: :foo) do |format|
format.html { raise ActionView::MissingTemplate.new([], "bar", ["foo"], {}, false) }
end
end
def using_resource_with_rendering_options
rendering_options = { template: "addresses/edit", status: :unprocessable_entity }
respond_with(resource, render: rendering_options) do |format|
format.html { raise ActionView::MissingTemplate.new([], "bar", ["foo"], {}, false) }
end
end
def using_responder_with_respond
responder = Class.new(ActionController::Responder) do
def respond; @controller.render body: "respond #{format}"; end
end
respond_with(resource, responder: responder)
end
def respond_with_additional_params
@params = RespondWithController.params
respond_with({ result: resource }, @params)
end
protected
def self.params
{
foo: "bar"
}
end
def resource
Customer.new("david", request.delete? ? nil : 13)
end
end
class InheritedRespondWithController < RespondWithController
clear_respond_to
respond_to :xml, :json
def index
respond_with(resource) do |format|
format.json { render body: "JSON" }
end
end
end
class CsvRespondWithController < ApplicationController
respond_to :csv
class RespondWithCsv
def to_csv
"c,s,v"
end
end
def index
respond_with(RespondWithCsv.new)
end
end
class EmptyRespondWithController < ApplicationController
clear_respond_to
def index
respond_with(Customer.new("david", 13))
end
end
class RespondWithControllerTest < ActionController::TestCase
def setup
super
@request.host = "www.example.com"
Mime::Type.register_alias("text/html", :iphone)
Mime::Type.register_alias("text/html", :touch)
Mime::Type.register("text/x-mobile", :mobile)
end
def teardown
super
Mime::Type.unregister(:iphone)
Mime::Type.unregister(:touch)
Mime::Type.unregister(:mobile)
end
def test_respond_with_shouldnt_modify_original_hash
get :respond_with_additional_params
assert_equal RespondWithController.params, assigns(:params)
end
def test_using_resource
@request.accept = "application/xml"
get :using_resource
assert_equal "application/xml", @response.media_type
assert_equal "david", @response.body
@request.accept = "application/json"
get :using_resource
assert_equal "application/json", @response.media_type
assert_equal "{\"name\":\"david\",\"id\":13}", @response.body
end
def test_using_resource_with_js_simply_tries_to_render_the_template
@request.accept = "text/javascript"
get :using_resource
assert_equal "text/javascript", @response.media_type
assert_equal "alert(\"Hi\");", @response.body
end
def test_using_hash_resource_with_js_raises_an_error_if_template_cant_be_found
@request.accept = "text/javascript"
assert_raise ActionView::MissingTemplate do
get :using_hash_resource
end
end
def test_using_hash_resource
@request.accept = "application/xml"
get :using_hash_resource
assert_equal "application/xml", @response.media_type
assert_equal "\n\n david\n\n", @response.body
@request.accept = "application/json"
get :using_hash_resource
assert_equal "application/json", @response.media_type
assert @response.body.include?("result")
assert @response.body.include?('"name":"david"')
assert @response.body.include?('"id":13')
end
def test_using_hash_resource_with_post
@request.accept = "application/json"
assert_raise ArgumentError, "Nil location provided. Can't build URI." do
post :using_hash_resource
end
end
def test_using_resource_with_block
@request.accept = "*/*"
get :using_resource_with_block
assert_equal "text/html", @response.media_type
assert_equal "Hello world!", @response.body
@request.accept = "text/csv"
get :using_resource_with_block
assert_equal "text/csv", @response.media_type
assert_equal "CSV", @response.body
@request.accept = "application/xml"
get :using_resource
assert_equal "application/xml", @response.media_type
assert_equal "david", @response.body
end
def test_using_resource_with_overwrite_block
get :using_resource_with_overwrite_block
assert_equal "text/html", @response.media_type
assert_equal "HTML", @response.body
end
def test_not_acceptable
@request.accept = "application/xml"
assert_raises(ActionController::UnknownFormat) do
get :using_resource_with_block
end
@request.accept = "text/javascript"
assert_raises(ActionController::UnknownFormat) do
get :using_resource_with_overwrite_block
end
end
def test_using_resource_for_post_with_html_redirects_on_success
with_test_route_set do
post :using_resource
assert_equal "text/html", @response.media_type
assert_equal 302, @response.status
assert_equal "http://www.example.com/customers/13", @response.location
assert @response.redirect?
end
end
def test_using_resource_for_post_with_html_rerender_on_failure
with_test_route_set do
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
post :using_resource
assert_equal "text/html", @response.media_type
assert_equal 200, @response.status
assert_equal "New world!\n", @response.body
assert_nil @response.location
end
end
def test_using_resource_for_post_with_xml_yields_created_on_success
with_test_route_set do
@request.accept = "application/xml"
post :using_resource
assert_equal "application/xml", @response.media_type
assert_equal 201, @response.status
assert_equal "david", @response.body
assert_equal "http://www.example.com/customers/13", @response.location
end
end
def test_using_resource_for_post_with_xml_yields_unprocessable_entity_on_failure
with_test_route_set do
@request.accept = "application/xml"
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
post :using_resource
assert_equal "application/xml", @response.media_type
assert_equal 422, @response.status
assert_equal errors.to_xml, @response.body
assert_nil @response.location
end
end
def test_using_resource_for_post_with_json_yields_unprocessable_entity_on_failure
with_test_route_set do
@request.accept = "application/json"
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
post :using_resource
assert_equal "application/json", @response.media_type
assert_equal 422, @response.status
errors = { errors: errors }
assert_equal errors.to_json, @response.body
assert_nil @response.location
end
end
def test_using_resource_for_patch_with_html_redirects_on_success
with_test_route_set do
patch :using_resource
assert_equal "text/html", @response.media_type
assert_equal 302, @response.status
assert_equal "http://www.example.com/customers/13", @response.location
assert @response.redirect?
end
end
def test_using_resource_for_patch_with_html_rerender_on_failure
with_test_route_set do
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
patch :using_resource
assert_equal "text/html", @response.media_type
assert_equal 200, @response.status
assert_equal "Edit world!\n", @response.body
assert_nil @response.location
end
end
def test_using_resource_for_patch_with_html_rerender_on_failure_even_on_method_override
with_test_route_set do
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
@request.env["rack.methodoverride.original_method"] = "POST"
patch :using_resource
assert_equal "text/html", @response.media_type
assert_equal 200, @response.status
assert_equal "Edit world!\n", @response.body
assert_nil @response.location
end
end
def test_using_resource_for_put_with_html_redirects_on_success
with_test_route_set do
put :using_resource
assert_equal "text/html", @response.media_type
assert_equal 302, @response.status
assert_equal "http://www.example.com/customers/13", @response.location
assert @response.redirect?
end
end
def test_using_resource_for_put_with_html_rerender_on_failure
with_test_route_set do
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
put :using_resource
assert_equal "text/html", @response.media_type
assert_equal 200, @response.status
assert_equal "Edit world!\n", @response.body
assert_nil @response.location
end
end
def test_using_resource_for_put_with_html_rerender_on_failure_even_on_method_override
with_test_route_set do
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
@request.env["rack.methodoverride.original_method"] = "POST"
put :using_resource
assert_equal "text/html", @response.media_type
assert_equal 200, @response.status
assert_equal "Edit world!\n", @response.body
assert_nil @response.location
end
end
def test_using_resource_for_put_with_xml_yields_no_content_on_success
@request.accept = "application/xml"
put :using_resource
assert_equal 204, @response.status
assert_equal "", @response.body
end
def test_using_resource_for_put_with_json_yields_no_content_on_success
@request.accept = "application/json"
put :using_resource_with_json
assert_equal 204, @response.status
assert_equal "", @response.body
end
def test_using_resource_for_put_with_xml_yields_unprocessable_entity_on_failure
@request.accept = "application/xml"
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
put :using_resource
assert_equal "application/xml", @response.media_type
assert_equal 422, @response.status
assert_equal errors.to_xml, @response.body
assert_nil @response.location
end
def test_using_resource_for_put_with_json_yields_unprocessable_entity_on_failure
@request.accept = "application/json"
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
put :using_resource
assert_equal "application/json", @response.media_type
assert_equal 422, @response.status
errors = { errors: errors }
assert_equal errors.to_json, @response.body
assert_nil @response.location
end
def test_using_resource_for_delete_with_html_redirects_on_success
with_test_route_set do
Customer.any_instance.stubs(:destroyed?).returns(true)
delete :using_resource
assert_equal "text/html", @response.media_type
assert_equal 302, @response.status
assert_equal "http://www.example.com/customers", @response.location
end
end
def test_using_resource_for_delete_with_xml_yields_no_content_on_success
Customer.any_instance.stubs(:destroyed?).returns(true)
@request.accept = "application/xml"
delete :using_resource
assert_equal 204, @response.status
assert_equal "", @response.body
end
def test_using_resource_for_delete_with_json_yields_no_content_on_success
Customer.any_instance.stubs(:destroyed?).returns(true)
@request.accept = "application/json"
delete :using_resource_with_json
assert_equal 204, @response.status
assert_equal "", @response.body
end
def test_using_resource_for_delete_with_html_redirects_on_failure
with_test_route_set do
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
Customer.any_instance.stubs(:destroyed?).returns(false)
delete :using_resource
assert_equal "text/html", @response.media_type
assert_equal 302, @response.status
assert_equal "http://www.example.com/customers", @response.location
end
end
def test_using_resource_with_parent_for_get
@request.accept = "application/xml"
get :using_resource_with_parent
assert_equal "application/xml", @response.media_type
assert_equal 200, @response.status
assert_equal "david", @response.body
end
def test_using_resource_with_parent_for_post
with_test_route_set do
@request.accept = "application/xml"
post :using_resource_with_parent
assert_equal "application/xml", @response.media_type
assert_equal 201, @response.status
assert_equal "david", @response.body
assert_equal "http://www.example.com/quiz_stores/11/customers/13", @response.location
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
post :using_resource
assert_equal "application/xml", @response.media_type
assert_equal 422, @response.status
assert_equal errors.to_xml, @response.body
assert_nil @response.location
end
end
def test_using_resource_with_collection
@request.accept = "application/xml"
get :using_resource_with_collection
assert_equal "application/xml", @response.media_type
assert_equal 200, @response.status
assert_match(/david<\/name>/, @response.body)
assert_match(/jamis<\/name>/, @response.body)
end
def test_using_resource_with_action
@controller.instance_eval do
def render(params = {})
self.response_body = "#{params[:action]} - #{formats}"
end
end
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
post :using_resource_with_action
assert_equal "foo - #{[:html]}", @controller.response.body
end
def test_using_resource_with_rendering_options
Customer.any_instance.stubs(:errors).returns(name: :invalid)
post :using_resource_with_rendering_options
assert_response :unprocessable_entity
assert_equal "edit.html.erb", @controller.response.body
end
def test_respond_as_responder_entry_point
@request.accept = "text/html"
get :using_responder_with_respond
assert_equal "respond html", @response.body
@request.accept = "application/xml"
get :using_responder_with_respond
assert_equal "respond xml", @response.body
end
def test_clear_respond_to
@controller = InheritedRespondWithController.new
@request.accept = "text/html"
assert_raises(ActionController::UnknownFormat) do
get :index
end
end
def test_first_in_respond_to_has_higher_priority
@controller = InheritedRespondWithController.new
@request.accept = "*/*"
get :index
assert_equal "application/xml", @response.media_type
assert_equal "david", @response.body
end
def test_block_inside_respond_with_is_rendered
@controller = InheritedRespondWithController.new
@request.accept = "application/json"
get :index
assert_equal "JSON", @response.body
end
def test_no_double_render_is_raised
@request.accept = "text/html"
assert_raise ActionView::MissingTemplate do
get :using_resource
end
end
def test_using_resource_with_status_and_location
@request.accept = "text/html"
post :using_resource_with_status_and_location
assert @response.redirect?
assert_equal "http://test.host/", @response.location
@request.accept = "application/xml"
get :using_resource_with_status_and_location
assert_equal 201, @response.status
end
def test_using_resource_with_status_and_location_with_invalid_resource
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
@request.accept = "text/xml"
post :using_resource_with_status_and_location
assert_equal errors.to_xml, @response.body
assert_equal 422, @response.status
assert_nil @response.location
put :using_resource_with_status_and_location
assert_equal errors.to_xml, @response.body
assert_equal 422, @response.status
assert_nil @response.location
end
def test_using_invalid_resource_with_template
errors = { name: :invalid }
Customer.any_instance.stubs(:errors).returns(errors)
@request.accept = "text/xml"
post :using_invalid_resource_with_template
assert_equal errors.to_xml, @response.body
assert_equal 422, @response.status
assert_nil @response.location
put :using_invalid_resource_with_template
assert_equal errors.to_xml, @response.body
assert_equal 422, @response.status
assert_nil @response.location
end
def test_using_options_with_template
@request.accept = "text/xml"
post :using_options_with_template
assert_equal "david", @response.body
assert_equal 123, @response.status
assert_equal "http://test.host/", @response.location
put :using_options_with_template
assert_equal "david", @response.body
assert_equal 123, @response.status
assert_equal "http://test.host/", @response.location
end
def test_using_resource_with_responder
get :using_resource_with_responder
assert_equal "Resource name is david", @response.body
end
def test_using_resource_with_set_responder
RespondWithController.responder = proc { |c, r, o| c.render body: "Resource name is #{r.first.name}" }
get :using_resource
assert_equal "Resource name is david", @response.body
ensure
RespondWithController.responder = ActionController::Responder
end
def test_raises_missing_renderer_if_an_api_behavior_with_no_renderer
@controller = CsvRespondWithController.new
assert_raise ActionController::MissingRenderer do
get :index, format: "csv"
end
end
def test_error_is_raised_if_no_respond_to_is_declared_and_respond_with_is_called
@controller = EmptyRespondWithController.new
@request.accept = "*/*"
assert_raise RuntimeError do
get :index
end
end
private
def with_test_route_set
with_routing do |set|
set.draw do
resources :customers
resources :quiz_stores do
resources :customers
end
ActiveSupport::Deprecation.silence do
get ":controller/:action"
end
end
yield
end
end
end
class LocationsController < ApplicationController
respond_to :html
# TODO: Remove this when we drop support for Rails 4.2.
if respond_to?(:before_action)
before_action :set_resource
else
before_filter :set_resource
end
def create
respond_with @resource, location: -> { "given_location" }
end
def update
respond_with @resource, location: "given_location"
end
def set_resource
@resource = Address.new
@resource.errors[:fail] << "FAIL" if params[:fail]
end
end
class LocationResponderTest < ActionController::TestCase
tests LocationsController
def test_redirects_to_block_location_on_success
post :create
assert_redirected_to "given_location"
end
def test_renders_page_on_fail
post :create, params: { fail: true }
assert @response.body.include?("new.html.erb")
end
def test_redirects_to_plain_string
post :update
assert_redirected_to "given_location"
end
end
responders-3.0.1/test/action_controller/verify_requested_format_test.rb 0000664 0000000 0000000 00000001702 13664214554 0026731 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "test_helper"
class ThingsController < ApplicationController
clear_respond_to
respond_to :js
respond_to :html, only: [:show, :new]
before_action :verify_requested_format!
attr_reader :called
def action
@called = true
render inline: action_name
end
alias :index :action
alias :show :action
alias :new :action
end
class VerifyRequestedFormatTest < ActionController::TestCase
tests ThingsController
def test_strict_mode_shouldnt_call_action
assert_raises(ActionController::UnknownFormat) do
get :index
end
refute @controller.called, "action should not be executed."
end
def test_strict_mode_calls_action_with_right_format
get :index, format: :js
assert @controller.called, "action should be executed."
end
def test_strict_mode_respects_only_option
get :show, format: :html
assert @controller.called, "action should be executed."
end
end
responders-3.0.1/test/locales/ 0000775 0000000 0000000 00000000000 13664214554 0016312 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/locales/en.yml 0000664 0000000 0000000 00000001635 13664214554 0017444 0 ustar 00root root 0000000 0000000 en:
flash:
actions:
create:
success: "Resource created with success"
failure: "Resource could not be created"
with_block:
success: "Resource with block created with success"
with_html:
failure_html: "OH NOES! You did it wrong!"
xss_html: "Yay! %{xss}"
addresses:
update:
success: "Nice! %{resource_name} was updated with success!"
failure: "Oh no! We could not update your address!"
destroy:
success: "Successfully deleted the address at %{reference}"
notice: "Successfully deleted the chosen address at %{reference}"
with_html:
success_html: "Yay! You did it!"
admin:
actions:
create:
notice: "Admin created address with success"
addresses:
update:
notice: "Admin updated address with success"
responders-3.0.1/test/responders/ 0000775 0000000 0000000 00000000000 13664214554 0017054 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/responders/collection_responder_test.rb 0000664 0000000 0000000 00000003774 13664214554 0024667 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "test_helper"
class CollectionResponder < ActionController::Responder
include Responders::CollectionResponder
end
class CollectionController < ApplicationController
self.responder = CollectionResponder
def single
respond_with Address.new
end
def namespaced
respond_with :admin, Address.new
end
def nested
respond_with User.new, Address.new
end
def only_symbols
respond_with :admin, :addresses
end
def with_location
respond_with Address.new, location: "given_location"
end
def isolated_namespace
respond_with MyEngine::Business
end
def uncountable
respond_with News.new
end
end
class CollectionResponderTest < ActionController::TestCase
tests CollectionController
def test_collection_with_single_resource
@controller.expects(:addresses_url).returns("addresses_url")
post :single
assert_redirected_to "addresses_url"
end
def test_collection_with_namespaced_resource
@controller.expects(:admin_addresses_url).returns("admin_addresses_url")
put :namespaced
assert_redirected_to "admin_addresses_url"
end
def test_collection_with_nested_resource
@controller.expects(:user_addresses_url).returns("user_addresses_url")
delete :nested
assert_redirected_to "user_addresses_url"
end
def test_collection_respects_location_option
delete :with_location
assert_redirected_to "given_location"
end
def test_collection_respects_only_symbols
@controller.expects(:admin_addresses_url).returns("admin_addresses_url")
post :only_symbols
assert_redirected_to "admin_addresses_url"
end
def test_collection_respects_isolated_namespace
@controller.expects(:businesses_url).returns("businesses_url")
post :isolated_namespace
assert_redirected_to "businesses_url"
end
def test_collection_respects_uncountable_resource
@controller.expects(:news_index_url).returns("news_index_url")
post :uncountable
assert_redirected_to "news_index_url"
end
end
responders-3.0.1/test/responders/controller_method_test.rb 0000664 0000000 0000000 00000002507 13664214554 0024167 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "test_helper"
ActionController::Base.extend Responders::ControllerMethod
module FooResponder
def to_html
@resource << "foo"
super
end
end
module BarResponder
def to_html
@resource << "bar"
super
end
end
module PeopleResponder
def to_html
@resource << "baz"
super
end
end
class PeopleController < ApplicationController
responders :foo, BarResponder
def index
@array = []
respond_with(@array) do |format|
format.html { render body: "Success!" }
end
end
end
class SpecialPeopleController < PeopleController
responders :people
end
class ControllerMethodTest < ActionController::TestCase
tests PeopleController
def setup
@controller.stubs(:polymorphic_url).returns("/")
end
def test_foo_responder_gets_added
get :index
assert assigns(:array).include? "foo"
end
def test_bar_responder_gets_added
get :index
assert assigns(:array).include? "bar"
end
end
class ControllerMethodInheritanceTest < ActionController::TestCase
tests SpecialPeopleController
def setup
@controller.stubs(:polymorphic_url).returns("/")
end
def test_responder_is_inherited
get :index
assert assigns(:array).include? "foo"
assert assigns(:array).include? "bar"
assert assigns(:array).include? "baz"
end
end
responders-3.0.1/test/responders/flash_responder_test.rb 0000664 0000000 0000000 00000017673 13664214554 0023634 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "test_helper"
class FlashResponder < ActionController::Responder
include Responders::FlashResponder
end
class AddressesController < ApplicationController
if respond_to?(:before_action)
before_action :set_resource
else
before_filter :set_resource
end
self.responder = FlashResponder
respond_to :js, only: :create
FLASH_PARAM_VALUES = {
"true" => true,
"false" => false
}
FLASH_NOW_PARAM_VALUES = {
"true" => true,
"false" => false,
"on_success" => :on_success,
"on_failure" => :on_failure
}
def action
set_flash = FLASH_PARAM_VALUES[params[:flash].to_s]
set_flash_now = FLASH_NOW_PARAM_VALUES[params[:flash_now].to_s]
flash[:success] = "Flash is set" if params[:set_flash]
respond_with(@resource, flash: set_flash, flash_now: set_flash_now)
end
alias :new :action
alias :create :action
alias :update :action
alias :destroy :action
def with_block
respond_with(@resource) do |format|
format.html { render html: "Success!" }
end
end
def another
respond_with(@resource, notice: "Yes, notice this!", alert: "Warning, warning!")
end
def with_html
respond_with(@resource)
end
def flexible
options = params[:responder_options] || {}
flash_now, alert = options.values_at(:flash_now, :alert)
respond_with(@resource, flash_now: flash_now, alert: alert)
end
protected
def flash_interpolation_options
{ reference: "Ocean Avenue", xss: "" }
end
def set_resource
@resource = Address.new
@resource.errors[:fail] << "FAIL" if params[:fail]
end
end
class PolymorphicAddesssController < AddressesController
def create
respond_with(User.new, Address.new)
end
end
module Admin
class AddressesController < ::AddressesController
end
end
class FlashResponderTest < ActionController::TestCase
tests AddressesController
def setup
Responders::FlashResponder.flash_keys = [ :success, :failure ]
@controller.stubs(:polymorphic_url).returns("/")
end
def test_sets_success_flash_message_on_non_get_requests
post :create
assert_equal "Resource created with success", flash[:success]
end
def test_sets_failure_flash_message_on_not_get_requests
post :create, params: { fail: true }
assert_equal "Resource could not be created", flash[:failure]
end
def test_does_not_set_flash_message_on_get_requests
get :new
assert flash.empty?
end
def test_sets_flash_message_for_the_current_controller
put :update, params: { fail: true }
assert_equal "Oh no! We could not update your address!", flash[:failure]
end
def test_sets_flash_message_with_resource_name
put :update
assert_equal "Nice! Address was updated with success!", flash[:success]
end
def test_sets_flash_message_with_interpolation_options
delete :destroy
assert_equal "Successfully deleted the address at Ocean Avenue", flash[:success]
end
def test_does_not_set_flash_if_flash_false_is_given
post :create, params: { flash: false }
assert flash.empty?
end
def test_does_not_overwrite_the_flash_if_already_set
post :create, params: { set_flash: true }
assert_equal "Flash is set", flash[:success]
end
def test_sets_flash_message_even_if_block_is_given
post :with_block
assert_equal "Resource with block created with success", flash[:success]
end
def test_sets_now_flash_message_on_javascript_requests
post :create, format: :js
assert_equal "Resource created with success", flash[:success]
assert_flash_now :success
end
def test_sets_flash_message_can_be_set_to_now
post :create, params: { flash_now: true }
assert_equal "Resource created with success", @controller.flash.now[:success]
assert_flash_now :success
end
def test_sets_flash_message_can_be_set_to_now_only_on_success
post :create, params: { flash_now: :on_success }
assert_equal "Resource created with success", @controller.flash.now[:success]
end
def test_sets_flash_message_can_be_set_to_now_only_on_failure
post :create, params: { flash_now: :on_failure }
assert_not_flash_now :success
end
def test_sets_message_based_on_notice_key_with_custom_keys
post :another
assert_equal "Yes, notice this!", flash[:success]
end
def test_sets_message_based_on_alert_key_with_custom_keys
post :another, params: { fail: true }
assert_equal "Warning, warning!", flash[:failure]
end
def test_sets_message_based_on_notice_key
Responders::FlashResponder.flash_keys = [ :notice, :alert ]
post :another
assert_equal "Yes, notice this!", flash[:notice]
end
def test_sets_message_based_on_alert_key
Responders::FlashResponder.flash_keys = [ :notice, :alert ]
post :another, params: { fail: true }
assert_equal "Warning, warning!", flash[:alert]
end
def test_sets_html_using_controller_scope
post :with_html
assert_equal "Yay! You did it!", flash[:success]
end
def test_sets_html_using_actions_scope
post :with_html, params: { fail: true }
assert_equal "OH NOES! You did it wrong!", flash[:failure]
end
def test_escapes_html_interpolations
Responders::FlashResponder.flash_keys = [ :xss, :xss ]
post :with_html
assert_equal "Yay! <script>alert(1)</script>", flash[:xss]
end
def test_sets_flash_now_on_failure_by_default
post :another, params: { fail: true }
assert_flash_now :failure
end
def test_does_not_set_flash_message_to_now_with_errors_and_redirect
delete :with_html, params: { fail: true }
assert_not_flash_now :failure
assert_equal "OH NOES! You did it wrong!", flash[:failure]
end
def test_never_set_flash_now
post :flexible, params: { fail: true, responder_options: { flash_now: false, alert: "Warning" } }
assert_not_flash_now :failure
end
# If we have flash.now, it's always marked as used. Rails 4.1 has string keys,
# whereas 3.2 and 4.0 has symbols, so we need to test both.
def assert_flash_now(k)
assert flash.used_keys.include?(k.to_sym) || flash.used_keys.include?(k.to_s),
"Expected #{k} to be in flash.now, but it's not."
end
def assert_not_flash_now(k)
assert flash[k], "Expected #{k} to be set"
assert !flash.used_keys.include?(k.to_sym),
"Expected #{k} to not be in flash.now, but it is."
end
end
class NamespacedFlashResponderTest < ActionController::TestCase
tests Admin::AddressesController
def setup
Responders::FlashResponder.flash_keys = [ :notice, :alert ]
@controller.stubs(:polymorphic_url).returns("/")
end
def test_sets_the_flash_message_based_on_the_current_controller
put :update
assert_equal "Admin updated address with success", flash[:notice]
end
def test_sets_the_flash_message_based_on_namespace_actions
Responders::FlashResponder.namespace_lookup = true
post :create
assert_equal "Admin created address with success", flash[:notice]
ensure
Responders::FlashResponder.namespace_lookup = false
end
def test_fallbacks_to_non_namespaced_controller_flash_message
Responders::FlashResponder.namespace_lookup = true
delete :destroy
assert_equal "Successfully deleted the chosen address at Ocean Avenue", flash[:notice]
ensure
Responders::FlashResponder.namespace_lookup = false
end
def test_does_not_fallbacks_to_namespaced_actions_if_disabled
post :create
assert_equal "Address was successfully created.", flash[:notice]
end
def test_does_not_fallbacks_to_non_namespaced_controller_flash_message_if_disabled
post :new
assert_nil flash[:notice]
end
end
class PolymorhicFlashResponderTest < ActionController::TestCase
tests PolymorphicAddesssController
def setup
Responders::FlashResponder.flash_keys = [ :notice, :alert ]
@controller.stubs(:polymorphic_url).returns("/")
end
def test_polymorhic_respond_with
post :create
assert_equal "Address was successfully created.", flash[:notice]
end
end
responders-3.0.1/test/responders/http_cache_responder_test.rb 0000664 0000000 0000000 00000006712 13664214554 0024631 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "test_helper"
class HttpCacheResponder < ActionController::Responder
include Responders::HttpCacheResponder
end
class HttpCacheController < ApplicationController
self.responder = HttpCacheResponder
HTTP_CACHE_PARAM_VALUES = { "false" => false }
def single
http_cache = HTTP_CACHE_PARAM_VALUES[params[:http_cache].to_s]
response.last_modified = Time.utc(2008) if params[:last_modified]
respond_with(Address.new(Time.utc(2009)), http_cache: http_cache)
end
def nested
respond_with Address.new(Time.utc(2009)), Address.new(Time.utc(2008))
end
def collection
respond_with [Address.new(Time.utc(2009)), Address.new(Time.utc(2008))]
end
def not_persisted
model = Address.new(Time.utc(2009))
model.persisted = false
respond_with(model)
end
def empty
respond_with []
end
end
class HttpCacheResponderTest < ActionController::TestCase
tests HttpCacheController
def setup
@request.accept = "application/xml"
@controller.stubs(:polymorphic_url).returns("/")
end
def test_last_modified_at_is_set_with_single_resource_on_get
get :single
assert_equal Time.utc(2009).httpdate, @response.headers["Last-Modified"]
assert_equal "", @response.body
assert_equal 200, @response.status
end
def test_returns_not_modified_if_return_is_cache_is_still_valid
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2009, 6).httpdate
get :single
assert_equal 304, @response.status
assert_includes " ", @response.body
end
def test_refreshes_last_modified_if_cache_is_expired
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2008, 6).httpdate
get :single
assert_equal Time.utc(2009).httpdate, @response.headers["Last-Modified"]
assert_equal "", @response.body
assert_equal 200, @response.status
end
def test_does_not_set_cache_unless_get_requests
post :single
assert_nil @response.headers["Last-Modified"]
assert_equal 201, @response.status
end
def test_does_not_use_cache_unless_get_requests
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2009, 6).httpdate
post :single
assert_equal 201, @response.status
end
def test_does_not_set_cache_if_http_cache_is_false
get :single, params: { http_cache: false }
assert_nil @response.headers["Last-Modified"]
assert_equal 200, @response.status
end
def test_does_not_use_cache_if_http_cache_is_false
@request.env["HTTP_IF_MODIFIED_SINCE"] = Time.utc(2009, 6).httpdate
get :single, params: { http_cache: false }
assert_equal 200, @response.status
end
def test_does_not_set_cache_for_collection
get :collection
assert_nil @response.headers["Last-Modified"]
assert_equal 200, @response.status
end
def test_works_for_nested_resources
get :nested
assert_equal Time.utc(2009).httpdate, @response.headers["Last-Modified"]
assert_match(/xml/, @response.body)
assert_equal 200, @response.status
end
def test_work_with_an_empty_array
get :empty
assert_nil @response.headers["Last-Modified"]
assert_match(/xml/, @response.body)
assert_equal 200, @response.status
end
def test_it_does_not_set_body_etag_for_single_resource
get :single
assert_nil @response.headers["ETag"]
end
def test_does_not_set_cache_for_new_records
get :not_persisted
assert_nil @response.headers["Last-Modified"]
assert_equal "", @response.body
assert_equal 200, @response.status
end
end
responders-3.0.1/test/support/ 0000775 0000000 0000000 00000000000 13664214554 0016404 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/support/models.rb 0000664 0000000 0000000 00000001415 13664214554 0020215 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
class Customer < Struct.new(:name, :id)
extend ActiveModel::Naming
include ActiveModel::Conversion
def to_xml(options = {})
if options[:builder]
options[:builder].name name
else
"#{name}"
end
end
def to_js(options = {})
"name: #{name.inspect}"
end
alias :to_text :to_js
def errors
[]
end
def persisted?
id.present?
end
end
class ValidatedCustomer < Customer
def errors
if name =~ /Sikachu/i
[]
else
[{ name: "is invalid" }]
end
end
end
module Quiz
class Question < Struct.new(:name, :id)
extend ActiveModel::Naming
include ActiveModel::Conversion
def persisted?
id.present?
end
end
class Store < Question
end
end
responders-3.0.1/test/test_helper.rb 0000664 0000000 0000000 00000003454 13664214554 0017541 0 ustar 00root root 0000000 0000000 # frozen_string_literal: true
require "bundler/setup"
require "minitest/autorun"
require "mocha/setup"
# Configure Rails
ENV["RAILS_ENV"] = "test"
require "active_support"
require "active_model"
require "rails/engine"
require "rails/railtie"
$:.unshift File.expand_path("../../lib", __FILE__)
require "responders"
I18n.enforce_available_locales = true
I18n.load_path << File.expand_path("../locales/en.yml", __FILE__)
I18n.reload!
Responders::Routes = ActionDispatch::Routing::RouteSet.new
Responders::Routes.draw do
resources :news
ActiveSupport::Deprecation.silence do
get "/admin/:action", controller: "admin/addresses"
get "/:controller(/:action(/:id))"
end
end
class ApplicationController < ActionController::Base
include Responders::Routes.url_helpers
self.view_paths = File.join(File.dirname(__FILE__), "views")
respond_to :html, :xml
end
class ActiveSupport::TestCase
self.test_order = :random
setup do
@routes = Responders::Routes
end
end
require "rails-controller-testing"
ActionController::TestCase.include Rails::Controller::Testing::TestProcess
ActionController::TestCase.include Rails::Controller::Testing::TemplateAssertions
module ActionDispatch
class Flash
class FlashHash
def used_keys
@discard
end
end
end
end
class Model
include ActiveModel::Conversion
include ActiveModel::Validations
attr_accessor :persisted, :updated_at
alias :persisted? :persisted
def persisted?
@persisted
end
def to_xml(*args)
""
end
def initialize(updated_at = nil)
@persisted = true
self.updated_at = updated_at
end
end
class Address < Model
end
class User < Model
end
class News < Model
end
module MyEngine
class Business < Rails::Engine
isolate_namespace MyEngine
extend ActiveModel::Naming
end
end
responders-3.0.1/test/views/ 0000775 0000000 0000000 00000000000 13664214554 0016025 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/views/addresses/ 0000775 0000000 0000000 00000000000 13664214554 0020002 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/views/addresses/create.js.erb 0000664 0000000 0000000 00000000015 13664214554 0022346 0 ustar 00root root 0000000 0000000 create.js.erb responders-3.0.1/test/views/addresses/edit.html.erb 0000664 0000000 0000000 00000000015 13664214554 0022360 0 ustar 00root root 0000000 0000000 edit.html.erb responders-3.0.1/test/views/addresses/new.html.erb 0000664 0000000 0000000 00000000014 13664214554 0022223 0 ustar 00root root 0000000 0000000 new.html.erb responders-3.0.1/test/views/locations/ 0000775 0000000 0000000 00000000000 13664214554 0020020 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/views/locations/new.html.erb 0000664 0000000 0000000 00000000015 13664214554 0022242 0 ustar 00root root 0000000 0000000 new.html.erb
responders-3.0.1/test/views/respond_with/ 0000775 0000000 0000000 00000000000 13664214554 0020532 5 ustar 00root root 0000000 0000000 responders-3.0.1/test/views/respond_with/edit.html.erb 0000664 0000000 0000000 00000000014 13664214554 0023107 0 ustar 00root root 0000000 0000000 Edit world!
responders-3.0.1/test/views/respond_with/new.html.erb 0000664 0000000 0000000 00000000013 13664214554 0022752 0 ustar 00root root 0000000 0000000 New world!
responders-3.0.1/test/views/respond_with/respond_with_additional_params.html.erb 0000664 0000000 0000000 00000000000 13664214554 0030415 0 ustar 00root root 0000000 0000000 responders-3.0.1/test/views/respond_with/using_invalid_resource_with_template.xml.erb 0000664 0000000 0000000 00000000054 13664214554 0031512 0 ustar 00root root 0000000 0000000 I should not be displayed