Merge branch 'master' of github.com:lifo/docrails
This commit is contained in:
commit
0c55335074
@ -1,11 +1,12 @@
|
||||
script: 'ci/travis.rb'
|
||||
before_install:
|
||||
- travis_retry gem install bundler
|
||||
- "rvm current | grep 'jruby' && export AR_JDBC=true || echo"
|
||||
rvm:
|
||||
- 1.9.3
|
||||
- 2.0.0
|
||||
- rbx-2.2.1
|
||||
- jruby-19mode
|
||||
- rbx-19mode
|
||||
env:
|
||||
- "GEM=railties"
|
||||
- "GEM=ap,am,amo,as,av"
|
||||
@ -15,8 +16,8 @@ env:
|
||||
- "GEM=ar:postgresql"
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rvm: rbx-2.2.1
|
||||
- rvm: jruby-19mode
|
||||
- rvm: rbx-19mode
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
|
25
Gemfile
25
Gemfile
@ -8,10 +8,11 @@ gemspec
|
||||
gem 'mocha', '~> 0.14', require: false
|
||||
|
||||
gem 'rack-cache', '~> 1.2'
|
||||
gem 'bcrypt-ruby', '~> 3.1.0'
|
||||
gem 'bcrypt-ruby', '~> 3.1.2'
|
||||
gem 'jquery-rails', '~> 2.2.0'
|
||||
gem 'turbolinks'
|
||||
gem 'coffee-rails', '~> 4.0.0'
|
||||
gem 'arel', github: 'rails/arel'
|
||||
|
||||
# This needs to be with require false to avoid
|
||||
# it being automatically loaded by sprockets
|
||||
@ -29,7 +30,7 @@ gem 'dalli', '>= 2.2.1'
|
||||
|
||||
# Add your own local bundler stuff
|
||||
local_gemfile = File.dirname(__FILE__) + "/.Gemfile"
|
||||
instance_eval File.read local_gemfile if File.exists? local_gemfile
|
||||
instance_eval File.read local_gemfile if File.exist? local_gemfile
|
||||
|
||||
group :test do
|
||||
platforms :mri_19 do
|
||||
@ -61,15 +62,27 @@ platforms :ruby do
|
||||
end
|
||||
|
||||
platforms :jruby do
|
||||
git 'git://github.com/jruby/activerecord-jdbc-adapter.git' do
|
||||
gem 'activerecord-jdbcsqlite3-adapter'
|
||||
gem 'json'
|
||||
if ENV['AR_JDBC']
|
||||
gem 'activerecord-jdbcsqlite3-adapter', github: 'jruby/activerecord-jdbc-adapter', branch: 'master'
|
||||
group :db do
|
||||
gem 'activerecord-jdbcmysql-adapter'
|
||||
gem 'activerecord-jdbcpostgresql-adapter'
|
||||
gem 'activerecord-jdbcmysql-adapter', github: 'jruby/activerecord-jdbc-adapter', branch: 'master'
|
||||
gem 'activerecord-jdbcpostgresql-adapter', github: 'jruby/activerecord-jdbc-adapter', branch: 'master'
|
||||
end
|
||||
else
|
||||
gem 'activerecord-jdbcsqlite3-adapter', '>= 1.3.0'
|
||||
group :db do
|
||||
gem 'activerecord-jdbcmysql-adapter', '>= 1.3.0'
|
||||
gem 'activerecord-jdbcpostgresql-adapter', '>= 1.3.0'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
platforms :rbx do
|
||||
gem 'psych', '~> 2.0'
|
||||
gem 'rubysl', '~> 2.0'
|
||||
end
|
||||
|
||||
# gems that are necessary for ActiveRecord tests with Oracle database
|
||||
if ENV['ORACLE_ENHANCED']
|
||||
platforms :ruby do
|
||||
|
@ -59,7 +59,7 @@ independently outside Rails.
|
||||
|
||||
Run with `--help` or `-h` for options.
|
||||
|
||||
4. Go to http://localhost:3000 and you'll see: "Welcome aboard: You're riding Ruby on Rails!"
|
||||
4. Using a browser, go to http://localhost:3000 and you'll see: "Welcome aboard: You're riding Ruby on Rails!"
|
||||
|
||||
5. Follow the guidelines to start developing your application. You may find
|
||||
the following resources handy:
|
||||
|
@ -113,7 +113,7 @@ what to do in case anything goes wrong:
|
||||
$ git tag -m'tagging rc release' v3.0.10.rc1
|
||||
$ git push
|
||||
$ git push --tags
|
||||
$ for i in $(ls dist); do gem push $i; done
|
||||
$ for i in $(ls pkg); do gem push $i; done
|
||||
|
||||
=== Send Rails release announcements
|
||||
|
||||
|
10
Rakefile
10
Rakefile
@ -36,15 +36,7 @@ task :smoke do
|
||||
end
|
||||
|
||||
desc "Install gems for all projects."
|
||||
task :install => :build do
|
||||
version = File.read("RAILS_VERSION").strip
|
||||
(PROJECTS - ["railties"]).each do |project|
|
||||
puts "INSTALLING #{project}"
|
||||
system("gem install #{project}/pkg/#{project}-#{version}.gem --local --no-ri --no-rdoc")
|
||||
end
|
||||
system("gem install railties/pkg/railties-#{version}.gem --local --no-ri --no-rdoc")
|
||||
system("gem install pkg/rails-#{version}.gem --local --no-ri --no-rdoc")
|
||||
end
|
||||
task :install => "all:install"
|
||||
|
||||
desc "Generate documentation for the Rails framework"
|
||||
if ENV['EDGE']
|
||||
|
@ -1,7 +1,14 @@
|
||||
* invoke mailer defaults as procs only if they are procs, do not convert
|
||||
with to_proc. That an object is convertible to a proc does not mean it's
|
||||
meant to be always used as a proc. Fixes #11533
|
||||
* Instrument the generation of Action Mailer messages. The time it takes to
|
||||
generate a message is written to the log.
|
||||
|
||||
*Alex Tsukernik*
|
||||
*Daniel Schierbeck*
|
||||
|
||||
* Invoke mailer defaults as procs only if they are procs, do not convert with
|
||||
`to_proc`. That an object is convertible to a proc does not mean it's meant
|
||||
to be always used as a proc.
|
||||
|
||||
Fixes #11533.
|
||||
|
||||
*Alex Tsukernik*
|
||||
|
||||
Please check [4-0-stable](https://github.com/rails/rails/blob/4-0-stable/actionmailer/CHANGELOG.md) for previous changes.
|
||||
|
@ -61,9 +61,7 @@ generated would look like this:
|
||||
|
||||
Thank you for signing up!
|
||||
|
||||
In previous version of Rails you would call <tt>create_method_name</tt> and
|
||||
<tt>deliver_method_name</tt>. Rails 3.0 has a much simpler interface - you
|
||||
simply call the method and optionally call +deliver+ on the return value.
|
||||
In order to send mails, you simply call the method and then call +deliver+ on the return value.
|
||||
|
||||
Calling the method returns a Mail Message object:
|
||||
|
||||
@ -76,7 +74,7 @@ Or you can just chain the methods together like:
|
||||
|
||||
== Setting defaults
|
||||
|
||||
It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method <tt>default</tt> which you get for free from ActionMailer::Base. This method accepts a Hash as the parameter. You can use any of the headers e-mail messages has, like <tt>:from</tt> as the key. You can also pass in a string as the key, like "Content-Type", but Action Mailer does this out of the box for you, so you won't need to worry about that. Finally, it is also possible to pass in a Proc that will get evaluated when it is needed.
|
||||
It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method <tt>default</tt> which you get for free from <tt>ActionMailer::Base</tt>. This method accepts a Hash as the parameter. You can use any of the headers e-mail messages has, like <tt>:from</tt> as the key. You can also pass in a string as the key, like "Content-Type", but Action Mailer does this out of the box for you, so you won't need to worry about that. Finally, it is also possible to pass in a Proc that will get evaluated when it is needed.
|
||||
|
||||
Note that every value you set with this method will get overwritten if you use the same key in your mailer method.
|
||||
|
||||
|
@ -373,6 +373,12 @@ class Base < AbstractController::Base
|
||||
include AbstractController::AssetPaths
|
||||
include AbstractController::Callbacks
|
||||
|
||||
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [:@_action_has_layout]
|
||||
|
||||
def _protected_ivars # :nodoc:
|
||||
PROTECTED_IVARS
|
||||
end
|
||||
|
||||
helper ActionMailer::MailHelper
|
||||
|
||||
private_class_method :new #:nodoc:
|
||||
@ -385,10 +391,6 @@ class Base < AbstractController::Base
|
||||
parts_order: [ "text/plain", "text/enriched", "text/html" ]
|
||||
}.freeze
|
||||
|
||||
def self.default_protected_instance_vars
|
||||
super.concat [:@_action_has_layout]
|
||||
end
|
||||
|
||||
class << self
|
||||
# Register one or more Observers which will be notified when mail is delivered.
|
||||
def register_observers(*observers)
|
||||
@ -513,11 +515,18 @@ def initialize(method_name=nil, *args)
|
||||
process(method_name, *args) if method_name
|
||||
end
|
||||
|
||||
def process(*args) #:nodoc:
|
||||
lookup_context.skip_default_locale!
|
||||
def process(method_name, *args) #:nodoc:
|
||||
payload = {
|
||||
mailer: self.class.name,
|
||||
action: method_name
|
||||
}
|
||||
|
||||
super
|
||||
@_message = NullMail.new unless @_mail_was_called
|
||||
ActiveSupport::Notifications.instrument("process.action_mailer", payload) do
|
||||
lookup_context.skip_default_locale!
|
||||
|
||||
super
|
||||
@_message = NullMail.new unless @_mail_was_called
|
||||
end
|
||||
end
|
||||
|
||||
class NullMail #:nodoc:
|
||||
@ -687,9 +696,9 @@ def mail(headers = {}, &block)
|
||||
content_type = headers[:content_type]
|
||||
|
||||
# Call all the procs (if any)
|
||||
class_default = self.class.default
|
||||
default_values = class_default.merge(class_default) do |k,v|
|
||||
v.is_a?(Proc) ? instance_eval(&v) : v
|
||||
default_values = {}
|
||||
self.class.default.each do |k,v|
|
||||
default_values[k] = v.is_a?(Proc) ? instance_eval(&v) : v
|
||||
end
|
||||
|
||||
# Handle defaults
|
||||
|
@ -64,7 +64,7 @@ def wrap_delivery_behavior(mail, method=nil, options=nil) # :nodoc:
|
||||
raise "Delivery method cannot be nil"
|
||||
when Symbol
|
||||
if klass = delivery_methods[method]
|
||||
mail.delivery_method(klass,(send(:"#{method}_settings") || {}).merge!(options || {}))
|
||||
mail.delivery_method(klass, (send(:"#{method}_settings") || {}).merge(options || {}))
|
||||
else
|
||||
raise "Invalid delivery method #{method.inspect}"
|
||||
end
|
||||
|
@ -19,6 +19,13 @@ def receive(event)
|
||||
debug(event.payload[:mail])
|
||||
end
|
||||
|
||||
# An email was generated.
|
||||
def process(event)
|
||||
mailer = event.payload[:mailer]
|
||||
action = event.payload[:action]
|
||||
debug("\n#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms")
|
||||
end
|
||||
|
||||
# Use the logger configured for ActionMailer::Base
|
||||
def logger
|
||||
ActionMailer::Base.logger
|
||||
|
@ -152,6 +152,9 @@ def teardown
|
||||
assert_equal "overridden", delivery_method_instance.settings[:user_name]
|
||||
assert_equal "somethingobtuse", delivery_method_instance.settings[:password]
|
||||
assert_equal delivery_method_instance.settings.merge(overridden_options), delivery_method_instance.settings
|
||||
|
||||
# make sure that overriding delivery method options per mail instance doesn't affect the Base setting
|
||||
assert_equal settings, ActionMailer::Base.smtp_settings
|
||||
end
|
||||
|
||||
test "non registered delivery methods raises errors" do
|
||||
|
@ -1 +1 @@
|
||||
<%= t('.greet_user', :name => 'lifo') %>
|
||||
<%= t('.greet_user', name: 'lifo') %>
|
20
actionmailer/test/fixtures/raw_email10
vendored
20
actionmailer/test/fixtures/raw_email10
vendored
@ -1,20 +0,0 @@
|
||||
Return-Path: <xxx@xxxx.xxx>
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
|
||||
Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
|
||||
Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
|
||||
Date: Tue, 10 May 2005 15:27:03 -0500
|
||||
From: xxx@xxxx.xxx
|
||||
Sender: xxx@xxxx.xxx
|
||||
To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Message-Id: <xxx@xxxx.xxx>
|
||||
X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Delivered-To: xxx@xxxx.xxx
|
||||
Importance: normal
|
||||
Content-Type: text/plain; charset=X-UNKNOWN
|
||||
|
||||
Test test. Hi. Waving. m
|
||||
|
||||
----------------------------------------------------------------
|
||||
Sent via Bell Mobility's Text Messaging service.
|
||||
Envoyé par le service de messagerie texte de Bell Mobilité.
|
||||
----------------------------------------------------------------
|
32
actionmailer/test/fixtures/raw_email12
vendored
32
actionmailer/test/fixtures/raw_email12
vendored
@ -1,32 +0,0 @@
|
||||
Mime-Version: 1.0 (Apple Message framework v730)
|
||||
Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
|
||||
Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
|
||||
From: foo@example.com
|
||||
Subject: testing
|
||||
Date: Mon, 6 Jun 2005 22:21:22 +0200
|
||||
To: blah@example.com
|
||||
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Type: text/plain;
|
||||
charset=ISO-8859-1;
|
||||
delsp=yes;
|
||||
format=flowed
|
||||
|
||||
This is the first part.
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Type: image/jpeg
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Location: Photo25.jpg
|
||||
Content-ID: <qbFGyPQAS8>
|
||||
Content-Disposition: inline
|
||||
|
||||
jamisSqGSIb3DQEHAqCAMIjamisxCzAJBgUrDgMCGgUAMIAGCSqGSjamisEHAQAAoIIFSjCCBUYw
|
||||
ggQujamisQICBD++ukQwDQYJKojamisNAQEFBQAwMTELMAkGA1UEBhMCRjamisAKBgNVBAoTA1RE
|
||||
QzEUMBIGjamisxMLVERDIE9DRVMgQ0jamisNMDQwMjI5MTE1OTAxWhcNMDYwMjamisIyOTAxWjCB
|
||||
gDELMAkGA1UEjamisEsxKTAnBgNVBAoTIEjamisuIG9yZ2FuaXNhdG9yaXNrIHRpbjamisRuaW5=
|
||||
|
||||
--Apple-Mail-13-196941151--
|
||||
|
29
actionmailer/test/fixtures/raw_email13
vendored
29
actionmailer/test/fixtures/raw_email13
vendored
@ -1,29 +0,0 @@
|
||||
Mime-Version: 1.0 (Apple Message framework v730)
|
||||
Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
|
||||
Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
|
||||
From: foo@example.com
|
||||
Subject: testing
|
||||
Date: Mon, 6 Jun 2005 22:21:22 +0200
|
||||
To: blah@example.com
|
||||
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Type: text/plain;
|
||||
charset=ISO-8859-1;
|
||||
delsp=yes;
|
||||
format=flowed
|
||||
|
||||
This is the first part.
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Type: text/x-ruby-script; name="hello.rb"
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: attachment;
|
||||
filename="api.rb"
|
||||
|
||||
puts "Hello, world!"
|
||||
gets
|
||||
|
||||
--Apple-Mail-13-196941151--
|
||||
|
114
actionmailer/test/fixtures/raw_email2
vendored
114
actionmailer/test/fixtures/raw_email2
vendored
@ -1,114 +0,0 @@
|
||||
From xxxxxxxxx.xxxxxxx@gmail.com Sun May 8 19:07:09 2005
|
||||
Return-Path: <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
X-Original-To: xxxxx@xxxxx.xxxxxxxxx.com
|
||||
Delivered-To: xxxxx@xxxxx.xxxxxxxxx.com
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
by xxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 06C9DA98D
|
||||
for <xxxxx@xxxxx.xxxxxxxxx.com>; Sun, 8 May 2005 19:09:13 +0000 (GMT)
|
||||
Received: from xxxxx.xxxxxxxxx.com ([127.0.0.1])
|
||||
by localhost (xxxxx.xxxxxxxxx.com [127.0.0.1]) (amavisd-new, port 10024)
|
||||
with LMTP id 88783-08 for <xxxxx@xxxxx.xxxxxxxxx.com>;
|
||||
Sun, 8 May 2005 19:09:12 +0000 (GMT)
|
||||
Received: from xxxxxxx.xxxxxxxxx.com (xxxxxxx.xxxxxxxxx.com [69.36.39.150])
|
||||
by xxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 10D8BA960
|
||||
for <xxxxx@xxxxxxxxx.org>; Sun, 8 May 2005 19:09:12 +0000 (GMT)
|
||||
Received: from zproxy.gmail.com (zproxy.gmail.com [64.233.162.199])
|
||||
by xxxxxxx.xxxxxxxxx.com (Postfix) with ESMTP id 9EBC4148EAB
|
||||
for <xxxxx@xxxxxxxxx.com>; Sun, 8 May 2005 14:09:11 -0500 (CDT)
|
||||
Received: by zproxy.gmail.com with SMTP id 13so1233405nzp
|
||||
for <xxxxx@xxxxxxxxx.com>; Sun, 08 May 2005 12:09:11 -0700 (PDT)
|
||||
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
|
||||
s=beta; d=gmail.com;
|
||||
h=received:message-id:date:from:reply-to:to:subject:in-reply-to:mime-version:content-type:references;
|
||||
b=cid1mzGEFa3gtRa06oSrrEYfKca2CTKu9sLMkWxjbvCsWMtp9RGEILjUz0L5RySdH5iO661LyNUoHRFQIa57bylAbXM3g2DTEIIKmuASDG3x3rIQ4sHAKpNxP7Pul+mgTaOKBv+spcH7af++QEJ36gHFXD2O/kx9RePs3JNf/K8=
|
||||
Received: by 10.36.10.16 with SMTP id 16mr1012493nzj;
|
||||
Sun, 08 May 2005 12:09:11 -0700 (PDT)
|
||||
Received: by 10.36.5.10 with HTTP; Sun, 8 May 2005 12:09:11 -0700 (PDT)
|
||||
Message-ID: <e85734b90505081209eaaa17b@mail.gmail.com>
|
||||
Date: Sun, 8 May 2005 14:09:11 -0500
|
||||
From: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
Reply-To: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
To: xxxxx xxxx <xxxxx@xxxxxxxxx.com>
|
||||
Subject: Fwd: Signed email causes file attachments
|
||||
In-Reply-To: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="----=_Part_5028_7368284.1115579351471"
|
||||
References: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
|
||||
|
||||
------=_Part_5028_7368284.1115579351471
|
||||
Content-Type: text/plain; charset=ISO-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
|
||||
We should not include these files or vcards as attachments.
|
||||
|
||||
---------- Forwarded message ----------
|
||||
From: xxxxx xxxxxx <xxxxxxxx@xxx.com>
|
||||
Date: May 8, 2005 1:17 PM
|
||||
Subject: Signed email causes file attachments
|
||||
To: xxxxxxx@xxxxxxxxxx.com
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
Just started to use my xxxxxxxx account (to set-up a GTD system,
|
||||
natch) and noticed that when I send content via email the signature/
|
||||
certificate from my email account gets added as a file (e.g.
|
||||
"smime.p7s").
|
||||
|
||||
Obviously I can uncheck the signature option in the Mail compose
|
||||
window but how often will I remember to do that?
|
||||
|
||||
Is there any way these kind of files could be ignored, e.g. via some
|
||||
sort of exclusions list?
|
||||
|
||||
------=_Part_5028_7368284.1115579351471
|
||||
Content-Type: application/pkcs7-signature; name=smime.p7s
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment; filename="smime.p7s"
|
||||
|
||||
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGFDCCAs0w
|
||||
ggI2oAMCAQICAw5c+TANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
|
||||
d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
|
||||
YWlsIElzc3VpbmcgQ0EwHhcNMDUwMzI5MDkzOTEwWhcNMDYwMzI5MDkzOTEwWjBCMR8wHQYDVQQD
|
||||
ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMR8wHQYJKoZIhvcNAQkBFhBzbWhhdW5jaEBtYWMuY29t
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn90dPsYS3LjfMY211OSYrDQLzwNYPlAL
|
||||
7+/0XA+kdy8/rRnyEHFGwhNCDmg0B6pxC7z3xxJD/8GfCd+IYUUNUQV5m9MkxfP9pTVXZVIYLaBw
|
||||
o8xS3A0a1LXealcmlEbJibmKkEaoXci3MhryLgpaa+Kk/sH02SNatDO1vS28bPsibZpcc6deFrla
|
||||
hSYnL+PW54mDTGHIcCN2fbx/Y6qspzqmtKaXrv75NBtuy9cB6KzU4j2xXbTkAwz3pRSghJJaAwdp
|
||||
+yIivAD3vr0kJE3p+Ez34HMh33EXEpFoWcN+MCEQZD9WnmFViMrvfvMXLGVFQfAAcC060eGFSRJ1
|
||||
ZQ9UVQIDAQABoy0wKzAbBgNVHREEFDASgRBzbWhhdW5jaEBtYWMuY29tMAwGA1UdEwEB/wQCMAAw
|
||||
DQYJKoZIhvcNAQEEBQADgYEAQMrg1n2pXVWteP7BBj+Pk3UfYtbuHb42uHcLJjfjnRlH7AxnSwrd
|
||||
L3HED205w3Cq8T7tzVxIjRRLO/ljq0GedSCFBky7eYo1PrXhztGHCTSBhsiWdiyLWxKlOxGAwJc/
|
||||
lMMnwqLOdrQcoF/YgbjeaUFOQbUh94w9VDNpWZYCZwcwggM/MIICqKADAgECAgENMA0GCSqGSIb3
|
||||
DQEBBQUAMIHRMQswCQYDVQQGEwJaQTEVMBMGA1UECBMMV2VzdGVybiBDYXBlMRIwEAYDVQQHEwlD
|
||||
YXBlIFRvd24xGjAYBgNVBAoTEVRoYXd0ZSBDb25zdWx0aW5nMSgwJgYDVQQLEx9DZXJ0aWZpY2F0
|
||||
aW9uIFNlcnZpY2VzIERpdmlzaW9uMSQwIgYDVQQDExtUaGF3dGUgUGVyc29uYWwgRnJlZW1haWwg
|
||||
Q0ExKzApBgkqhkiG9w0BCQEWHHBlcnNvbmFsLWZyZWVtYWlsQHRoYXd0ZS5jb20wHhcNMDMwNzE3
|
||||
MDAwMDAwWhcNMTMwNzE2MjM1OTU5WjBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3RlIENv
|
||||
bnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWlsIElz
|
||||
c3VpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMSmPFVzVftOucqZWh5owHUEcJ3f
|
||||
6f+jHuy9zfVb8hp2vX8MOmHyv1HOAdTlUAow1wJjWiyJFXCO3cnwK4Vaqj9xVsuvPAsH5/EfkTYk
|
||||
KhPPK9Xzgnc9A74r/rsYPge/QIACZNenprufZdHFKlSFD0gEf6e20TxhBEAeZBlyYLf7AgMBAAGj
|
||||
gZQwgZEwEgYDVR0TAQH/BAgwBgEB/wIBADBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLnRo
|
||||
YXd0ZS5jb20vVGhhd3RlUGVyc29uYWxGcmVlbWFpbENBLmNybDALBgNVHQ8EBAMCAQYwKQYDVR0R
|
||||
BCIwIKQeMBwxGjAYBgNVBAMTEVByaXZhdGVMYWJlbDItMTM4MA0GCSqGSIb3DQEBBQUAA4GBAEiM
|
||||
0VCD6gsuzA2jZqxnD3+vrL7CF6FDlpSdf0whuPg2H6otnzYvwPQcUCCTcDz9reFhYsPZOhl+hLGZ
|
||||
GwDFGguCdJ4lUJRix9sncVcljd2pnDmOjCBPZV+V2vf3h9bGCE6u9uo05RAaWzVNd+NWIXiC3CEZ
|
||||
Nd4ksdMdRv9dX2VPMYIC5zCCAuMCAQEwaTBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhhd3Rl
|
||||
IENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVtYWls
|
||||
IElzc3VpbmcgQ0ECAw5c+TAJBgUrDgMCGgUAoIIBUzAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcB
|
||||
MBwGCSqGSIb3DQEJBTEPFw0wNTA1MDgxODE3NDZaMCMGCSqGSIb3DQEJBDEWBBQSkG9j6+hB0pKp
|
||||
fV9tCi/iP59sNTB4BgkrBgEEAYI3EAQxazBpMGIxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3
|
||||
dGUgQ29uc3VsdGluZyAoUHR5KSBMdGQuMSwwKgYDVQQDEyNUaGF3dGUgUGVyc29uYWwgRnJlZW1h
|
||||
aWwgSXNzdWluZyBDQQIDDlz5MHoGCyqGSIb3DQEJEAILMWugaTBiMQswCQYDVQQGEwJaQTElMCMG
|
||||
A1UEChMcVGhhd3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNv
|
||||
bmFsIEZyZWVtYWlsIElzc3VpbmcgQ0ECAw5c+TANBgkqhkiG9w0BAQEFAASCAQAm1GeF7dWfMvrW
|
||||
8yMPjkhE+R8D1DsiCoWSCp+5gAQm7lcK7V3KrZh5howfpI3TmCZUbbaMxOH+7aKRKpFemxoBY5Q8
|
||||
rnCkbpg/++/+MI01T69hF/rgMmrGcrv2fIYy8EaARLG0xUVFSZHSP+NQSYz0TTmh4cAESHMzY3JA
|
||||
nHOoUkuPyl8RXrimY1zn0lceMXlweZRouiPGuPNl1hQKw8P+GhOC5oLlM71UtStnrlk3P9gqX5v7
|
||||
Tj7Hx057oVfY8FMevjxGwU3EK5TczHezHbWWgTyum9l2ZQbUQsDJxSniD3BM46C1VcbDLPaotAZ0
|
||||
fTYLZizQfm5hcWEbfYVzkSzLAAAAAAAA
|
||||
------=_Part_5028_7368284.1115579351471--
|
||||
|
70
actionmailer/test/fixtures/raw_email3
vendored
70
actionmailer/test/fixtures/raw_email3
vendored
@ -1,70 +0,0 @@
|
||||
From xxxx@xxxx.com Tue May 10 11:28:07 2005
|
||||
Return-Path: <xxxx@xxxx.com>
|
||||
X-Original-To: xxxx@xxxx.com
|
||||
Delivered-To: xxxx@xxxx.com
|
||||
Received: from localhost (localhost [127.0.0.1])
|
||||
by xxx.xxxxx.com (Postfix) with ESMTP id 50FD3A96F
|
||||
for <xxxx@xxxx.com>; Tue, 10 May 2005 17:26:50 +0000 (GMT)
|
||||
Received: from xxx.xxxxx.com ([127.0.0.1])
|
||||
by localhost (xxx.xxxxx.com [127.0.0.1]) (amavisd-new, port 10024)
|
||||
with LMTP id 70060-03 for <xxxx@xxxx.com>;
|
||||
Tue, 10 May 2005 17:26:49 +0000 (GMT)
|
||||
Received: from xxx.xxxxx.com (xxx.xxxxx.com [69.36.39.150])
|
||||
by xxx.xxxxx.com (Postfix) with ESMTP id 8B957A94B
|
||||
for <xxxx@xxxx.com>; Tue, 10 May 2005 17:26:48 +0000 (GMT)
|
||||
Received: from xxx.xxxxx.com (xxx.xxxxx.com [64.233.184.203])
|
||||
by xxx.xxxxx.com (Postfix) with ESMTP id 9972514824C
|
||||
for <xxxx@xxxx.com>; Tue, 10 May 2005 12:26:40 -0500 (CDT)
|
||||
Received: by xxx.xxxxx.com with SMTP id 68so1694448wri
|
||||
for <xxxx@xxxx.com>; Tue, 10 May 2005 10:26:40 -0700 (PDT)
|
||||
DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws;
|
||||
s=beta; d=xxxxx.com;
|
||||
h=received:message-id:date:from:reply-to:to:subject:mime-version:content-type;
|
||||
b=g8ZO5ttS6GPEMAz9WxrRk9+9IXBUfQIYsZLL6T88+ECbsXqGIgfGtzJJFn6o9CE3/HMrrIGkN5AisxVFTGXWxWci5YA/7PTVWwPOhJff5BRYQDVNgRKqMl/SMttNrrRElsGJjnD1UyQ/5kQmcBxq2PuZI5Zc47u6CILcuoBcM+A=
|
||||
Received: by 10.54.96.19 with SMTP id t19mr621017wrb;
|
||||
Tue, 10 May 2005 10:26:39 -0700 (PDT)
|
||||
Received: by 10.54.110.5 with HTTP; Tue, 10 May 2005 10:26:39 -0700 (PDT)
|
||||
Message-ID: <xxxx@xxxx.com>
|
||||
Date: Tue, 10 May 2005 11:26:39 -0600
|
||||
From: Test Tester <xxxx@xxxx.com>
|
||||
Reply-To: Test Tester <xxxx@xxxx.com>
|
||||
To: xxxx@xxxx.com, xxxx@xxxx.com
|
||||
Subject: Another PDF
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="----=_Part_2192_32400445.1115745999735"
|
||||
X-Virus-Scanned: amavisd-new at textdrive.com
|
||||
|
||||
------=_Part_2192_32400445.1115745999735
|
||||
Content-Type: text/plain; charset=ISO-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
|
||||
Just attaching another PDF, here, to see what the message looks like,
|
||||
and to see if I can figure out what is going wrong here.
|
||||
|
||||
------=_Part_2192_32400445.1115745999735
|
||||
Content-Type: application/pdf; name="broken.pdf"
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment; filename="broken.pdf"
|
||||
|
||||
JVBERi0xLjQNCiXk9tzfDQoxIDAgb2JqDQo8PCAvTGVuZ3RoIDIgMCBSDQogICAvRmlsdGVyIC9G
|
||||
bGF0ZURlY29kZQ0KPj4NCnN0cmVhbQ0KeJy9Wt2KJbkNvm/od6jrhZxYln9hWEh2p+8HBvICySaE
|
||||
ycLuTV4/1ifJ9qnq09NpSBimu76yLUuy/qzqcPz7+em3Ixx/CDc6CsXxs3b5+fvfjr/8cPz6/BRu
|
||||
rbfAx/n3739/fuJylJ5u5fjX81OuDr4deK4Bz3z/aDP+8fz0yw8g0Ofq7ktr1Mn+u28rvhy/jVeD
|
||||
QSa+9YNKHP/pxjvDNfVAx/m3MFz54FhvTbaseaxiDoN2LeMVMw+yA7RbHSCDzxZuaYB2E1Yay7QU
|
||||
x89vz0+tyFDKMlAHK5yqLmnjF+c4RjEiQIUeKwblXMe+AsZjN1J5yGQL5DHpDHksurM81rF6PKab
|
||||
gK6zAarIDzIiUY23rJsN9iorAE816aIu6lsgAdQFsuhhkHOUFgVjp2GjMqSewITXNQ27jrMeamkg
|
||||
1rPI3iLWG2CIaSBB+V1245YVRICGbbpYKHc2USFDl6M09acQVQYhlwIrkBNLISvXhGlF1wi5FHCw
|
||||
wxZkoGNJlVeJCEsqKA+3YAV5AMb6KkeaqEJQmFKKQU8T1pRi2ihE1Y4CDrqoYFFXYjJJOatsyzuI
|
||||
8SIlykuxKTMibWK8H1PgEvqYgs4GmQSrEjJAalgGirIhik+p4ZQN9E3ETFPAHE1b8pp1l/0Rc1gl
|
||||
fQs0ABWvyoZZzU8VnPXwVVcO9BEsyjEJaO6eBoZRyKGlrKoYoOygA8BGIzgwN3RQ15ouigG5idZQ
|
||||
fx2U4Db2CqiLO0WHAZoylGiCAqhniNQjFjQPSkmjwfNTgQ6M1Ih+eWo36wFmjIxDJZiGUBiWsAyR
|
||||
xX3EekGOizkGI96Ol9zVZTAivikURhRsHh2E3JhWMpSTZCnnonrLhMCodgrNcgo4uyJUJc6qnVss
|
||||
nrGd1Ptr0YwisCOYyIbUwVjV4xBUNLbguSO2YHujonAMJkMdSI7bIw91Akq2AUlMUWGFTMAOamjU
|
||||
OvZQCxIkY2pCpMFo/IwLdVLHs6nddwTRrgoVbvLU9eB0G4EMndV0TNoxHbt3JBWwK6hhv3iHfDtF
|
||||
yokB302IpEBTnWICde4uYc/1khDbSIkQopO6lcqamGBu1OSE3N5IPSsZX00CkSHRiiyx6HQIShsS
|
||||
HSVNswdVsaOUSAWq9aYhDtGDaoG5a3lBGkYt/lFlBFt1UqrYnzVtUpUQnLiZeouKgf1KhRBViRRk
|
||||
ExepJCzTwEmFDalIRbLEGtw0gfpESOpIAF/NnpPzcVCG86s0g2DuSyd41uhNGbEgaSrWEXORErbw
|
||||
------=_Part_2192_32400445.1115745999735--
|
||||
|
59
actionmailer/test/fixtures/raw_email4
vendored
59
actionmailer/test/fixtures/raw_email4
vendored
@ -1,59 +0,0 @@
|
||||
Return-Path: <xxx@xxxx.xxx>
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id 6AAEE3B4D23 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:23 -0500
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id j48HUC213279 for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:13 -0500
|
||||
Received: from conversion-xxx.xxxx.xxx.net by xxx.xxxx.xxx id <0IG600901LQ64I@xxx.xxxx.xxx> for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:12 -0500
|
||||
Received: from agw1 by xxx.xxxx.xxx with ESMTP id <0IG600JFYLYCAxxx@xxxx.xxx> for <xxx@xxxx.xxx>; Sun, 8 May 2005 12:30:12 -0500
|
||||
Date: Sun, 8 May 2005 12:30:08 -0500
|
||||
From: xxx@xxxx.xxx
|
||||
To: xxx@xxxx.xxx
|
||||
Message-Id: <7864245.1115573412626.JavaMxxx@xxxx.xxx>
|
||||
Subject: Filth
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed; boundary=mimepart_427e4cb4ca329_133ae40413c81ef
|
||||
X-Mms-Priority: 1
|
||||
X-Mms-Transaction-Id: 3198421808-0
|
||||
X-Mms-Message-Type: 0
|
||||
X-Mms-Sender-Visibility: 1
|
||||
X-Mms-Read-Reply: 1
|
||||
X-Original-To: xxx@xxxx.xxx
|
||||
X-Mms-Message-Class: 0
|
||||
X-Mms-Delivery-Report: 0
|
||||
X-Mms-Mms-Version: 16
|
||||
Delivered-To: xxx@xxxx.xxx
|
||||
X-Nokia-Ag-Version: 2.0
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
--mimepart_427e4cb4ca329_133ae40413c81ef
|
||||
Content-Type: multipart/mixed; boundary=mimepart_427e4cb4cbd97_133ae40413c8217
|
||||
|
||||
|
||||
|
||||
--mimepart_427e4cb4cbd97_133ae40413c8217
|
||||
Content-Type: text/plain; charset=utf-8
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Disposition: inline
|
||||
Content-Location: text.txt
|
||||
|
||||
Some text
|
||||
|
||||
--mimepart_427e4cb4cbd97_133ae40413c8217--
|
||||
|
||||
--mimepart_427e4cb4ca329_133ae40413c81ef
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
|
||||
|
||||
--
|
||||
This Orange Multi Media Message was sent wirefree from an Orange
|
||||
MMS phone. If you would like to reply, please text or phone the
|
||||
sender directly by using the phone number listed in the sender's
|
||||
address. To learn more about Orange's Multi Media Messaging
|
||||
Service, find us on the Web at xxx.xxxx.xxx.uk/mms
|
||||
|
||||
|
||||
--mimepart_427e4cb4ca329_133ae40413c81ef
|
||||
|
||||
|
||||
--mimepart_427e4cb4ca329_133ae40413c81ef-
|
||||
|
19
actionmailer/test/fixtures/raw_email5
vendored
19
actionmailer/test/fixtures/raw_email5
vendored
@ -1,19 +0,0 @@
|
||||
Return-Path: <xxx@xxxx.xxx>
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
|
||||
Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
|
||||
Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
|
||||
Date: Tue, 10 May 2005 15:27:03 -0500
|
||||
From: xxx@xxxx.xxx
|
||||
Sender: xxx@xxxx.xxx
|
||||
To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Message-Id: <xxx@xxxx.xxx>
|
||||
X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Delivered-To: xxx@xxxx.xxx
|
||||
Importance: normal
|
||||
|
||||
Test test. Hi. Waving. m
|
||||
|
||||
----------------------------------------------------------------
|
||||
Sent via Bell Mobility's Text Messaging service.
|
||||
Envoyé par le service de messagerie texte de Bell Mobilité.
|
||||
----------------------------------------------------------------
|
20
actionmailer/test/fixtures/raw_email6
vendored
20
actionmailer/test/fixtures/raw_email6
vendored
@ -1,20 +0,0 @@
|
||||
Return-Path: <xxx@xxxx.xxx>
|
||||
Received: from xxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id C1B953B4CB6 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:05 -0500
|
||||
Received: from SMS-GTYxxx.xxxx.xxx by xxx.xxxx.xxx with ESMTP id ca for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:04 -0500
|
||||
Received: from xxx.xxxx.xxx by SMS-GTYxxx.xxxx.xxx with ESMTP id j4AKR3r23323 for <xxxxx@Exxx.xxxx.xxx>; Tue, 10 May 2005 15:27:03 -0500
|
||||
Date: Tue, 10 May 2005 15:27:03 -0500
|
||||
From: xxx@xxxx.xxx
|
||||
Sender: xxx@xxxx.xxx
|
||||
To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Message-Id: <xxx@xxxx.xxx>
|
||||
X-Original-To: xxxxxxxxxxx@xxxx.xxxx.xxx
|
||||
Delivered-To: xxx@xxxx.xxx
|
||||
Importance: normal
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
|
||||
Test test. Hi. Waving. m
|
||||
|
||||
----------------------------------------------------------------
|
||||
Sent via Bell Mobility's Text Messaging service.
|
||||
Envoyé par le service de messagerie texte de Bell Mobilité.
|
||||
----------------------------------------------------------------
|
66
actionmailer/test/fixtures/raw_email7
vendored
66
actionmailer/test/fixtures/raw_email7
vendored
@ -1,66 +0,0 @@
|
||||
Mime-Version: 1.0 (Apple Message framework v730)
|
||||
Content-Type: multipart/mixed; boundary=Apple-Mail-13-196941151
|
||||
Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
|
||||
From: foo@example.com
|
||||
Subject: testing
|
||||
Date: Mon, 6 Jun 2005 22:21:22 +0200
|
||||
To: blah@example.com
|
||||
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Type: multipart/mixed;
|
||||
boundary=Apple-Mail-12-196940926
|
||||
|
||||
|
||||
--Apple-Mail-12-196940926
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Type: text/plain;
|
||||
charset=ISO-8859-1;
|
||||
delsp=yes;
|
||||
format=flowed
|
||||
|
||||
This is the first part.
|
||||
|
||||
--Apple-Mail-12-196940926
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Type: text/x-ruby-script;
|
||||
x-unix-mode=0666;
|
||||
name="test.rb"
|
||||
Content-Disposition: attachment;
|
||||
filename=test.rb
|
||||
|
||||
puts "testing, testing"
|
||||
|
||||
--Apple-Mail-12-196940926
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Type: application/pdf;
|
||||
x-unix-mode=0666;
|
||||
name="test.pdf"
|
||||
Content-Disposition: inline;
|
||||
filename=test.pdf
|
||||
|
||||
YmxhaCBibGFoIGJsYWg=
|
||||
|
||||
--Apple-Mail-12-196940926
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Type: text/plain;
|
||||
charset=US-ASCII;
|
||||
format=flowed
|
||||
|
||||
|
||||
|
||||
--Apple-Mail-12-196940926--
|
||||
|
||||
--Apple-Mail-13-196941151
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Type: application/pkcs7-signature;
|
||||
name=smime.p7s
|
||||
Content-Disposition: attachment;
|
||||
filename=smime.p7s
|
||||
|
||||
jamisSqGSIb3DQEHAqCAMIjamisxCzAJBgUrDgMCGgUAMIAGCSqGSjamisEHAQAAoIIFSjCCBUYw
|
||||
ggQujamisQICBD++ukQwDQYJKojamisNAQEFBQAwMTELMAkGA1UEBhMCRjamisAKBgNVBAoTA1RE
|
||||
QzEUMBIGjamisxMLVERDIE9DRVMgQ0jamisNMDQwMjI5MTE1OTAxWhcNMDYwMjamisIyOTAxWjCB
|
||||
gDELMAkGA1UEjamisEsxKTAnBgNVBAoTIEjamisuIG9yZ2FuaXNhdG9yaXNrIHRpbjamisRuaW5=
|
||||
|
||||
--Apple-Mail-13-196941151--
|
47
actionmailer/test/fixtures/raw_email8
vendored
47
actionmailer/test/fixtures/raw_email8
vendored
@ -1,47 +0,0 @@
|
||||
From xxxxxxxxx.xxxxxxx@gmail.com Sun May 8 19:07:09 2005
|
||||
Return-Path: <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
Message-ID: <e85734b90505081209eaaa17b@mail.gmail.com>
|
||||
Date: Sun, 8 May 2005 14:09:11 -0500
|
||||
From: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
Reply-To: xxxxxxxxx xxxxxxx <xxxxxxxxx.xxxxxxx@gmail.com>
|
||||
To: xxxxx xxxx <xxxxx@xxxxxxxxx.com>
|
||||
Subject: Fwd: Signed email causes file attachments
|
||||
In-Reply-To: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="----=_Part_5028_7368284.1115579351471"
|
||||
References: <F6E2D0B4-CC35-4A91-BA4C-C7C712B10C13@mac.com>
|
||||
|
||||
------=_Part_5028_7368284.1115579351471
|
||||
Content-Type: text/plain; charset=ISO-8859-1
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Disposition: inline
|
||||
|
||||
We should not include these files or vcards as attachments.
|
||||
|
||||
---------- Forwarded message ----------
|
||||
From: xxxxx xxxxxx <xxxxxxxx@xxx.com>
|
||||
Date: May 8, 2005 1:17 PM
|
||||
Subject: Signed email causes file attachments
|
||||
To: xxxxxxx@xxxxxxxxxx.com
|
||||
|
||||
|
||||
Hi,
|
||||
|
||||
Test attachments oddly encoded with japanese charset.
|
||||
|
||||
|
||||
------=_Part_5028_7368284.1115579351471
|
||||
Content-Type: application/octet-stream; name*=iso-2022-jp'ja'01%20Quien%20Te%20Dij%8aat.%20Pitbull.mp3
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Disposition: attachment
|
||||
|
||||
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGFDCCAs0w
|
||||
ggI2oAMCAQICAw5c+TANBgkqhkiG9w0BAQQFADBiMQswCQYDVQQGEwJaQTElMCMGA1UEChMcVGhh
|
||||
d3RlIENvbnN1bHRpbmcgKFB0eSkgTHRkLjEsMCoGA1UEAxMjVGhhd3RlIFBlcnNvbmFsIEZyZWVt
|
||||
YWlsIElzc3VpbmcgQ0EwHhcNMDUwMzI5MDkzOTEwWhcNMDYwMzI5MDkzOTEwWjBCMR8wHQYDVQQD
|
||||
ExZUaGF3dGUgRnJlZW1haWwgTWVtYmVyMR8wHQYJKoZIhvcNAQkBFhBzbWhhdW5jaEBtYWMuY29t
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn90dPsYS3LjfMY211OSYrDQLzwNYPlAL
|
||||
7+/0XA+kdy8/rRnyEHFGwhNCDmg0B6pxC7z3xxJD/8GfCd+IYUUNUQV5m9MkxfP9pTVXZVIYLaBw
|
||||
------=_Part_5028_7368284.1115579351471--
|
||||
|
28
actionmailer/test/fixtures/raw_email9
vendored
28
actionmailer/test/fixtures/raw_email9
vendored
@ -1,28 +0,0 @@
|
||||
Received: from xxx.xxx.xxx ([xxx.xxx.xxx.xxx] verified)
|
||||
by xxx.com (CommuniGate Pro SMTP 4.2.8)
|
||||
with SMTP id 2532598 for xxx@xxx.com; Wed, 23 Feb 2005 17:51:49 -0500
|
||||
Received-SPF: softfail
|
||||
receiver=xxx.com; client-ip=xxx.xxx.xxx.xxx; envelope-from=xxx@xxx.xxx
|
||||
quite Delivered-To: xxx@xxx.xxx
|
||||
Received: by xxx.xxx.xxx (Wostfix, from userid xxx)
|
||||
id 0F87F333; Wed, 23 Feb 2005 16:16:17 -0600
|
||||
Date: Wed, 23 Feb 2005 18:20:17 -0400
|
||||
From: "xxx xxx" <xxx@xxx.xxx>
|
||||
Message-ID: <4D6AA7EB.6490534@xxx.xxx>
|
||||
To: xxx@xxx.com
|
||||
Subject: Stop adware/spyware once and for all.
|
||||
X-Scanned-By: MIMEDefang 2.11 (www dot roaringpenguin dot com slash mimedefang)
|
||||
|
||||
You are infected with:
|
||||
Ad Ware and Spy Ware
|
||||
|
||||
Get your free scan and removal download now,
|
||||
before it gets any worse.
|
||||
|
||||
http://xxx.xxx.info?aid=3D13&?stat=3D4327kdzt
|
||||
|
||||
|
||||
|
||||
|
||||
no more? (you will still be infected)
|
||||
http://xxx.xxx.info/discon/?xxx@xxx.com
|
@ -1,14 +0,0 @@
|
||||
Mime-Version: 1.0 (Apple Message framework v730)
|
||||
Message-Id: <9169D984-4E0B-45EF-82D4-8F5E53AD7012@example.com>
|
||||
From: foo@example.com
|
||||
Subject: testing
|
||||
Date: Mon, 6 Jun 2005 22:21:22 +0200
|
||||
To: blah@example.com
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
Content-Type: text/plain
|
||||
|
||||
A fax has arrived from remote ID ''.=0D=0A-----------------------=
|
||||
-------------------------------------=0D=0ATime: 3/9/2006 3:50:52=
|
||||
PM=0D=0AReceived from remote ID: =0D=0AInbound user ID XXXXXXXXXX, r=
|
||||
outing code XXXXXXXXX=0D=0AResult: (0/352;0/0) Successful Send=0D=0AP=
|
||||
age record: 1 - 1=0D=0AElapsed time: 00:58 on channel 11=0D=0A
|
@ -1,104 +0,0 @@
|
||||
Return-Path: <mikel.other@baci>
|
||||
Received: from some.isp.com by baci with ESMTP id 632BD5758 for <mikel.lindsaar@baci>; Sun, 21 Oct 2007 19:38:21 +1000
|
||||
Date: Sun, 21 Oct 2007 19:38:13 +1000
|
||||
From: Mikel Lindsaar <mikel.other@baci>
|
||||
Reply-To: Mikel Lindsaar <mikel.other@baci>
|
||||
To: mikel.lindsaar@baci
|
||||
Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a>
|
||||
Subject: Testing outlook
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary=----=_NextPart_000_0093_01C81419.EB75E850
|
||||
Delivered-To: mikel.lindsaar@baci
|
||||
X-Mimeole: Produced By Microsoft MimeOLE V6.00.2900.3138
|
||||
X-Msmail-Priority: Normal
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: Quoted-printable
|
||||
|
||||
Hello
|
||||
This is an outlook test
|
||||
|
||||
So there.
|
||||
|
||||
Me.
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: Quoted-printable
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML><HEAD>
|
||||
<META http-equiv=3DContent-Type content=3D"text/html; =
|
||||
charset=3Diso-8859-1">
|
||||
<META content=3D"MSHTML 6.00.6000.16525" name=3DGENERATOR>
|
||||
<STYLE></STYLE>
|
||||
</HEAD>
|
||||
<BODY bgColor=3D#ffffff>
|
||||
<DIV><FONT face=3DArial size=3D2>Hello</FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG>This is an outlook=20
|
||||
test</STRONG></FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG></STRONG></FONT> </DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG>So there.</STRONG></FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
|
||||
<DIV><FONT face=3DArial size=3D2>Me.</FONT></DIV></BODY></HTML>
|
||||
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850--
|
||||
|
||||
|
||||
Return-Path: <mikel.other@baci>
|
||||
Received: from some.isp.com by baci with ESMTP id 632BD5758 for <mikel.lindsaar@baci>; Sun, 21 Oct 2007 19:38:21 +1000
|
||||
Date: Sun, 21 Oct 2007 19:38:13 +1000
|
||||
From: Mikel Lindsaar <mikel.other@baci>
|
||||
Reply-To: Mikel Lindsaar <mikel.other@baci>
|
||||
To: mikel.lindsaar@baci
|
||||
Message-Id: <009601c813c6$19df3510$0437d30a@mikel091a>
|
||||
Subject: Testing outlook
|
||||
Mime-Version: 1.0
|
||||
Content-Type: multipart/alternative; boundary=----=_NextPart_000_0093_01C81419.EB75E850
|
||||
Delivered-To: mikel.lindsaar@baci
|
||||
X-Mimeole: Produced By Microsoft MimeOLE V6.00.2900.3138
|
||||
X-Msmail-Priority: Normal
|
||||
|
||||
This is a multi-part message in MIME format.
|
||||
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850
|
||||
Content-Type: text/plain; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: Quoted-printable
|
||||
|
||||
Hello
|
||||
This is an outlook test
|
||||
|
||||
So there.
|
||||
|
||||
Me.
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850
|
||||
Content-Type: text/html; charset=iso-8859-1
|
||||
Content-Transfer-Encoding: Quoted-printable
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML><HEAD>
|
||||
<META http-equiv=3DContent-Type content=3D"text/html; =
|
||||
charset=3Diso-8859-1">
|
||||
<META content=3D"MSHTML 6.00.6000.16525" name=3DGENERATOR>
|
||||
<STYLE></STYLE>
|
||||
</HEAD>
|
||||
<BODY bgColor=3D#ffffff>
|
||||
<DIV><FONT face=3DArial size=3D2>Hello</FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG>This is an outlook=20
|
||||
test</STRONG></FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG></STRONG></FONT> </DIV>
|
||||
<DIV><FONT face=3DArial size=3D2><STRONG>So there.</STRONG></FONT></DIV>
|
||||
<DIV><FONT face=3DArial size=3D2></FONT> </DIV>
|
||||
<DIV><FONT face=3DArial size=3D2>Me.</FONT></DIV></BODY></HTML>
|
||||
|
||||
|
||||
------=_NextPart_000_0093_01C81419.EB75E850--
|
||||
|
||||
|
@ -1,100 +0,0 @@
|
||||
From jamis@37signals.com Thu Feb 22 11:20:31 2007
|
||||
Mime-Version: 1.0 (Apple Message framework v752.3)
|
||||
Message-Id: <2CCE0408-10C7-4045-9B16-A1C11C31469B@37signals.com>
|
||||
Content-Type: multipart/signed;
|
||||
micalg=sha1;
|
||||
boundary=Apple-Mail-42-587703407;
|
||||
protocol="application/pkcs7-signature"
|
||||
To: Jamis Buck <jamis@jamisbuck.org>
|
||||
Subject: Testing attachments
|
||||
From: Jamis Buck <jamis@37signals.com>
|
||||
Date: Thu, 22 Feb 2007 11:20:31 -0700
|
||||
|
||||
|
||||
--Apple-Mail-42-587703407
|
||||
Content-Type: multipart/mixed;
|
||||
boundary=Apple-Mail-41-587703287
|
||||
|
||||
|
||||
--Apple-Mail-41-587703287
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Content-Type: text/plain;
|
||||
charset=US-ASCII;
|
||||
format=flowed
|
||||
|
||||
Here is a test of an attachment via email.
|
||||
|
||||
- Jamis
|
||||
|
||||
|
||||
--Apple-Mail-41-587703287
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Type: image/png;
|
||||
x-unix-mode=0644;
|
||||
name=byo-ror-cover.png
|
||||
Content-Disposition: inline;
|
||||
filename=truncated.png
|
||||
|
||||
iVBORw0KGgoAAAANSUhEUgAAAKUAAADXCAYAAAB7wZEQAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz
|
||||
AAALEgAACxIB0t1+/AAAABd0RVh0Q3JlYXRpb24gVGltZQAxLzI1LzIwMDeD9CJVAAAAGHRFWHRT
|
||||
b2Z0d2FyZQBBZG9iZSBGaXJld29ya3NPsx9OAAAyBWlUWHRYTUw6Y29tLmFkb2JlLnhtcDw/eHBh
|
||||
Y2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+Cjx4OnhtcG1l
|
||||
dGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDQuMS1j
|
||||
MDIwIDEuMjU1NzE2LCBUdWUgT2N0IDEwIDIwMDYgMjM6MTY6MzQiPgogICA8cmRmOlJERiB4bWxu
|
||||
czpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAg
|
||||
ICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4YXA9Imh0
|
||||
dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iPgogICAgICAgICA8eGFwOkNyZWF0b3JUb29sPkFk
|
||||
b2JlIEZpcmV3b3JrcyBDUzM8L3hhcDpDcmVhdG9yVG9vbD4KICAgICAgICAgPHhhcDpDcmVhdGVE
|
||||
YXRlPjIwMDctMDEtMjVUMDU6Mjg6MjFaPC94YXA6Q3JlYXRlRGF0ZT4KICAgICAgICAgPHhhcDpN
|
||||
b2RpZnlEYXRlPjIwMDctMDEtMjVUMDU6Mjg6MjFaPC94YXA6TW9kaWZ5RGF0ZT4KICAgICAgPC9y
|
||||
ZGY6RGVzY3JpcHRpb24+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAg
|
||||
ICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+CiAgICAg
|
||||
ICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgIDwvcmRmOkRlc2NyaXB0
|
||||
hhojpmnJMfaYFmSkXWg5PGCmHXVj/c9At0hSK2xGdd8F3muk0VFjb4f5Ue0ksQ8qAcq0delaXhdb
|
||||
DjKNnF+3B3t9kObZYmk7AZgWYqO9anpR3wpM9sQ5XslB9a+kWyTtNb0fOmudzGHfPFBQDKesyycm
|
||||
DBL7Cw5bXjIEuci+SSOm/LYnXDZu6iuPEj8lYBb+OU8xx1f9m+e5rhJiYKqjo5vHfiZp+VUkW9xc
|
||||
Ufd6JHNWc47PkQqb9ie3SLEZB/ZqyAssiqURY+G35iOMZUrHbasHnb80QAPv9FHtAbJIyro7bi5b
|
||||
ai2TEAKen5+LJNWrglZjm3UbZvt7KryA2J5b5J1jZF8kL6GzvG1Zqx54Y1y7J7n20wMOt9frG2sW
|
||||
uwGP07kNz3732vf6bfvAvLldfS+9fts2euXY37D+R29FGZdlnhzV4TTFmPJduBP2RbNNua4rTqcT
|
||||
Qt7Xy1KUB0AHSdP5AZQYvHZg7WD1XvYeMO1A9HhZPqMX5KXbMBrn2efxns/ee21674efxz4Tp/fq
|
||||
2HZ648dgYaC1i3Vq1IbNPq3PvDTPezY9FaRISjvnzWqdgcWN8EJgjnNq+Z7ktOm9l2Nfth28EZi4
|
||||
bG/we5JwxM+Tql47/D/X6b38I8/RyxvxPJrX6zvQbo3h9jyJx+C0ALX327QETHl5eYlaYCT5rPTb
|
||||
+5/rAq26t3lKIxV/p88hq6ptngdgCzoPjJqndiLfc/6y5A14WeDFGNPct4iUsJBV2bYzLEV7m83s
|
||||
6Rp63VPhHKC/g/LzaU9qexJRr56043JWinqAtfZqsSm1sjoznthl54dtCqv+uL4nIY+oYWuc3+nH
|
||||
kGfn8b0HQpvOYLQAZUDanbJs3jQhITZEgdarZK+cO6ySlL13rut5nFaN23s7u3Snz6eRPTkCoc2/
|
||||
Vp1zHfZVFpZ87FiMVLV1iqyK5rlzfji2GzjfDsodlD+Weo5UD4h6PwKqzQMqID0tq2VjjFVSMpis
|
||||
ZLRAs7sePZBZAHI+gIanB8I7MD+femAceeUe2Kxa5jS950kZ1p5eNEdeX1+jFmSpZ+1EdWCsDcne
|
||||
NPNgUHNw3aYpnzv9PGTX0uo94EtN9qq1rOdxe3kc79T8ukeHJJ8Fnxej6qlylbLLsjQLOy6Xy2a1
|
||||
kefs/N+nM7+S7IG5/E5Yc7F003pWErLjbH0O5cGadiMptSB/DZ5U5DI9yeg5MFYyMj8lC/Y7/Xjq
|
||||
OZlWcnpg9aQfXz2HRq+Wn5xOp6gN8tWq8R44e2pfyzLYemEgprst+XXk2Zj2nXlbsG05BprndTMv
|
||||
C3QRaXczshhVsHnMgfYn80Y2g5JureA6wBasPeP7LkE/jvZMJAaf/g/U2RelHsisvan5FqweIAHg
|
||||
Pwc7L68GxvVDAAAAAElFTkSuQmCC
|
||||
|
||||
--Apple-Mail-41-587703287--
|
||||
|
||||
--Apple-Mail-42-587703407
|
||||
Content-Transfer-Encoding: base64
|
||||
Content-Type: application/pkcs7-signature;
|
||||
name=smime.p7s
|
||||
Content-Disposition: attachment;
|
||||
filename=smime.p7s
|
||||
|
||||
MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIGJzCCAuAw
|
||||
ggJJoAMCAQICEFjnFNYXwDEZRWY5EkfzopUwDQYJKoZIhvcNAQEFBQAwYjELMAkGA1UEBhMCWkEx
|
||||
JTAjBgNVBAoTHFRoYXd0ZSBDb25zdWx0aW5nIChQdHkpIEx0ZC4xLDAqBgNVBAMTI1RoYXd0ZSBQ
|
||||
ZXJzb25hbCBGcmVlbWFpbCBJc3N1aW5nIENBMB4XDTA2MDkxMjE3MDExMloXDTA3MDkxMjE3MDEx
|
||||
MlowRTEfMB0GA1UEAxMWVGhhd3RlIEZyZWVtYWlsIE1lbWJlcjEiMCAGCSqGSIb3DQEJARYTamFt
|
||||
aXNAMzdzaWduYWxzLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAO2A9JeOFIFJ
|
||||
G6z8pTcAldrZ2nMe+Xb1tNrbHgoVzN/QhHXM4qst2Ml93cmFLjMmwG7P9RJeU4oNx+jTqVoBB7NV
|
||||
Ne1/o56Do0KhfMZ9iUDQdPLbkZMq4EEpFMdm6PyM3muRKwPhj66iAWe/osCb8DowUK2f66vaRx0Z
|
||||
Y0MQHIIrXE02Ta4IfAhIfPqBLkZ4WgTYBHN9vMdYea1jF0GO4gqGk1wqwb3yxv2QMYMbwJ6SI+k/
|
||||
ZjkSR/OilTCBhwYLKoZIhvcNAQkQAgsxeKB2MGIxCzAJBgNVBAYTAlpBMSUwIwYDVQQKExxUaGF3
|
||||
dGUgQ29uc3VsdGluZyAoUHR5KSBMdGQuMSwwKgYDVQQDEyNUaGF3dGUgUGVyc29uYWwgRnJlZW1h
|
||||
aWwgSXNzdWluZyBDQQIQWOcU1hfAMRlFZjkSR/OilTANBgkqhkiG9w0BAQEFAASCAQCfwQiC3v6/
|
||||
yleRDGv3bJ4nQYQ+c3mz3+mn3Xi6uU35n3piwxZZaWRdmLyiXPvU+QReHpSf3l2qsEZM3sdE0XF9
|
||||
eRul/+QTFJcDNXOEAxG1zC2Gpz+6c6RrX4Ou12Pwkp+pNrZWTSY/mZgdqcArupOBcZi7qBjoWcy5
|
||||
wb54dfvSSjrjmqLbkH/E8ww/6gGQuU/xXpAUZgUrTmQHrNKeIdSh5oDkOxFaFWvnmb8Z/2ixKqW/
|
||||
Ux6WqamyvBtTs/5YBEtnpZOk+uVoscYEUBhU+DVJ2OSvTdXSivMtBdXmGTsG22k+P1NGUHi/A7ev
|
||||
xPaO0uk4V8xyjNlN4HPuGpkrlXwPAAAAAAAA
|
||||
|
||||
--Apple-Mail-42-587703407--
|
@ -1,14 +0,0 @@
|
||||
From jamis@37signals.com Mon May 2 16:07:05 2005
|
||||
Mime-Version: 1.0 (Apple Message framework v622)
|
||||
Content-Transfer-Encoding: base64
|
||||
Message-Id: <d3b8cf8e49f04480850c28713a1f473e@37signals.com>
|
||||
Content-Type: text/plain;
|
||||
charset=EUC-KR;
|
||||
format=flowed
|
||||
To: jamis@37signals.com
|
||||
From: Jamis Buck <jamis@37signals.com>
|
||||
Subject: Re: Test: =?UTF-8?B?Iua8ouWtlyI=?= mid =?UTF-8?B?Iua8ouWtlyI=?= tail
|
||||
Date: Mon, 2 May 2005 16:07:05 -0600
|
||||
|
||||
tOu6zrrQwMcguLbC+bChwfa3ziwgv+y4rrTCIMfPs6q01MC7ILnPvcC0z7TZLg0KDQrBpiDAzLin
|
||||
wLogSmFtaXPA1LTPtNku
|
@ -1 +1 @@
|
||||
Hey Ho, <%= render :partial => "subtemplate" %>
|
||||
Hey Ho, <%= render partial: "subtemplate" %>
|
@ -24,10 +24,13 @@ def set_logger(logger)
|
||||
def test_deliver_is_notified
|
||||
BaseMailer.welcome.deliver
|
||||
wait
|
||||
|
||||
assert_equal(1, @logger.logged(:info).size)
|
||||
assert_match(/Sent mail to system@test.lindsaar.net/, @logger.logged(:info).first)
|
||||
assert_equal(1, @logger.logged(:debug).size)
|
||||
assert_match(/Welcome/, @logger.logged(:debug).first)
|
||||
|
||||
assert_equal(2, @logger.logged(:debug).size)
|
||||
assert_match(/BaseMailer#welcome: processed outbound mail in [\d.]+ms/, @logger.logged(:debug).first)
|
||||
assert_match(/Welcome/, @logger.logged(:debug).second)
|
||||
end
|
||||
|
||||
def test_receive_is_notified
|
||||
@ -39,4 +42,4 @@ def test_receive_is_notified
|
||||
assert_equal(1, @logger.logged(:debug).size)
|
||||
assert_match(/Jamis/, @logger.logged(:debug).first)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -120,7 +120,7 @@ def without_mail_call
|
||||
end
|
||||
|
||||
def with_nil_as_return_value
|
||||
mail(:template_name => "welcome")
|
||||
mail(template_name: "welcome")
|
||||
nil
|
||||
end
|
||||
|
||||
|
@ -1,7 +1,126 @@
|
||||
* Introduce `BasicRendering` which is the most basic rendering implementation. It
|
||||
allows to `render :text` and `render :nothing` without depending on Action View.
|
||||
* Fix formatting for `rake routes` when a section is shorter than a header.
|
||||
|
||||
*Łukasz Strzałkowski*
|
||||
*Sıtkı Bağdat*
|
||||
|
||||
* Take a hash with options inside array in `#url_for`.
|
||||
|
||||
Example:
|
||||
|
||||
url_for [:new, :admin, :post, { param: 'value' }]
|
||||
# => http://example.com/admin/posts/new?param=value
|
||||
|
||||
*Andrey Ognevsky*
|
||||
|
||||
* Add `session#fetch` method
|
||||
|
||||
fetch behaves similarly to [Hash#fetch](http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-fetch),
|
||||
with the exception that the returned value is always saved into the session.
|
||||
|
||||
It returns a value from the hash for the given key.
|
||||
If the key can’t be found, there are several options:
|
||||
|
||||
* With no other arguments, it will raise an KeyError exception.
|
||||
* If a default value is given, then that will be returned.
|
||||
* If the optional code block is specified, then that will be run and its result returned.
|
||||
|
||||
*Damien Mathieu*
|
||||
|
||||
* Don't let strong parameters mutate the given hash via `fetch`
|
||||
|
||||
Create a new instance if the given parameter is a `Hash` instead of
|
||||
passing it to the `convert_hashes_to_parameters` method since it is
|
||||
overriding its default value.
|
||||
|
||||
*Brendon Murphy*, *Doug Cole*
|
||||
|
||||
* Add `params` option to `button_to` form helper, which renders the given hash
|
||||
as hidden form fields.
|
||||
|
||||
*Andy Waite*
|
||||
|
||||
* Make assets helpers work in the controllers like it works in the views.
|
||||
|
||||
Example:
|
||||
|
||||
# config/application.rb
|
||||
config.asset_host = 'http://mycdn.com'
|
||||
|
||||
ActionController::Base.helpers.asset_path('fallback.png')
|
||||
# => http://mycdn.com/assets/fallback.png
|
||||
|
||||
Fixes #10051.
|
||||
|
||||
*Tima Maslyuchenko*
|
||||
|
||||
* Respect `SCRIPT_NAME` when using `redirect` with a relative path
|
||||
|
||||
Example:
|
||||
|
||||
# application routes.rb
|
||||
mount BlogEngine => '/blog'
|
||||
|
||||
# engine routes.rb
|
||||
get '/admin' => redirect('admin/dashboard')
|
||||
|
||||
This now redirects to the path `/blog/admin/dashboard`, whereas before it would've
|
||||
generated an invalid url because there would be no slash between the host name and
|
||||
the path. It also allows redirects to work where the application is deployed to a
|
||||
subdirectory of a website.
|
||||
|
||||
Fixes #7977.
|
||||
|
||||
*Andrew White*
|
||||
|
||||
* Fixing repond_with working directly on the options hash
|
||||
This fixes an issue where the respond_with worked directly with the given
|
||||
options hash, so that if a user relied on it after calling respond_with,
|
||||
the hash wouldn't be the same.
|
||||
|
||||
Fixes #12029.
|
||||
|
||||
*bluehotdog*
|
||||
|
||||
* Fix `ActionDispatch::RemoteIp::GetIp#calculate_ip` to only check for spoofing
|
||||
attacks if both `HTTP_CLIENT_IP` and `HTTP_X_FORWARDED_FOR` are set.
|
||||
|
||||
Fixes #10844.
|
||||
|
||||
*Tamir Duberstein*
|
||||
|
||||
* Strong parameters should permit nested number as key.
|
||||
|
||||
Fixes #12293.
|
||||
|
||||
*kennyj*
|
||||
|
||||
* Fix regex used to detect URI schemes in `redirect_to` to be consistent with
|
||||
RFC 3986.
|
||||
|
||||
*Derek Prior*
|
||||
|
||||
* Fix incorrect `assert_redirected_to` failure message for protocol-relative
|
||||
URLs.
|
||||
|
||||
*Derek Prior*
|
||||
|
||||
* Fix an issue where router can't recognize downcased url encoding path.
|
||||
|
||||
Fixes #12269.
|
||||
|
||||
*kennyj*
|
||||
|
||||
* Fix custom flash type definition. Misusage of the `_flash_types` class variable
|
||||
caused an error when reloading controllers with custom flash types.
|
||||
|
||||
Fixes #12057.
|
||||
|
||||
*Ricardo de Cillo*
|
||||
|
||||
* Do not break params filtering on `nil` values.
|
||||
|
||||
Fixes #12149.
|
||||
|
||||
*Vasiliy Ermolovich*
|
||||
|
||||
* Separate Action View completely from Action Pack.
|
||||
|
||||
@ -14,21 +133,21 @@
|
||||
* Fix an issue where :if and :unless controller action procs were being run
|
||||
before checking for the correct action in the :only and :unless options.
|
||||
|
||||
Fixes #11799
|
||||
Fixes #11799.
|
||||
|
||||
*Nicholas Jakobsen*
|
||||
|
||||
* Fix an issue where `assert_dom_equal` and `assert_dom_not_equal` were
|
||||
ignoring the passed failure message argument.
|
||||
|
||||
Fixes #11751
|
||||
Fixes #11751.
|
||||
|
||||
*Ryan McGeary*
|
||||
|
||||
* Allow REMOTE_ADDR, HTTP_HOST and HTTP_USER_AGENT to be overridden from
|
||||
the environment passed into `ActionDispatch::TestRequest.new`.
|
||||
|
||||
Fixes #11590
|
||||
Fixes #11590.
|
||||
|
||||
*Andrew White*
|
||||
|
||||
@ -43,7 +162,7 @@
|
||||
* Skip routes pointing to a redirect or mounted application when generating urls
|
||||
using an options hash as they aren't relevant and generate incorrect urls.
|
||||
|
||||
Fixes #8018
|
||||
Fixes #8018.
|
||||
|
||||
*Andrew White*
|
||||
|
||||
@ -61,7 +180,7 @@
|
||||
* Fix `ActionDispatch::ParamsParser#parse_formatted_parameters` to rewind body input stream on
|
||||
parsing json params.
|
||||
|
||||
Fixes #11345
|
||||
Fixes #11345.
|
||||
|
||||
*Yuri Bol*, *Paul Nikitochkin*
|
||||
|
||||
@ -94,7 +213,7 @@
|
||||
was setting `request.formats` with an array containing a `nil` value, which
|
||||
raised an error when setting the controller formats.
|
||||
|
||||
Fixes #10965
|
||||
Fixes #10965.
|
||||
|
||||
*Becker*
|
||||
|
||||
@ -103,15 +222,17 @@
|
||||
no `:to` present in the options hash so should only affect routes using the
|
||||
shorthand syntax (i.e. endpoint is inferred from the path).
|
||||
|
||||
Fixes #9856
|
||||
Fixes #9856.
|
||||
|
||||
*Yves Senn*, *Andrew White*
|
||||
|
||||
* ActionView extracted from ActionPack
|
||||
* ActionView extracted from ActionPack.
|
||||
|
||||
*Piotr Sarnacki*, *Łukasz Strzałkowski*
|
||||
|
||||
* Fix removing trailing slash for mounted apps #3215
|
||||
* Fix removing trailing slash for mounted apps.
|
||||
|
||||
Fixes #3215.
|
||||
|
||||
*Piotr Sarnacki*
|
||||
|
||||
|
@ -21,10 +21,9 @@
|
||||
|
||||
s.add_dependency 'activesupport', version
|
||||
|
||||
s.add_dependency 'rack', '~> 1.5.2'
|
||||
s.add_dependency 'rack-test', '~> 0.6.2'
|
||||
s.add_dependency 'rack', '~> 1.5.2'
|
||||
s.add_dependency 'rack-test', '~> 0.6.2'
|
||||
|
||||
s.add_development_dependency 'actionview', version
|
||||
s.add_development_dependency 'activemodel', version
|
||||
s.add_development_dependency 'tzinfo', '~> 0.3.37'
|
||||
s.add_development_dependency 'actionview', version
|
||||
s.add_development_dependency 'activemodel', version
|
||||
end
|
||||
|
@ -114,11 +114,6 @@ def method_added(name)
|
||||
end
|
||||
end
|
||||
|
||||
# Define some internal variables that should not be propagated to the view.
|
||||
def self.default_protected_instance_vars
|
||||
[]
|
||||
end
|
||||
|
||||
abstract!
|
||||
|
||||
# Calls the action going through the entire action dispatch stack.
|
||||
|
@ -1,5 +1,6 @@
|
||||
require 'active_support/concern'
|
||||
require 'active_support/core_ext/class/attribute'
|
||||
require 'set'
|
||||
|
||||
module AbstractController
|
||||
class DoubleRenderError < Error
|
||||
@ -13,8 +14,14 @@ def initialize(message = nil)
|
||||
module Rendering
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.default_protected_instance_vars
|
||||
super.concat [:@_action_name, :@_response_body, :@_formats, :@_prefixes, :@_config]
|
||||
# Normalize arguments, options and then delegates render_to_body and
|
||||
# sticks the result in self.response_body.
|
||||
# :api: public
|
||||
def render(*args, &block)
|
||||
options = _normalize_render(*args, &block)
|
||||
self.response_body = render_to_body(options)
|
||||
_process_format(rendered_format)
|
||||
self.response_body
|
||||
end
|
||||
|
||||
# Raw rendering of a template to a string.
|
||||
@ -29,40 +36,49 @@ def self.default_protected_instance_vars
|
||||
# overridden in order to still return a string.
|
||||
# :api: plugin
|
||||
def render_to_string(*args, &block)
|
||||
options = _normalize_render(*args, &block)
|
||||
render_to_body(options)
|
||||
end
|
||||
|
||||
# Raw rendering of a template.
|
||||
# :api: plugin
|
||||
# Performs the actual template rendering.
|
||||
# :api: public
|
||||
def render_to_body(options = {})
|
||||
end
|
||||
|
||||
# Normalize arguments, options and then delegates render_to_body and
|
||||
# sticks the result in self.response_body.
|
||||
# :api: public
|
||||
def render(*args, &block)
|
||||
end
|
||||
|
||||
# Return Content-Type of rendered content
|
||||
# Returns Content-Type of rendered content
|
||||
# :api: public
|
||||
def rendered_format
|
||||
Mime::TEXT
|
||||
end
|
||||
|
||||
DEFAULT_PROTECTED_INSTANCE_VARIABLES = Set.new %w(
|
||||
@_action_name @_response_body @_formats @_prefixes @_config
|
||||
@_view_context_class @_view_renderer @_lookup_context
|
||||
@_routes @_db_runtime
|
||||
).map(&:to_sym)
|
||||
|
||||
# This method should return a hash with assigns.
|
||||
# You can overwrite this configuration per controller.
|
||||
# :api: public
|
||||
def view_assigns
|
||||
hash = {}
|
||||
(instance_variables - self.class.default_protected_instance_vars).each do |name|
|
||||
hash[name[1..-1]] = instance_variable_get(name)
|
||||
end
|
||||
hash
|
||||
protected_vars = _protected_ivars
|
||||
variables = instance_variables
|
||||
|
||||
variables.reject! { |s| protected_vars.include? s }
|
||||
variables.each_with_object({}) { |name, hash|
|
||||
hash[name.slice(1, name.length)] = instance_variable_get(name)
|
||||
}
|
||||
end
|
||||
|
||||
# Normalize args by converting render "foo" to render :action => "foo" and
|
||||
# render "foo/bar" to render :file => "foo/bar".
|
||||
# :api: plugin
|
||||
def _normalize_args(action=nil, options={})
|
||||
options
|
||||
if action.is_a? Hash
|
||||
action
|
||||
else
|
||||
options
|
||||
end
|
||||
end
|
||||
|
||||
# Normalize options.
|
||||
@ -76,5 +92,22 @@ def _normalize_options(options)
|
||||
def _process_options(options)
|
||||
options
|
||||
end
|
||||
|
||||
# Process the rendered format.
|
||||
# :api: private
|
||||
def _process_format(format)
|
||||
end
|
||||
|
||||
# Normalize args and options.
|
||||
# :api: private
|
||||
def _normalize_render(*args, &block)
|
||||
options = _normalize_args(*args, &block)
|
||||
_normalize_options(options)
|
||||
options
|
||||
end
|
||||
|
||||
def _protected_ivars # :nodoc:
|
||||
DEFAULT_PROTECTED_INSTANCE_VARIABLES
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -13,7 +13,6 @@ module ActionController
|
||||
autoload :Middleware
|
||||
|
||||
autoload_under "metal" do
|
||||
autoload :BasicRendering, 'action_controller/metal/rendering'
|
||||
autoload :Compatibility
|
||||
autoload :ConditionalGet
|
||||
autoload :Cookies
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
module ActionController
|
||||
# The <tt>metal</tt> anonymous class was introduced to solve issue with including modules in <tt>ActionController::Base</tt>.
|
||||
# Modules needes to be included in particluar order. First wee need to have <tt>AbstractController::Rendering</tt> included,
|
||||
# Modules needs to be included in particluar order. First we need to have <tt>AbstractController::Rendering</tt> included,
|
||||
# next we should include actuall implementation which would be for example <tt>ActionView::Rendering</tt> and after that
|
||||
# <tt>ActionController::Rendering</tt>. This order must be preserved and as we want to have middle module included dynamicaly
|
||||
# <tt>metal</tt> class was introduced. It has <tt>AbstractController::Rendering</tt> included and is parent class of
|
||||
@ -14,7 +14,6 @@ module ActionController
|
||||
#
|
||||
metal = Class.new(Metal) do
|
||||
include AbstractController::Rendering
|
||||
include ActionController::BasicRendering
|
||||
end
|
||||
|
||||
# Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
|
||||
@ -74,7 +73,7 @@ module ActionController
|
||||
# <input type="text" name="post[address]" value="hyacintvej">
|
||||
#
|
||||
# A request stemming from a form holding these inputs will include <tt>{ "post" => { "name" => "david", "address" => "hyacintvej" } }</tt>.
|
||||
# If the address input had been named "post[address][street]", the params would have included
|
||||
# If the address input had been named <tt>post[address][street]</tt>, the params would have included
|
||||
# <tt>{ "post" => { "address" => { "street" => "hyacintvej" } } }</tt>. There's no limit to the depth of the nesting.
|
||||
#
|
||||
# == Sessions
|
||||
@ -261,11 +260,17 @@ def self.without_modules(*modules)
|
||||
include mod
|
||||
end
|
||||
|
||||
def self.default_protected_instance_vars
|
||||
super.concat [
|
||||
:@_status, :@_headers, :@_params, :@_env, :@_response, :@_request,
|
||||
:@_view_runtime, :@_stream, :@_url_options, :@_action_has_layout
|
||||
]
|
||||
# Define some internal variables that should not be propagated to the view.
|
||||
PROTECTED_IVARS = AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [
|
||||
:@_status, :@_headers, :@_params, :@_env, :@_response, :@_request,
|
||||
:@_view_runtime, :@_stream, :@_url_options, :@_action_has_layout ]
|
||||
|
||||
def _protected_ivars # :nodoc:
|
||||
PROTECTED_IVARS
|
||||
end
|
||||
|
||||
def self.protected_instance_variables
|
||||
PROTECTED_IVARS
|
||||
end
|
||||
|
||||
ActiveSupport.run_load_hooks(:action_controller, self)
|
||||
|
@ -37,7 +37,7 @@ def add_flash_types(*types)
|
||||
end
|
||||
helper_method type
|
||||
|
||||
_flash_types << type
|
||||
self._flash_types += [type]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -48,7 +48,7 @@ module ClassMethods
|
||||
# You can pass any of the following options to affect the redirect status and response
|
||||
# * <tt>status</tt> - Redirect with a custom status (default is 301 Moved Permanently)
|
||||
# * <tt>flash</tt> - Set a flash message when redirecting
|
||||
# * <tt>alert</tt> - Set a alert message when redirecting
|
||||
# * <tt>alert</tt> - Set an alert message when redirecting
|
||||
# * <tt>notice</tt> - Set a notice message when redirecting
|
||||
#
|
||||
# ==== Action Options
|
||||
|
@ -1,8 +1,6 @@
|
||||
module ActionController
|
||||
module Head
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# Return a response that has no content (merely headers). The options
|
||||
# Returns a response that has no content (merely headers). The options
|
||||
# argument is interpreted to be a hash of header names and values.
|
||||
# This allows you to easily return a response that consists only of
|
||||
# significant headers:
|
||||
|
@ -73,7 +73,11 @@ def helper_attr(*attrs)
|
||||
|
||||
# Provides a proxy to access helpers methods from outside the view.
|
||||
def helpers
|
||||
@helper_proxy ||= ActionView::Base.new.extend(_helpers)
|
||||
@helper_proxy ||= begin
|
||||
proxy = ActionView::Base.new
|
||||
proxy.config = config.inheritable_copy
|
||||
proxy.extend(_helpers)
|
||||
end
|
||||
end
|
||||
|
||||
# Overwrite modules_for_helpers to accept :all as argument, which loads
|
||||
|
@ -326,6 +326,7 @@ def respond_with(*resources, &block)
|
||||
|
||||
if collector = retrieve_collector_from_mimes(&block)
|
||||
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)
|
||||
end
|
||||
@ -364,9 +365,7 @@ def retrieve_collector_from_mimes(mimes=nil, &block) #:nodoc:
|
||||
format = collector.negotiate_format(request)
|
||||
|
||||
if format
|
||||
self.content_type ||= format.to_s
|
||||
lookup_context.formats = [format.to_sym]
|
||||
lookup_context.rendered_format = lookup_context.formats.first
|
||||
_process_format(format)
|
||||
collector
|
||||
else
|
||||
raise ActionController::UnknownFormat
|
||||
@ -397,10 +396,10 @@ def retrieve_collector_from_mimes(mimes=nil, &block) #:nodoc:
|
||||
# request, with this response then being accessible by calling #response.
|
||||
class Collector
|
||||
include AbstractController::Collector
|
||||
attr_accessor :order, :format
|
||||
attr_accessor :format
|
||||
|
||||
def initialize(mimes)
|
||||
@order, @responses = [], {}
|
||||
@responses = {}
|
||||
mimes.each { |mime| send(mime) }
|
||||
end
|
||||
|
||||
@ -415,7 +414,6 @@ def any(*args, &block)
|
||||
|
||||
def custom(mime_type, &block)
|
||||
mime_type = Mime::Type.lookup(mime_type.to_s) unless mime_type.is_a?(Mime::Type)
|
||||
@order << mime_type
|
||||
@responses[mime_type] ||= block
|
||||
end
|
||||
|
||||
@ -424,7 +422,7 @@ def response
|
||||
end
|
||||
|
||||
def negotiate_format(request)
|
||||
@format = request.negotiate_mime(order)
|
||||
@format = request.negotiate_mime(@responses.keys)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -71,6 +71,26 @@ def redirect_to(options = {}, response_status = {}) #:doc:
|
||||
self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.h(location)}\">redirected</a>.</body></html>"
|
||||
end
|
||||
|
||||
def _compute_redirect_to_location(options) #:nodoc:
|
||||
case options
|
||||
# The scheme name consist of a letter followed by any combination of
|
||||
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
|
||||
# characters; and is terminated by a colon (":").
|
||||
# See http://tools.ietf.org/html/rfc3986#section-3.1
|
||||
# The protocol relative scheme starts with a double slash "//".
|
||||
when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/i
|
||||
options
|
||||
when String
|
||||
request.protocol + request.host_with_port + options
|
||||
when :back
|
||||
request.headers["Referer"] or raise RedirectBackError
|
||||
when Proc
|
||||
_compute_redirect_to_location options.call
|
||||
else
|
||||
url_for(options)
|
||||
end.delete("\0\r\n")
|
||||
end
|
||||
|
||||
private
|
||||
def _extract_redirect_to_status(options, response_status)
|
||||
if options.is_a?(Hash) && options.key?(:status)
|
||||
@ -81,24 +101,5 @@ def _extract_redirect_to_status(options, response_status)
|
||||
302
|
||||
end
|
||||
end
|
||||
|
||||
def _compute_redirect_to_location(options)
|
||||
case options
|
||||
# The scheme name consist of a letter followed by any combination of
|
||||
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
|
||||
# characters; and is terminated by a colon (":").
|
||||
# The protocol relative scheme starts with a double slash "//"
|
||||
when %r{\A(\w[\w+.-]*:|//).*}
|
||||
options
|
||||
when String
|
||||
request.protocol + request.host_with_port + options
|
||||
when :back
|
||||
request.headers["Referer"] or raise RedirectBackError
|
||||
when Proc
|
||||
_compute_redirect_to_location options.call
|
||||
else
|
||||
url_for(options)
|
||||
end.delete("\0\r\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -8,8 +8,7 @@ def self.add_renderer(key, &block)
|
||||
|
||||
class MissingRenderer < LoadError
|
||||
def initialize(format)
|
||||
@format = format
|
||||
super("No renderer defined for format: #{@format}")
|
||||
super "No renderer defined for format: #{format}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,36 +1,4 @@
|
||||
module ActionController
|
||||
# Basic rendering implements the most minimal rendering layer.
|
||||
# It only supports rendering :text and :nothing. Passing any other option will
|
||||
# result in `UnsupportedOperationError` exception. For more functionality like
|
||||
# different formats, layouts etc. you should use `ActionView` gem.
|
||||
module BasicRendering
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# Render text or nothing (empty string) to response_body
|
||||
# :api: public
|
||||
def render(*args, &block)
|
||||
super(*args, &block)
|
||||
opts = args.first
|
||||
if opts.has_key?(:text) && opts[:text].present?
|
||||
self.response_body = opts[:text]
|
||||
elsif opts.has_key?(:nothing) && opts[:nothing]
|
||||
self.response_body = " "
|
||||
else
|
||||
raise UnsupportedOperationError
|
||||
end
|
||||
end
|
||||
|
||||
def rendered_format
|
||||
Mime::TEXT
|
||||
end
|
||||
|
||||
class UnsupportedOperationError < StandardError
|
||||
def initialize
|
||||
super "Unsupported render operation. BasicRendering supports only :text and :nothing options. For more, you need to include ActionView."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Rendering
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
@ -44,27 +12,31 @@ def process_action(*) #:nodoc:
|
||||
def render(*args) #:nodoc:
|
||||
raise ::AbstractController::DoubleRenderError if self.response_body
|
||||
super
|
||||
self.content_type ||= rendered_format.to_s
|
||||
self.response_body
|
||||
end
|
||||
|
||||
# Overwrite render_to_string because body can now be set to a rack body.
|
||||
def render_to_string(*)
|
||||
if self.response_body = super
|
||||
result = super
|
||||
if result.respond_to?(:each)
|
||||
string = ""
|
||||
self.response_body.each { |r| string << r }
|
||||
result.each { |r| string << r }
|
||||
string
|
||||
else
|
||||
result
|
||||
end
|
||||
ensure
|
||||
self.response_body = nil
|
||||
end
|
||||
|
||||
def render_to_body(*)
|
||||
super || " "
|
||||
def render_to_body(options = {})
|
||||
super || options[:text].presence || ' '
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _process_format(format)
|
||||
super
|
||||
self.content_type ||= format.to_s
|
||||
end
|
||||
|
||||
# Normalize arguments by catching blocks and setting them on :update.
|
||||
def _normalize_args(action=nil, options={}, &blk) #:nodoc:
|
||||
options = super
|
||||
|
@ -124,6 +124,9 @@ def initialize(env)
|
||||
@loaded = true
|
||||
end
|
||||
|
||||
# no-op
|
||||
def destroy; end
|
||||
|
||||
def exists?
|
||||
true
|
||||
end
|
||||
|
@ -144,7 +144,7 @@ def initialize(controller, resources, options={})
|
||||
undef_method(:to_json) if method_defined?(:to_json)
|
||||
undef_method(:to_yaml) if method_defined?(:to_yaml)
|
||||
|
||||
# Initializes a new responder an invoke the proper format. If the format is
|
||||
# Initializes a new responder and invokes the proper format. If the format is
|
||||
# not defined, call to_format.
|
||||
#
|
||||
def self.call(*args)
|
||||
|
@ -17,7 +17,7 @@ class ParameterMissing < KeyError
|
||||
|
||||
def initialize(param) # :nodoc:
|
||||
@param = param
|
||||
super("param not found: #{param}")
|
||||
super("param is missing or the value is empty: #{param}")
|
||||
end
|
||||
end
|
||||
|
||||
@ -284,7 +284,14 @@ def [](key)
|
||||
# params.fetch(:none, 'Francesco') # => "Francesco"
|
||||
# params.fetch(:none) { 'Francesco' } # => "Francesco"
|
||||
def fetch(key, *args)
|
||||
convert_hashes_to_parameters(key, super)
|
||||
value = super
|
||||
# Don't rely on +convert_hashes_to_parameters+
|
||||
# so as to not mutate via a +fetch+
|
||||
if value.is_a?(Hash)
|
||||
value = self.class.new(value)
|
||||
value.permit! if permitted?
|
||||
end
|
||||
value
|
||||
rescue KeyError
|
||||
raise ActionController::ParameterMissing.new(key)
|
||||
end
|
||||
@ -334,7 +341,7 @@ def convert_hashes_to_parameters(key, value)
|
||||
def each_element(object)
|
||||
if object.is_a?(Array)
|
||||
object.map { |el| yield el }.compact
|
||||
elsif object.is_a?(Hash) && object.keys.all? { |k| k =~ /\A-?\d+\z/ }
|
||||
elsif fields_for_style?(object)
|
||||
hash = object.class.new
|
||||
object.each { |k,v| hash[k] = yield v }
|
||||
hash
|
||||
@ -343,6 +350,10 @@ def each_element(object)
|
||||
end
|
||||
end
|
||||
|
||||
def fields_for_style?(object)
|
||||
object.is_a?(Hash) && object.all? { |k, v| k =~ /\A-?\d+\z/ && v.is_a?(Hash) }
|
||||
end
|
||||
|
||||
def unpermitted_parameters!(params)
|
||||
unpermitted_keys = unpermitted_keys(params)
|
||||
if unpermitted_keys.any?
|
||||
@ -421,7 +432,7 @@ def hash_filter(params, filter)
|
||||
|
||||
# Slicing filters out non-declared keys.
|
||||
slice(*filter.keys).each do |key, value|
|
||||
return unless value
|
||||
next unless value
|
||||
|
||||
if filter[key] == EMPTY_ARRAY
|
||||
# Declaration { comment_ids: [] }.
|
||||
|
@ -299,17 +299,24 @@ def local?
|
||||
LOCALHOST =~ remote_addr && LOCALHOST =~ remote_ip
|
||||
end
|
||||
|
||||
protected
|
||||
# Extracted into ActionDispatch::Request::Utils.deep_munge, but kept here for backwards compatibility.
|
||||
def deep_munge(hash)
|
||||
ActiveSupport::Deprecation.warn(
|
||||
"This method has been extracted into ActionDispatch::Request::Utils.deep_munge. Please start using that instead."
|
||||
)
|
||||
|
||||
def parse_query(qs)
|
||||
Utils.deep_munge(super)
|
||||
Utils.deep_munge(hash)
|
||||
end
|
||||
|
||||
protected
|
||||
def parse_query(qs)
|
||||
Utils.deep_munge(super)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_method(name)
|
||||
HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
|
||||
name
|
||||
end
|
||||
def check_method(name)
|
||||
HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
|
||||
name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -41,7 +41,7 @@ class Response
|
||||
|
||||
# Get and set headers for this response.
|
||||
attr_accessor :header
|
||||
|
||||
|
||||
alias_method :headers=, :header=
|
||||
alias_method :headers, :header
|
||||
|
||||
@ -181,9 +181,9 @@ def message
|
||||
end
|
||||
alias_method :status_message, :message
|
||||
|
||||
def respond_to?(method)
|
||||
def respond_to?(method, include_private = false)
|
||||
if method.to_s == 'to_path'
|
||||
stream.respond_to?(:to_path)
|
||||
stream.respond_to?(method)
|
||||
else
|
||||
super
|
||||
end
|
||||
|
@ -9,8 +9,8 @@ class TransitionTable # :nodoc:
|
||||
attr_reader :memos
|
||||
|
||||
def initialize
|
||||
@regexp_states = Hash.new { |h,k| h[k] = {} }
|
||||
@string_states = Hash.new { |h,k| h[k] = {} }
|
||||
@regexp_states = {}
|
||||
@string_states = {}
|
||||
@accepting = {}
|
||||
@memos = Hash.new { |h,k| h[k] = [] }
|
||||
end
|
||||
@ -43,9 +43,7 @@ def move(t, a)
|
||||
move_string(t, a).concat(move_regexp(t, a))
|
||||
end
|
||||
|
||||
def to_json
|
||||
require 'json'
|
||||
|
||||
def as_json(options = nil)
|
||||
simple_regexp = Hash.new { |h,k| h[k] = {} }
|
||||
|
||||
@regexp_states.each do |from, hash|
|
||||
@ -54,11 +52,11 @@ def to_json
|
||||
end
|
||||
end
|
||||
|
||||
JSON.dump({
|
||||
{
|
||||
regexp_states: simple_regexp,
|
||||
string_states: @string_states,
|
||||
accepting: @accepting
|
||||
})
|
||||
}
|
||||
end
|
||||
|
||||
def to_svg
|
||||
@ -111,14 +109,8 @@ def visualizer(paths, title = 'FSM')
|
||||
end
|
||||
|
||||
def []=(from, to, sym)
|
||||
case sym
|
||||
when String
|
||||
@string_states[from][sym] = to
|
||||
when Regexp
|
||||
@regexp_states[from][sym] = to
|
||||
else
|
||||
raise ArgumentError, 'unknown symbol: %s' % sym.class
|
||||
end
|
||||
to_mappings = states_hash_for(sym)[from] ||= {}
|
||||
to_mappings[sym] = to
|
||||
end
|
||||
|
||||
def states
|
||||
@ -137,18 +129,35 @@ def transitions
|
||||
|
||||
private
|
||||
|
||||
def states_hash_for(sym)
|
||||
case sym
|
||||
when String
|
||||
@string_states
|
||||
when Regexp
|
||||
@regexp_states
|
||||
else
|
||||
raise ArgumentError, 'unknown symbol: %s' % sym.class
|
||||
end
|
||||
end
|
||||
|
||||
def move_regexp(t, a)
|
||||
return [] if t.empty?
|
||||
|
||||
t.map { |s|
|
||||
@regexp_states[s].map { |re, v| re === a ? v : nil }
|
||||
if states = @regexp_states[s]
|
||||
states.map { |re, v| re === a ? v : nil }
|
||||
end
|
||||
}.flatten.compact.uniq
|
||||
end
|
||||
|
||||
def move_string(t, a)
|
||||
return [] if t.empty?
|
||||
|
||||
t.map { |s| @string_states[s][a] }.compact
|
||||
t.map do |s|
|
||||
if states = @string_states[s]
|
||||
states[a]
|
||||
end
|
||||
end.compact
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -7,15 +7,18 @@ class Utils # :nodoc:
|
||||
# Normalizes URI path.
|
||||
#
|
||||
# Strips off trailing slash and ensures there is a leading slash.
|
||||
# Also converts downcase url encoded string to uppercase.
|
||||
#
|
||||
# normalize_path("/foo") # => "/foo"
|
||||
# normalize_path("/foo/") # => "/foo"
|
||||
# normalize_path("foo") # => "/foo"
|
||||
# normalize_path("") # => "/"
|
||||
# normalize_path("/%ab") # => "/%AB"
|
||||
def self.normalize_path(path)
|
||||
path = "/#{path}"
|
||||
path.squeeze!('/')
|
||||
path.sub!(%r{/+\Z}, '')
|
||||
path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase }
|
||||
path = '/' if path == ''
|
||||
path
|
||||
end
|
||||
@ -35,7 +38,7 @@ module UriEscape # :nodoc:
|
||||
UNSAFE_FRAGMENT = Regexp.new("[^#{safe_fragment}]", false).freeze
|
||||
end
|
||||
|
||||
Parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
|
||||
Parser = URI::Parser.new
|
||||
|
||||
def self.escape_path(path)
|
||||
Parser.escape(path.to_s, UriEscape::UNSAFE_SEGMENT)
|
||||
|
@ -1,9 +1,12 @@
|
||||
# encoding: utf-8
|
||||
|
||||
require 'thread_safe'
|
||||
|
||||
module ActionDispatch
|
||||
module Journey # :nodoc:
|
||||
module Visitors # :nodoc:
|
||||
class Visitor # :nodoc:
|
||||
DISPATCH_CACHE = Hash.new { |h,k|
|
||||
DISPATCH_CACHE = ThreadSafe::Cache.new { |h,k|
|
||||
h[k] = :"visit_#{k}"
|
||||
}
|
||||
|
||||
@ -84,44 +87,43 @@ def visit_GROUP(node)
|
||||
|
||||
# Used for formatting urls (url_for)
|
||||
class Formatter < Visitor # :nodoc:
|
||||
attr_reader :options, :consumed
|
||||
attr_reader :options
|
||||
|
||||
def initialize(options)
|
||||
@options = options
|
||||
@consumed = {}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def visit_GROUP(node)
|
||||
if consumed == options
|
||||
nil
|
||||
else
|
||||
route = visit(node.left)
|
||||
route.include?("\0") ? nil : route
|
||||
def visit(node, optional = false)
|
||||
case node.type
|
||||
when :LITERAL, :SLASH, :DOT
|
||||
node.left
|
||||
when :STAR
|
||||
visit(node.left)
|
||||
when :GROUP
|
||||
visit(node.left, true)
|
||||
when :CAT
|
||||
visit_CAT(node, optional)
|
||||
when :SYMBOL
|
||||
visit_SYMBOL(node)
|
||||
end
|
||||
end
|
||||
|
||||
def terminal(node)
|
||||
node.left
|
||||
end
|
||||
def visit_CAT(node, optional)
|
||||
left = visit(node.left, optional)
|
||||
right = visit(node.right, optional)
|
||||
|
||||
def binary(node)
|
||||
[visit(node.left), visit(node.right)].join
|
||||
end
|
||||
|
||||
def nary(node)
|
||||
node.children.map { |c| visit(c) }.join
|
||||
if optional && !(right && left)
|
||||
""
|
||||
else
|
||||
[left, right].join
|
||||
end
|
||||
end
|
||||
|
||||
def visit_SYMBOL(node)
|
||||
key = node.to_sym
|
||||
|
||||
if value = options[key]
|
||||
consumed[key] = value
|
||||
if value = options[node.to_sym]
|
||||
Router::Utils.escape_path(value)
|
||||
else
|
||||
"\0"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -8,14 +8,14 @@ class Callbacks
|
||||
|
||||
class << self
|
||||
delegate :to_prepare, :to_cleanup, :to => "ActionDispatch::Reloader"
|
||||
end
|
||||
|
||||
def self.before(*args, &block)
|
||||
set_callback(:call, :before, *args, &block)
|
||||
end
|
||||
def before(*args, &block)
|
||||
set_callback(:call, :before, *args, &block)
|
||||
end
|
||||
|
||||
def self.after(*args, &block)
|
||||
set_callback(:call, :after, *args, &block)
|
||||
def after(*args, &block)
|
||||
set_callback(:call, :after, *args, &block)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(app)
|
||||
|
@ -96,7 +96,7 @@ def backtrace_cleaner
|
||||
def source_fragment(path, line)
|
||||
return unless Rails.respond_to?(:root) && Rails.root
|
||||
full_path = Rails.root.join(path)
|
||||
if File.exists?(full_path)
|
||||
if File.exist?(full_path)
|
||||
File.open(full_path, "r") do |file|
|
||||
start = [line - 3, 0].max
|
||||
lines = file.each_line.drop(start).take(6)
|
||||
|
@ -143,7 +143,7 @@ def calculate_ip
|
||||
# proxies with incompatible IP header conventions, and there is no way
|
||||
# for us to determine which header is the right one after the fact.
|
||||
# Since we have no idea, we give up and explode.
|
||||
should_check_ip = @check_ip && client_ips.last
|
||||
should_check_ip = @check_ip && client_ips.last && forwarded_ips.last
|
||||
if should_check_ip && !forwarded_ips.include?(client_ips.last)
|
||||
# We don't know which came from the proxy, and which from the user
|
||||
raise IpSpoofAttackError, "IP spoofing attack?! " +
|
||||
|
@ -29,8 +29,11 @@ def initialize(app, exceptions_app)
|
||||
def call(env)
|
||||
@app.call(env)
|
||||
rescue Exception => exception
|
||||
raise exception if env['action_dispatch.show_exceptions'] == false
|
||||
render_exception(env, exception)
|
||||
if env['action_dispatch.show_exceptions'] == false
|
||||
raise exception
|
||||
else
|
||||
render_exception(env, exception)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -127,6 +127,18 @@ def delete(key)
|
||||
@delegate.delete key.to_s
|
||||
end
|
||||
|
||||
def fetch(key, default=nil)
|
||||
if self.key?(key)
|
||||
self[key]
|
||||
elsif default
|
||||
self[key] = default
|
||||
elsif block_given?
|
||||
self[key] = yield(key)
|
||||
else
|
||||
raise KeyError
|
||||
end
|
||||
end
|
||||
|
||||
def inspect
|
||||
if loaded?
|
||||
super
|
||||
|
@ -179,7 +179,8 @@ def no_routes
|
||||
|
||||
private
|
||||
def draw_section(routes)
|
||||
name_width, verb_width, path_width = widths(routes)
|
||||
header_lengths = ['Prefix', 'Verb', 'URI Pattern'].map(&:length)
|
||||
name_width, verb_width, path_width = widths(routes).zip(header_lengths).map(&:max)
|
||||
|
||||
routes.map do |r|
|
||||
"#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
|
||||
|
@ -147,14 +147,16 @@ def normalize_defaults!
|
||||
@defaults.merge!(options[:defaults]) if options[:defaults]
|
||||
|
||||
options.each do |key, default|
|
||||
next if Regexp === default || IGNORE_OPTIONS.include?(key)
|
||||
@defaults[key] = default
|
||||
unless Regexp === default || IGNORE_OPTIONS.include?(key)
|
||||
@defaults[key] = default
|
||||
end
|
||||
end
|
||||
|
||||
if options[:constraints].is_a?(Hash)
|
||||
options[:constraints].each do |key, default|
|
||||
next unless URL_OPTIONS.include?(key) && (String === default || Fixnum === default)
|
||||
@defaults[key] ||= default
|
||||
if URL_OPTIONS.include?(key) && (String === default || Fixnum === default)
|
||||
@defaults[key] ||= default
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -166,19 +168,21 @@ def normalize_defaults!
|
||||
end
|
||||
|
||||
def normalize_conditions!
|
||||
@conditions.merge!(:path_info => path)
|
||||
@conditions[:path_info] = path
|
||||
|
||||
constraints.each do |key, condition|
|
||||
next if segment_keys.include?(key) || key == :controller
|
||||
@conditions[key] = condition
|
||||
unless segment_keys.include?(key) || key == :controller
|
||||
@conditions[key] = condition
|
||||
end
|
||||
end
|
||||
|
||||
@conditions[:required_defaults] = []
|
||||
required_defaults = []
|
||||
options.each do |key, required_default|
|
||||
next if segment_keys.include?(key) || IGNORE_OPTIONS.include?(key)
|
||||
next if Regexp === required_default
|
||||
@conditions[:required_defaults] << key
|
||||
unless segment_keys.include?(key) || IGNORE_OPTIONS.include?(key) || Regexp === required_default
|
||||
required_defaults << key
|
||||
end
|
||||
end
|
||||
@conditions[:required_defaults] = required_defaults
|
||||
|
||||
via_all = options.delete(:via) if options[:via] == :all
|
||||
|
||||
@ -192,8 +196,7 @@ def normalize_conditions!
|
||||
end
|
||||
|
||||
if via = options[:via]
|
||||
list = Array(via).map { |m| m.to_s.dasherize.upcase }
|
||||
@conditions.merge!(:request_method => list)
|
||||
@conditions[:request_method] = Array(via).map { |m| m.to_s.dasherize.upcase }
|
||||
end
|
||||
end
|
||||
|
||||
@ -226,11 +229,13 @@ def default_controller_and_action
|
||||
action = action.to_s unless action.is_a?(Regexp)
|
||||
|
||||
if controller.blank? && segment_keys.exclude?(:controller)
|
||||
raise ArgumentError, "missing :controller"
|
||||
message = "Missing :controller key on routes definition, please check your routes."
|
||||
raise ArgumentError, message
|
||||
end
|
||||
|
||||
if action.blank? && segment_keys.exclude?(:action)
|
||||
raise ArgumentError, "missing :action"
|
||||
message = "Missing :action key on routes definition, please check your routes."
|
||||
raise ArgumentError, message
|
||||
end
|
||||
|
||||
if controller.is_a?(String) && controller !~ /\A[a-z_0-9\/]*\z/
|
||||
@ -362,8 +367,9 @@ def root(options = {})
|
||||
# # Yes, controller actions are just rack endpoints
|
||||
# match 'photos/:id', to: PhotosController.action(:show)
|
||||
#
|
||||
# Because request various HTTP verbs with a single action has security
|
||||
# implications, is recommendable use HttpHelpers[rdoc-ref:HttpHelpers]
|
||||
# Because requesting various HTTP verbs with a single action has security
|
||||
# implications, you must either specify the actions in
|
||||
# the via options or use one of the HtttpHelpers[rdoc-ref:HttpHelpers]
|
||||
# instead +match+
|
||||
#
|
||||
# === Options
|
||||
@ -383,7 +389,7 @@ def root(options = {})
|
||||
# The namespace for :controller.
|
||||
#
|
||||
# match 'path', to: 'c#a', module: 'sekret', controller: 'posts'
|
||||
# #=> Sekret::PostsController
|
||||
# # => Sekret::PostsController
|
||||
#
|
||||
# See <tt>Scoping#namespace</tt> for its scope equivalent.
|
||||
#
|
||||
@ -432,10 +438,10 @@ def root(options = {})
|
||||
#
|
||||
# match 'json_only', constraints: { format: 'json' }
|
||||
#
|
||||
# class Blacklist
|
||||
# class Whitelist
|
||||
# def matches?(request) request.remote_ip == '1.2.3.4' end
|
||||
# end
|
||||
# match 'path', to: 'c#a', constraints: Blacklist.new
|
||||
# match 'path', to: 'c#a', constraints: Whitelist.new
|
||||
#
|
||||
# See <tt>Scoping#constraints</tt> for more examples with its scope
|
||||
# equivalent.
|
||||
@ -1066,18 +1072,18 @@ def resources_path_names(options)
|
||||
# a singular resource to map /profile (rather than /profile/:id) to
|
||||
# the show action:
|
||||
#
|
||||
# resource :geocoder
|
||||
# resource :profile
|
||||
#
|
||||
# creates six different routes in your application, all mapping to
|
||||
# the +GeoCoders+ controller (note that the controller is named after
|
||||
# the +Profiles+ controller (note that the controller is named after
|
||||
# the plural):
|
||||
#
|
||||
# GET /geocoder/new
|
||||
# POST /geocoder
|
||||
# GET /geocoder
|
||||
# GET /geocoder/edit
|
||||
# PATCH/PUT /geocoder
|
||||
# DELETE /geocoder
|
||||
# GET /profile/new
|
||||
# POST /profile
|
||||
# GET /profile
|
||||
# GET /profile/edit
|
||||
# PATCH/PUT /profile
|
||||
# DELETE /profile
|
||||
#
|
||||
# === Options
|
||||
# Takes same options as +resources+.
|
||||
|
@ -74,6 +74,19 @@ module PolymorphicRoutes
|
||||
# * <tt>:routing_type</tt> - Allowed values are <tt>:path</tt> or <tt>:url</tt>.
|
||||
# Default is <tt>:url</tt>.
|
||||
#
|
||||
# Also includes all the options from <tt>url_for</tt>. These include such
|
||||
# things as <tt>:anchor</tt> or <tt>:trailing_slash</tt>. Example usage
|
||||
# is given below:
|
||||
#
|
||||
# polymorphic_url([blog, post], anchor: 'my_anchor')
|
||||
# # => "http://example.com/blogs/1/posts/1#my_anchor"
|
||||
# polymorphic_url([blog, post], anchor: 'my_anchor', script_name: "/my_app")
|
||||
# # => "http://example.com/my_app/blogs/1/posts/1#my_anchor"
|
||||
#
|
||||
# For all of these options, see the documentation for <tt>url_for</tt>.
|
||||
#
|
||||
# ==== Functionality
|
||||
#
|
||||
# # an Article record
|
||||
# polymorphic_url(record) # same as article_url(record)
|
||||
#
|
||||
|
@ -17,7 +17,7 @@ def initialize(status, block)
|
||||
def call(env)
|
||||
req = Request.new(env)
|
||||
|
||||
# If any of the path parameters has a invalid encoding then
|
||||
# If any of the path parameters has an invalid encoding then
|
||||
# raise since it's likely to trigger errors further on.
|
||||
req.symbolized_path_parameters.each do |key, value|
|
||||
unless value.valid_encoding?
|
||||
@ -30,6 +30,10 @@ def call(env)
|
||||
uri.host ||= req.host
|
||||
uri.port ||= req.port unless req.standard_port?
|
||||
|
||||
if relative_path?(uri.path)
|
||||
uri.path = "#{req.script_name}/#{uri.path}"
|
||||
end
|
||||
|
||||
body = %(<html><body>You are being <a href="#{ERB::Util.h(uri.to_s)}">redirected</a>.</body></html>)
|
||||
|
||||
headers = {
|
||||
@ -48,6 +52,11 @@ def path(params, request)
|
||||
def inspect
|
||||
"redirect(#{status})"
|
||||
end
|
||||
|
||||
private
|
||||
def relative_path?(path)
|
||||
path && !path.empty? && path[0] != '/'
|
||||
end
|
||||
end
|
||||
|
||||
class PathRedirect < Redirect
|
||||
@ -81,6 +90,11 @@ def path(params, request)
|
||||
url_options[:path] = (url_options[:path] % escape_path(params))
|
||||
end
|
||||
|
||||
if relative_path?(url_options[:path])
|
||||
url_options[:path] = "/#{url_options[:path]}"
|
||||
url_options[:script_name] = request.script_name
|
||||
end
|
||||
|
||||
ActionDispatch::Http::URL.url_for url_options
|
||||
end
|
||||
|
||||
@ -104,6 +118,10 @@ module Redirection
|
||||
#
|
||||
# get 'docs/:article', to: redirect('/wiki/%{article}')
|
||||
#
|
||||
# Note that if you return a path without a leading slash then the url is prefixed with the
|
||||
# current SCRIPT_NAME environment variable. This is typically '/' but may be different in
|
||||
# a mounted engine or where the application is deployed to a subdirectory of a website.
|
||||
#
|
||||
# Alternatively you can use one of the other syntaxes:
|
||||
#
|
||||
# The block version of redirect allows for the easy encapsulation of any logic associated with
|
||||
|
@ -28,7 +28,7 @@ def initialize(options={})
|
||||
def call(env)
|
||||
params = env[PARAMETERS_KEY]
|
||||
|
||||
# If any of the path parameters has a invalid encoding then
|
||||
# If any of the path parameters has an invalid encoding then
|
||||
# raise since it's likely to trigger errors further on.
|
||||
params.each do |key, value|
|
||||
next unless value.respond_to?(:valid_encoding?)
|
||||
@ -514,11 +514,12 @@ def initialize(options, recall, set)
|
||||
@recall = recall.dup
|
||||
@set = set
|
||||
|
||||
normalize_recall!
|
||||
normalize_options!
|
||||
normalize_controller_action_id!
|
||||
use_relative_controller!
|
||||
normalize_controller!
|
||||
handle_nil_action!
|
||||
normalize_action!
|
||||
end
|
||||
|
||||
def controller
|
||||
@ -537,6 +538,11 @@ def use_recall_for(key)
|
||||
end
|
||||
end
|
||||
|
||||
# Set 'index' as default action for recall
|
||||
def normalize_recall!
|
||||
@recall[:action] ||= 'index'
|
||||
end
|
||||
|
||||
def normalize_options!
|
||||
# If an explicit :controller was given, always make :action explicit
|
||||
# too, so that action expiry works as expected for things like
|
||||
@ -552,8 +558,8 @@ def normalize_options!
|
||||
options[:controller] = options[:controller].to_s
|
||||
end
|
||||
|
||||
if options[:action]
|
||||
options[:action] = options[:action].to_s
|
||||
if options.key?(:action)
|
||||
options[:action] = (options[:action] || 'index').to_s
|
||||
end
|
||||
end
|
||||
|
||||
@ -563,8 +569,6 @@ def normalize_options!
|
||||
# :controller, :action or :id is not found, don't pull any
|
||||
# more keys from the recall.
|
||||
def normalize_controller_action_id!
|
||||
@recall[:action] ||= 'index' if current_controller
|
||||
|
||||
use_recall_for(:controller) or return
|
||||
use_recall_for(:action) or return
|
||||
use_recall_for(:id)
|
||||
@ -586,13 +590,11 @@ def normalize_controller!
|
||||
@options[:controller] = controller.sub(%r{^/}, '') if controller
|
||||
end
|
||||
|
||||
# This handles the case of action: nil being explicitly passed.
|
||||
# It is identical to action: "index"
|
||||
def handle_nil_action!
|
||||
if options.has_key?(:action) && options[:action].nil?
|
||||
options[:action] = 'index'
|
||||
# Move 'index' action from options to recall
|
||||
def normalize_action!
|
||||
if @options[:action] == 'index'
|
||||
@recall[:action] = @options.delete(:action)
|
||||
end
|
||||
recall[:action] = options.delete(:action) if options[:action] == 'index'
|
||||
end
|
||||
|
||||
# Generates a path from routes, returns [path, params].
|
||||
|
@ -20,7 +20,7 @@ module Routing
|
||||
#
|
||||
# <%= link_to('Click here', controller: 'users',
|
||||
# action: 'new', message: 'Welcome!') %>
|
||||
# # => "/users/new?message=Welcome%21"
|
||||
# # => <a href="/users/new?message=Welcome%21">Click here</a>
|
||||
#
|
||||
# link_to, and all other functions that require URL generation functionality,
|
||||
# actually use ActionController::UrlFor under the hood. And in particular,
|
||||
@ -155,6 +155,8 @@ def url_for(options = nil)
|
||||
_routes.url_for(options.symbolize_keys.reverse_merge!(url_options))
|
||||
when String
|
||||
options
|
||||
when Array
|
||||
polymorphic_url(options, options.extract_options!)
|
||||
else
|
||||
polymorphic_url(options)
|
||||
end
|
||||
|
@ -67,21 +67,11 @@ def parameterize(value)
|
||||
end
|
||||
|
||||
def normalize_argument_to_redirection(fragment)
|
||||
normalized = case fragment
|
||||
when Regexp
|
||||
fragment
|
||||
when %r{^\w[A-Za-z\d+.-]*:.*}
|
||||
fragment
|
||||
when String
|
||||
@request.protocol + @request.host_with_port + fragment
|
||||
when :back
|
||||
raise RedirectBackError unless refer = @request.headers["Referer"]
|
||||
refer
|
||||
else
|
||||
@controller.url_for(fragment)
|
||||
end
|
||||
|
||||
normalized.respond_to?(:delete) ? normalized.delete("\0\r\n") : normalized
|
||||
if Regexp === fragment
|
||||
fragment
|
||||
else
|
||||
@controller._compute_redirect_to_location(fragment)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -242,7 +242,7 @@ def https!(flag = true)
|
||||
@https = flag
|
||||
end
|
||||
|
||||
# Return +true+ if the session is mimicking a secure HTTPS request.
|
||||
# Returns +true+ if the session is mimicking a secure HTTPS request.
|
||||
#
|
||||
# if session.https?
|
||||
# ...
|
||||
|
@ -39,6 +39,8 @@ def redirect_to_named_route() redirect_to route_one_url end
|
||||
|
||||
def redirect_external() redirect_to "http://www.rubyonrails.org"; end
|
||||
|
||||
def redirect_external_protocol_relative() redirect_to "//www.rubyonrails.org"; end
|
||||
|
||||
def response404() head '404 AWOL' end
|
||||
|
||||
def response500() head '500 Sorry' end
|
||||
@ -258,6 +260,19 @@ def test_assert_redirected_to_top_level_named_route_with_same_controller_name_in
|
||||
end
|
||||
end
|
||||
|
||||
def test_assert_redirect_failure_message_with_protocol_relative_url
|
||||
begin
|
||||
process :redirect_external_protocol_relative
|
||||
assert_redirected_to "/foo"
|
||||
rescue ActiveSupport::TestCase::Assertion => ex
|
||||
assert_no_match(
|
||||
/#{request.protocol}#{request.host}\/\/www.rubyonrails.org/,
|
||||
ex.message,
|
||||
'protocol relative url was incorrectly normalized'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def test_template_objects_exist
|
||||
process :assign_this
|
||||
assert !@controller.instance_variable_defined?(:"@hi")
|
||||
@ -309,6 +324,9 @@ def test_redirection_location
|
||||
|
||||
process :redirect_external
|
||||
assert_equal 'http://www.rubyonrails.org', @response.redirect_url
|
||||
|
||||
process :redirect_external_protocol_relative
|
||||
assert_equal '//www.rubyonrails.org', @response.redirect_url
|
||||
end
|
||||
|
||||
def test_no_redirect_url
|
||||
|
@ -20,7 +20,7 @@ def setup
|
||||
@controller = FragmentCachingMetalTestController.new
|
||||
@controller.perform_caching = true
|
||||
@controller.cache_store = @store
|
||||
@params = { controller: 'posts', action: 'index'}
|
||||
@params = { controller: 'posts', action: 'index' }
|
||||
@request = ActionController::TestRequest.new
|
||||
@response = ActionController::TestResponse.new
|
||||
@controller.params = @params
|
||||
@ -40,7 +40,7 @@ class CachingController < ActionController::Base
|
||||
end
|
||||
|
||||
class FragmentCachingTestController < CachingController
|
||||
def some_action; end;
|
||||
def some_action; end
|
||||
end
|
||||
|
||||
class FragmentCachingTest < ActionController::TestCase
|
||||
|
@ -17,7 +17,7 @@ def before_filters
|
||||
def assigns(key = nil)
|
||||
assigns = {}
|
||||
instance_variables.each do |ivar|
|
||||
next if ActionController::Base.default_protected_instance_vars.include?(ivar)
|
||||
next if ActionController::Base.protected_instance_variables.include?(ivar)
|
||||
assigns[ivar[1..-1]] = instance_variable_get(ivar)
|
||||
end
|
||||
|
||||
|
@ -214,6 +214,18 @@ def test_redirect_to_with_adding_flash_types
|
||||
get :redirect_with_foo_flash
|
||||
assert_equal "for great justice", @controller.send(:flash)[:foo]
|
||||
end
|
||||
|
||||
class SubclassesTestController < TestController; end
|
||||
|
||||
def test_add_flash_type_to_subclasses
|
||||
TestController.add_flash_types :foo
|
||||
assert SubclassesTestController._flash_types.include?(:foo)
|
||||
end
|
||||
|
||||
def test_do_not_add_flash_type_to_parent_class
|
||||
SubclassesTestController.add_flash_types :bar
|
||||
assert_not TestController._flash_types.include?(:bar)
|
||||
end
|
||||
end
|
||||
|
||||
class FlashIntegrationTest < ActionDispatch::IntegrationTest
|
||||
|
@ -201,6 +201,12 @@ def test_helper_proxy
|
||||
# fun/pdf_helper.rb
|
||||
assert methods.include?(:foobar)
|
||||
end
|
||||
|
||||
def test_helper_proxy_config
|
||||
AllHelpersController.config.my_var = 'smth'
|
||||
|
||||
assert_equal 'smth', AllHelpersController.helpers.config.my_var
|
||||
end
|
||||
|
||||
private
|
||||
def expected_helper_methods
|
||||
|
@ -21,7 +21,7 @@ def display
|
||||
|
||||
def authenticate
|
||||
authenticate_or_request_with_http_digest("SuperSecret") do |username|
|
||||
# Return the password
|
||||
# Returns the password
|
||||
USERS[username]
|
||||
end
|
||||
end
|
||||
|
@ -65,7 +65,17 @@ def respond; @controller.render :text => "respond #{format}"; 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)
|
||||
@ -145,6 +155,11 @@ def teardown
|
||||
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
|
||||
|
@ -92,7 +92,7 @@ class StreamingTest < Rack::TestCase
|
||||
io.rewind
|
||||
assert_match "(undefined method `invalid!' for nil:NilClass)", io.read
|
||||
ensure
|
||||
ActionController::Base.logger = _old
|
||||
ActionView::Base.logger = _old
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,6 +1,15 @@
|
||||
require 'abstract_unit'
|
||||
|
||||
module RenderText
|
||||
class MinimalController < ActionController::Metal
|
||||
include AbstractController::Rendering
|
||||
include ActionController::Rendering
|
||||
|
||||
def index
|
||||
render text: "Hello World!"
|
||||
end
|
||||
end
|
||||
|
||||
class SimpleController < ActionController::Base
|
||||
self.view_paths = [ActionView::FixtureResolver.new]
|
||||
|
||||
@ -63,6 +72,12 @@ def with_ivar_in_layout
|
||||
end
|
||||
|
||||
class RenderTextTest < Rack::TestCase
|
||||
test "rendering text from a minimal controller" do
|
||||
get "/render_text/minimal/index"
|
||||
assert_body "Hello World!"
|
||||
assert_status 200
|
||||
end
|
||||
|
||||
test "rendering text from an action with default options renders the text with the layout" do
|
||||
with_routing do |set|
|
||||
set.draw { get ':controller', :action => 'index' }
|
||||
|
@ -169,4 +169,19 @@ def assert_filtered_out(params, key)
|
||||
|
||||
assert_filtered_out permitted[:book][:authors_attributes]['-1'], :age_of_death
|
||||
end
|
||||
|
||||
test "nested number as key" do
|
||||
params = ActionController::Parameters.new({
|
||||
product: {
|
||||
properties: {
|
||||
'0' => "prop0",
|
||||
'1' => "prop1"
|
||||
}
|
||||
}
|
||||
})
|
||||
params = params.require(:product).permit(:properties => ["0"])
|
||||
assert_not_nil params[:properties]["0"]
|
||||
assert_nil params[:properties]["1"]
|
||||
assert_equal "prop0", params[:properties]["0"]
|
||||
end
|
||||
end
|
||||
|
@ -107,6 +107,15 @@ def assert_filtered_out(params, key)
|
||||
assert_equal [], permitted[:id]
|
||||
end
|
||||
|
||||
test 'do not break params filtering on nil values' do
|
||||
params = ActionController::Parameters.new(a: 1, b: [1, 2, 3], c: nil)
|
||||
|
||||
permitted = params.permit(:a, c: [], b: [])
|
||||
assert_equal 1, permitted[:a]
|
||||
assert_equal [1, 2, 3], permitted[:b]
|
||||
assert_equal nil, permitted[:c]
|
||||
end
|
||||
|
||||
test 'key to empty array: arrays of permitted scalars pass' do
|
||||
[['foo'], [1], ['foo', 'bar'], [1, 2, 3]].each do |array|
|
||||
params = ActionController::Parameters.new(id: array)
|
||||
@ -138,6 +147,12 @@ def assert_filtered_out(params, key)
|
||||
assert_equal :foo, e.param
|
||||
end
|
||||
|
||||
test "fetch with a default value of a hash does not mutate the object" do
|
||||
params = ActionController::Parameters.new({})
|
||||
params.fetch :foo, {}
|
||||
assert_equal nil, params[:foo]
|
||||
end
|
||||
|
||||
test "fetch doesnt raise ParameterMissing exception if there is a default" do
|
||||
assert_equal "monkey", @params.fetch(:foo, "monkey")
|
||||
assert_equal "monkey", @params.fetch(:foo) { "monkey" }
|
||||
|
@ -78,6 +78,11 @@ def encrypted
|
||||
cookies.encrypted[:foo] = 'bar'
|
||||
render :nothing => true
|
||||
end
|
||||
|
||||
def try_to_reset_session
|
||||
reset_session
|
||||
render :nothing => true
|
||||
end
|
||||
end
|
||||
|
||||
class FreeCookieController < RequestForgeryProtectionControllerUsingResetSession
|
||||
@ -320,6 +325,11 @@ def setup
|
||||
post :encrypted
|
||||
assert_response :ok
|
||||
end
|
||||
|
||||
test 'should allow reset_session' do
|
||||
post :try_to_reset_session
|
||||
assert_response :ok
|
||||
end
|
||||
end
|
||||
|
||||
class RequestForgeryProtectionControllerUsingExceptionTest < ActionController::TestCase
|
||||
|
@ -2,6 +2,7 @@
|
||||
require 'abstract_unit'
|
||||
require 'controller/fake_controllers'
|
||||
require 'active_support/core_ext/object/with_options'
|
||||
require 'active_support/core_ext/object/json'
|
||||
|
||||
class MilestonesController < ActionController::Base
|
||||
def index() head :ok end
|
||||
@ -86,36 +87,36 @@ def setup
|
||||
def test_symbols_with_dashes
|
||||
rs.draw do
|
||||
get '/:artist/:song-omg', :to => lambda { |env|
|
||||
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
[200, {}, [resp]]
|
||||
}
|
||||
end
|
||||
|
||||
hash = JSON.load get(URI('http://example.org/journey/faithfully-omg'))
|
||||
hash = ActiveSupport::JSON.decode get(URI('http://example.org/journey/faithfully-omg'))
|
||||
assert_equal({"artist"=>"journey", "song"=>"faithfully"}, hash)
|
||||
end
|
||||
|
||||
def test_id_with_dash
|
||||
rs.draw do
|
||||
get '/journey/:id', :to => lambda { |env|
|
||||
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
[200, {}, [resp]]
|
||||
}
|
||||
end
|
||||
|
||||
hash = JSON.load get(URI('http://example.org/journey/faithfully-omg'))
|
||||
hash = ActiveSupport::JSON.decode get(URI('http://example.org/journey/faithfully-omg'))
|
||||
assert_equal({"id"=>"faithfully-omg"}, hash)
|
||||
end
|
||||
|
||||
def test_dash_with_custom_regexp
|
||||
rs.draw do
|
||||
get '/:artist/:song-omg', :constraints => { :song => /\d+/ }, :to => lambda { |env|
|
||||
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
[200, {}, [resp]]
|
||||
}
|
||||
end
|
||||
|
||||
hash = JSON.load get(URI('http://example.org/journey/123-omg'))
|
||||
hash = ActiveSupport::JSON.decode get(URI('http://example.org/journey/123-omg'))
|
||||
assert_equal({"artist"=>"journey", "song"=>"123"}, hash)
|
||||
assert_equal 'Not Found', get(URI('http://example.org/journey/faithfully-omg'))
|
||||
end
|
||||
@ -123,24 +124,24 @@ def test_dash_with_custom_regexp
|
||||
def test_pre_dash
|
||||
rs.draw do
|
||||
get '/:artist/omg-:song', :to => lambda { |env|
|
||||
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
[200, {}, [resp]]
|
||||
}
|
||||
end
|
||||
|
||||
hash = JSON.load get(URI('http://example.org/journey/omg-faithfully'))
|
||||
hash = ActiveSupport::JSON.decode get(URI('http://example.org/journey/omg-faithfully'))
|
||||
assert_equal({"artist"=>"journey", "song"=>"faithfully"}, hash)
|
||||
end
|
||||
|
||||
def test_pre_dash_with_custom_regexp
|
||||
rs.draw do
|
||||
get '/:artist/omg-:song', :constraints => { :song => /\d+/ }, :to => lambda { |env|
|
||||
resp = JSON.dump env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
resp = ActiveSupport::JSON.encode env[ActionDispatch::Routing::RouteSet::PARAMETERS_KEY]
|
||||
[200, {}, [resp]]
|
||||
}
|
||||
end
|
||||
|
||||
hash = JSON.load get(URI('http://example.org/journey/omg-123'))
|
||||
hash = ActiveSupport::JSON.decode get(URI('http://example.org/journey/omg-123'))
|
||||
assert_equal({"artist"=>"journey", "song"=>"123"}, hash)
|
||||
assert_equal 'Not Found', get(URI('http://example.org/journey/omg-faithfully'))
|
||||
end
|
||||
@ -160,14 +161,14 @@ def test_star_paths_are_greedy
|
||||
def test_star_paths_are_greedy_but_not_too_much
|
||||
rs.draw do
|
||||
get "/*path", :to => lambda { |env|
|
||||
x = JSON.dump env["action_dispatch.request.path_parameters"]
|
||||
x = ActiveSupport::JSON.encode env["action_dispatch.request.path_parameters"]
|
||||
[200, {}, [x]]
|
||||
}
|
||||
end
|
||||
|
||||
expected = { "path" => "foo/bar", "format" => "html" }
|
||||
u = URI('http://example.org/foo/bar.html')
|
||||
assert_equal expected, JSON.parse(get(u))
|
||||
assert_equal expected, ActiveSupport::JSON.decode(get(u))
|
||||
end
|
||||
|
||||
def test_optional_star_paths_are_greedy
|
||||
@ -185,7 +186,7 @@ def test_optional_star_paths_are_greedy
|
||||
def test_optional_star_paths_are_greedy_but_not_too_much
|
||||
rs.draw do
|
||||
get "/(*filters)", :to => lambda { |env|
|
||||
x = JSON.dump env["action_dispatch.request.path_parameters"]
|
||||
x = ActiveSupport::JSON.encode env["action_dispatch.request.path_parameters"]
|
||||
[200, {}, [x]]
|
||||
}
|
||||
end
|
||||
@ -193,7 +194,7 @@ def test_optional_star_paths_are_greedy_but_not_too_much
|
||||
expected = { "filters" => "ne_27.065938,-80.6092/sw_25.489856,-82",
|
||||
"format" => "542794" }
|
||||
u = URI('http://example.org/ne_27.065938,-80.6092/sw_25.489856,-82.542794')
|
||||
assert_equal expected, JSON.parse(get(u))
|
||||
assert_equal expected, ActiveSupport::JSON.decode(get(u))
|
||||
end
|
||||
|
||||
def test_regexp_precidence
|
||||
@ -1904,6 +1905,10 @@ def test_unicode_path
|
||||
assert_equal({:controller => 'news', :action => 'index'}, @routes.recognize_path(URI.parser.escape('こんにちは/世界'), :method => :get))
|
||||
end
|
||||
|
||||
def test_downcased_unicode_path
|
||||
assert_equal({:controller => 'news', :action => 'index'}, @routes.recognize_path(URI.parser.escape('こんにちは/世界').downcase, :method => :get))
|
||||
end
|
||||
|
||||
private
|
||||
def sort_extras!(extras)
|
||||
if extras.length == 2
|
||||
|
@ -1,5 +1,6 @@
|
||||
require 'abstract_unit'
|
||||
require 'controller/fake_controllers'
|
||||
require 'active_support/json/decoding'
|
||||
|
||||
class TestCaseTest < ActionController::TestCase
|
||||
class TestController < ActionController::Base
|
||||
@ -622,7 +623,7 @@ def test_params_passing_doesnt_modify_in_place
|
||||
@request.headers['Referer'] = "http://nohost.com/home"
|
||||
@request.headers['Content-Type'] = "application/rss+xml"
|
||||
get :test_headers
|
||||
parsed_env = JSON.parse(@response.body)
|
||||
parsed_env = ActiveSupport::JSON.decode(@response.body)
|
||||
assert_equal "http://nohost.com/home", parsed_env["HTTP_REFERER"]
|
||||
assert_equal "application/rss+xml", parsed_env["CONTENT_TYPE"]
|
||||
end
|
||||
@ -631,7 +632,7 @@ def test_params_passing_doesnt_modify_in_place
|
||||
@request.headers['HTTP_REFERER'] = "http://example.com/about"
|
||||
@request.headers['CONTENT_TYPE'] = "application/json"
|
||||
get :test_headers
|
||||
parsed_env = JSON.parse(@response.body)
|
||||
parsed_env = ActiveSupport::JSON.decode(@response.body)
|
||||
assert_equal "http://example.com/about", parsed_env["HTTP_REFERER"]
|
||||
assert_equal "application/json", parsed_env["CONTENT_TYPE"]
|
||||
end
|
||||
|
@ -370,6 +370,24 @@ def test_false_url_params_are_included_in_query
|
||||
assert_equal("/c/a?show=false", W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :show => false))
|
||||
end
|
||||
|
||||
def test_url_generation_with_array_and_hash
|
||||
with_routing do |set|
|
||||
set.draw do
|
||||
namespace :admin do
|
||||
resources :posts
|
||||
end
|
||||
end
|
||||
|
||||
kls = Class.new { include set.url_helpers }
|
||||
kls.default_url_options[:host] = 'www.basecamphq.com'
|
||||
|
||||
controller = kls.new
|
||||
assert_equal("http://www.basecamphq.com/admin/posts/new?param=value",
|
||||
controller.send(:url_for, [:new, :admin, :post, { param: 'value' }])
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def extract_params(url)
|
||||
url.split('?', 2).last.split('&').sort
|
||||
|
@ -1,4 +1,5 @@
|
||||
require 'abstract_unit'
|
||||
require 'active_support/json/decoding'
|
||||
|
||||
class WebServiceTest < ActionDispatch::IntegrationTest
|
||||
class TestController < ActionController::Base
|
||||
@ -54,7 +55,7 @@ def test_put_json
|
||||
|
||||
def test_register_and_use_json_simple
|
||||
with_test_route_set do
|
||||
with_params_parsers Mime::JSON => Proc.new { |data| JSON.parse(data)['request'].with_indifferent_access } do
|
||||
with_params_parsers Mime::JSON => Proc.new { |data| ActiveSupport::JSON.decode(data)['request'].with_indifferent_access } do
|
||||
post "/", '{"request":{"summary":"content...","title":"JSON"}}',
|
||||
'CONTENT_TYPE' => 'application/json'
|
||||
|
||||
|
@ -31,6 +31,14 @@ def self.routes
|
||||
get "/polymorphic_path_for_engine", :to => "inside_engine_generating#polymorphic_path_for_engine"
|
||||
get "/conflicting_url", :to => "inside_engine_generating#conflicting"
|
||||
get "/foo", :to => "never#invoked", :as => :named_helper_that_should_be_invoked_only_in_respond_to_test
|
||||
|
||||
get "/relative_path_redirect", :to => redirect("foo")
|
||||
get "/relative_option_redirect", :to => redirect(:path => "foo")
|
||||
get "/relative_custom_redirect", :to => redirect { |params, request| "foo" }
|
||||
|
||||
get "/absolute_path_redirect", :to => redirect("/foo")
|
||||
get "/absolute_option_redirect", :to => redirect(:path => "/foo")
|
||||
get "/absolute_custom_redirect", :to => redirect { |params, request| "/foo" }
|
||||
end
|
||||
|
||||
routes
|
||||
@ -182,6 +190,48 @@ def setup
|
||||
assert_equal "engine", last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] relative path redirect uses SCRIPT_NAME from request" do
|
||||
get "/awesome/blog/relative_path_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/awesome/blog/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/awesome/blog/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] relative option redirect uses SCRIPT_NAME from request" do
|
||||
get "/awesome/blog/relative_option_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/awesome/blog/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/awesome/blog/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] relative custom redirect uses SCRIPT_NAME from request" do
|
||||
get "/awesome/blog/relative_custom_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/awesome/blog/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/awesome/blog/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] absolute path redirect doesn't use SCRIPT_NAME from request" do
|
||||
get "/awesome/blog/absolute_path_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] absolute option redirect doesn't use SCRIPT_NAME from request" do
|
||||
get "/awesome/blog/absolute_option_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] absolute custom redirect doesn't use SCRIPT_NAME from request" do
|
||||
get "/awesome/blog/absolute_custom_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
# Inside Application
|
||||
test "[APP] generating engine's route includes prefix" do
|
||||
get "/generate"
|
||||
@ -281,6 +331,14 @@ def self.routes
|
||||
routes = ActionDispatch::Routing::RouteSet.new
|
||||
routes.draw do
|
||||
get "/posts/:id", :to => "posts#show", :as => :post
|
||||
|
||||
get "/relative_path_redirect", :to => redirect("foo")
|
||||
get "/relative_option_redirect", :to => redirect(:path => "foo")
|
||||
get "/relative_custom_redirect", :to => redirect { |params, request| "foo" }
|
||||
|
||||
get "/absolute_path_redirect", :to => redirect("/foo")
|
||||
get "/absolute_option_redirect", :to => redirect(:path => "/foo")
|
||||
get "/absolute_custom_redirect", :to => redirect { |params, request| "/foo" }
|
||||
end
|
||||
|
||||
routes
|
||||
@ -331,5 +389,47 @@ def app
|
||||
get "/posts/1"
|
||||
assert_equal "/posts/1", last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] relative path redirect uses SCRIPT_NAME from request" do
|
||||
get "/relative_path_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] relative option redirect uses SCRIPT_NAME from request" do
|
||||
get "/relative_option_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] relative custom redirect uses SCRIPT_NAME from request" do
|
||||
get "/relative_custom_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] absolute path redirect doesn't use SCRIPT_NAME from request" do
|
||||
get "/absolute_path_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] absolute option redirect doesn't use SCRIPT_NAME from request" do
|
||||
get "/absolute_option_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
|
||||
test "[ENGINE] absolute custom redirect doesn't use SCRIPT_NAME from request" do
|
||||
get "/absolute_custom_redirect"
|
||||
assert_equal 301, last_response.status
|
||||
assert_equal "http://example.org/foo", last_response.headers["Location"]
|
||||
assert_equal %(<html><body>You are being <a href="http://example.org/foo">redirected</a>.</body></html>), last_response.body
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -61,6 +61,23 @@ def test_clear
|
||||
assert_equal([], s.values)
|
||||
end
|
||||
|
||||
def test_fetch
|
||||
session = Session.create(store, {}, {})
|
||||
|
||||
session['one'] = '1'
|
||||
assert_equal '1', session.fetch(:one)
|
||||
|
||||
assert_equal '2', session.fetch(:two, '2')
|
||||
assert_equal '2', session.fetch(:two)
|
||||
|
||||
assert_equal 'three', session.fetch(:three) {|el| el.to_s }
|
||||
assert_equal 'three', session.fetch(:three)
|
||||
|
||||
assert_raise KeyError do
|
||||
session.fetch(:four)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def store
|
||||
Class.new {
|
||||
|
@ -212,6 +212,11 @@ def test_response_body_encoding
|
||||
ActionDispatch::Response.default_headers = nil
|
||||
end
|
||||
end
|
||||
|
||||
test "respond_to? accepts include_private" do
|
||||
assert_not @response.respond_to?(:method_missing)
|
||||
assert @response.respond_to?(:method_missing, true)
|
||||
end
|
||||
end
|
||||
|
||||
class ResponseIntegrationTest < ActionDispatch::IntegrationTest
|
||||
|
@ -46,11 +46,11 @@ def self.inspect
|
||||
|
||||
assert_equal [
|
||||
" Prefix Verb URI Pattern Controller#Action",
|
||||
"custom_assets GET /custom/assets(.:format) custom_assets#show",
|
||||
" blog /blog Blog::Engine",
|
||||
"custom_assets GET /custom/assets(.:format) custom_assets#show",
|
||||
" blog /blog Blog::Engine",
|
||||
"",
|
||||
"Routes for Blog::Engine:",
|
||||
"cart GET /cart(.:format) cart#show"
|
||||
" cart GET /cart(.:format) cart#show"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -61,7 +61,7 @@ def test_cart_inspect
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
"cart GET /cart(.:format) cart#show"
|
||||
" cart GET /cart(.:format) cart#show"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -72,7 +72,7 @@ def test_inspect_shows_custom_assets
|
||||
|
||||
assert_equal [
|
||||
" Prefix Verb URI Pattern Controller#Action",
|
||||
"custom_assets GET /custom/assets(.:format) custom_assets#show"
|
||||
"custom_assets GET /custom/assets(.:format) custom_assets#show"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -101,7 +101,7 @@ def test_inspect_routes_shows_root_route
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
"root GET / pages#main"
|
||||
" root GET / pages#main"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -112,7 +112,7 @@ def test_inspect_routes_shows_dynamic_action_route
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
" GET /api/:action(.:format) api#:action"
|
||||
" GET /api/:action(.:format) api#:action"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -123,7 +123,7 @@ def test_inspect_routes_shows_controller_and_action_only_route
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
" GET /:controller/:action(.:format) :controller#:action"
|
||||
" GET /:controller/:action(.:format) :controller#:action"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -134,7 +134,7 @@ def test_inspect_routes_shows_controller_and_action_route_with_constraints
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
" GET /:controller(/:action(/:id))(.:format) :controller#:action {:id=>/\\d+/}"
|
||||
" GET /:controller(/:action(/:id))(.:format) :controller#:action {:id=>/\\d+/}"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -145,7 +145,7 @@ def test_rake_routes_shows_route_with_defaults
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
%Q[ GET /photos/:id(.:format) photos#show {:format=>"jpg"}]
|
||||
%Q[ GET /photos/:id(.:format) photos#show {:format=>"jpg"}]
|
||||
], output
|
||||
end
|
||||
|
||||
@ -156,7 +156,7 @@ def test_rake_routes_shows_route_with_constraints
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
" GET /photos/:id(.:format) photos#show {:id=>/[A-Z]\\d{5}/}"
|
||||
" GET /photos/:id(.:format) photos#show {:id=>/[A-Z]\\d{5}/}"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -172,7 +172,7 @@ def test_rake_routes_shows_route_with_rack_app
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
" GET /foo/:id(.:format) #{RackApp.name} {:id=>/[A-Z]\\d{5}/}"
|
||||
" GET /foo/:id(.:format) #{RackApp.name} {:id=>/[A-Z]\\d{5}/}"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -191,7 +191,7 @@ def inspect
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
" /foo #{RackApp.name} {:constraint=>( my custom constraint )}"
|
||||
" /foo #{RackApp.name} {:constraint=>( my custom constraint )}"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -212,9 +212,9 @@ def test_redirect
|
||||
|
||||
assert_equal [
|
||||
"Prefix Verb URI Pattern Controller#Action",
|
||||
" foo GET /foo(.:format) redirect(301, /foo/bar) {:subdomain=>\"admin\"}",
|
||||
" bar GET /bar(.:format) redirect(307, path: /foo/bar)",
|
||||
"foobar GET /foobar(.:format) redirect(301)"
|
||||
" foo GET /foo(.:format) redirect(301, /foo/bar) {:subdomain=>\"admin\"}",
|
||||
" bar GET /bar(.:format) redirect(307, path: /foo/bar)",
|
||||
"foobar GET /foobar(.:format) redirect(301)"
|
||||
], output
|
||||
end
|
||||
|
||||
@ -241,7 +241,7 @@ def test_regression_route_with_controller_regexp
|
||||
end
|
||||
|
||||
assert_equal ["Prefix Verb URI Pattern Controller#Action",
|
||||
" GET /:controller(/:action) (?-mix:api\\/[^\\/]+)#:action"], output
|
||||
" GET /:controller(/:action) (?-mix:api\\/[^\\/]+)#:action"], output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1102,6 +1102,19 @@ def test_scoped_root
|
||||
assert_equal 'projects#index', @response.body
|
||||
end
|
||||
|
||||
def test_scoped_root_as_name
|
||||
draw do
|
||||
scope '(:locale)', :locale => /en|pl/ do
|
||||
root :to => 'projects#index', :as => 'projects'
|
||||
end
|
||||
end
|
||||
|
||||
assert_equal '/en', projects_path(:locale => 'en')
|
||||
assert_equal '/', projects_path
|
||||
get '/en'
|
||||
assert_equal 'projects#index', @response.body
|
||||
end
|
||||
|
||||
def test_scope_with_format_option
|
||||
draw do
|
||||
get "direct/index", as: :no_format_direct, format: false
|
||||
|
@ -37,6 +37,10 @@ def test_serves_static_index_file_in_directory
|
||||
end
|
||||
|
||||
def test_served_static_file_with_non_english_filename
|
||||
if RUBY_ENGINE == 'jruby '
|
||||
skip "Stop skipping if following bug gets fixed: " \
|
||||
"http://jira.codehaus.org/browse/JRUBY-7192"
|
||||
end
|
||||
assert_html "means hello in Japanese\n", get("/foo/#{Rack::Utils.escape("こんにちは.html")}")
|
||||
end
|
||||
|
||||
|
@ -1,5 +1,3 @@
|
||||
module AbcHelper
|
||||
def bare_a() end
|
||||
def bare_b() end
|
||||
def bare_c() end
|
||||
end
|
||||
|
@ -1,5 +0,0 @@
|
||||
module HelperyTestHelper
|
||||
def helpery_test
|
||||
"Default"
|
||||
end
|
||||
end
|
0
actionpack/test/fixtures/respond_with/respond_with_additional_params.html.erb
vendored
Normal file
0
actionpack/test/fixtures/respond_with/respond_with_additional_params.html.erb
vendored
Normal file
@ -1,5 +1,5 @@
|
||||
require 'abstract_unit'
|
||||
require 'json'
|
||||
require 'active_support/json/decoding'
|
||||
|
||||
module ActionDispatch
|
||||
module Journey
|
||||
@ -13,7 +13,7 @@ def test_to_json
|
||||
/articles/:id(.:format)
|
||||
}
|
||||
|
||||
json = JSON.load table.to_json
|
||||
json = ActiveSupport::JSON.decode table.to_json
|
||||
assert json['regexp_states']
|
||||
assert json['string_states']
|
||||
assert json['accepting']
|
||||
|
@ -15,6 +15,14 @@ def test_fragment_escape
|
||||
def test_uri_unescape
|
||||
assert_equal "a/b c+d", Utils.unescape_uri("a%2Fb%20c+d")
|
||||
end
|
||||
|
||||
def test_normalize_path_not_greedy
|
||||
assert_equal "/foo%20bar%20baz", Utils.normalize_path("/foo%20bar%20baz")
|
||||
end
|
||||
|
||||
def test_normalize_path_uppercase
|
||||
assert_equal "/foo%AAbar%AAbaz", Utils.normalize_path("/foo%aabar%aabaz")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -96,88 +96,6 @@ def relevances_attributes=(attributes); end
|
||||
attr_accessor :body
|
||||
end
|
||||
|
||||
class Tag
|
||||
extend ActiveModel::Naming
|
||||
include ActiveModel::Conversion
|
||||
|
||||
attr_reader :id
|
||||
attr_reader :post_id
|
||||
def initialize(id = nil, post_id = nil); @id, @post_id = id, post_id end
|
||||
def to_key; id ? [id] : nil end
|
||||
def save; @id = 1; @post_id = 1 end
|
||||
def persisted?; @id.present? end
|
||||
def to_param; @id; end
|
||||
def value
|
||||
@id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}"
|
||||
end
|
||||
|
||||
attr_accessor :relevances
|
||||
def relevances_attributes=(attributes); end
|
||||
|
||||
end
|
||||
|
||||
class CommentRelevance
|
||||
extend ActiveModel::Naming
|
||||
include ActiveModel::Conversion
|
||||
|
||||
attr_reader :id
|
||||
attr_reader :comment_id
|
||||
def initialize(id = nil, comment_id = nil); @id, @comment_id = id, comment_id end
|
||||
def to_key; id ? [id] : nil end
|
||||
def save; @id = 1; @comment_id = 1 end
|
||||
def persisted?; @id.present? end
|
||||
def to_param; @id; end
|
||||
def value
|
||||
@id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}"
|
||||
end
|
||||
end
|
||||
|
||||
class Sheep
|
||||
extend ActiveModel::Naming
|
||||
include ActiveModel::Conversion
|
||||
|
||||
attr_reader :id
|
||||
def to_key; id ? [id] : nil end
|
||||
def save; @id = 1 end
|
||||
def new_record?; @id.nil? end
|
||||
def name
|
||||
@id.nil? ? 'new sheep' : "sheep ##{@id}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class TagRelevance
|
||||
extend ActiveModel::Naming
|
||||
include ActiveModel::Conversion
|
||||
|
||||
attr_reader :id
|
||||
attr_reader :tag_id
|
||||
def initialize(id = nil, tag_id = nil); @id, @tag_id = id, tag_id end
|
||||
def to_key; id ? [id] : nil end
|
||||
def save; @id = 1; @tag_id = 1 end
|
||||
def persisted?; @id.present? end
|
||||
def to_param; @id; end
|
||||
def value
|
||||
@id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}"
|
||||
end
|
||||
end
|
||||
|
||||
class Author < Comment
|
||||
attr_accessor :post
|
||||
def post_attributes=(attributes); end
|
||||
end
|
||||
|
||||
class HashBackedAuthor < Hash
|
||||
extend ActiveModel::Naming
|
||||
include ActiveModel::Conversion
|
||||
|
||||
def persisted?; false; end
|
||||
|
||||
def name
|
||||
"hash backed author"
|
||||
end
|
||||
end
|
||||
|
||||
module Blog
|
||||
def self.use_relative_model_naming?
|
||||
true
|
||||
@ -193,21 +111,8 @@ def persisted?
|
||||
end
|
||||
end
|
||||
|
||||
class ArelLike
|
||||
def to_ary
|
||||
true
|
||||
end
|
||||
def each
|
||||
a = Array.new(2) { |id| Comment.new(id + 1) }
|
||||
a.each { |i| yield i }
|
||||
end
|
||||
end
|
||||
|
||||
class RenderJsonTestException < Exception
|
||||
def to_json(options = nil)
|
||||
return { :error => self.class.name, :message => self.to_s }.to_json
|
||||
def as_json(options = nil)
|
||||
{ :error => self.class.name, :message => self.to_s }
|
||||
end
|
||||
end
|
||||
|
||||
class Car < Struct.new(:color)
|
||||
end
|
||||
|
@ -1,7 +1,60 @@
|
||||
* Only cache template digests if `config.cache_template_loading` id true.
|
||||
* Use `set_backtrace` instead of instance variable `@backtrace` in ActionView exceptions
|
||||
|
||||
*Shimpei Makimoto*
|
||||
|
||||
* Fix `simple_format` escapes own output when passing `sanitize: true`
|
||||
|
||||
*Paul Seidemann*
|
||||
|
||||
* Ensure `ActionView::Digestor.cache` is correctly cleaned up when
|
||||
combining recursive templates with `ActionView::Resolver.caching = false`.
|
||||
|
||||
*wyaeld*
|
||||
|
||||
* Fix `collection_check_boxes` generated hidden input to use the name attribute provided
|
||||
in the options hash.
|
||||
|
||||
*Angel N. Sciortino*
|
||||
|
||||
* Fix some edge cases for AV `select` helper with `:selected` option.
|
||||
|
||||
*Bogdan Gusiev*
|
||||
|
||||
* Ability to pass block to `select` helper
|
||||
|
||||
<%= select(report, "campaign_ids") do %>
|
||||
<% available_campaigns.each do |c| -%>
|
||||
<%= content_tag(:option, c.name, value: c.id, data: { tags: c.tags.to_json }) %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
|
||||
*Bogdan Gusiev*
|
||||
|
||||
* Handle `:namespace` form option in collection labels.
|
||||
|
||||
*Vasiliy Ermolovich*
|
||||
|
||||
* Fix `form_for` when both `namespace` and `as` options are present.
|
||||
|
||||
`as` option no longer overwrites `namespace` option when generating
|
||||
html id attribute of the form element.
|
||||
|
||||
*Adam Niedzielski*
|
||||
|
||||
* Fix `excerpt` when `:separator` is `nil`.
|
||||
|
||||
*Paul Nikitochkin*
|
||||
|
||||
* Only cache template digests if `config.cache_template_loading` is true.
|
||||
|
||||
*Josh Lauer*, *Justin Ridgewell*
|
||||
|
||||
* Fixed a bug where the lookup details were not being taken into account
|
||||
when caching the digest of a template - changes to the details now
|
||||
cause a different cache key to be used.
|
||||
|
||||
*Daniel Schierbeck*
|
||||
|
||||
* Added an `extname` hash option for `javascript_include_tag` method.
|
||||
|
||||
Before:
|
||||
|
@ -18,7 +18,7 @@ which can be further narrowed down to one test:
|
||||
|
||||
== Dependency on Active Record and database setup
|
||||
|
||||
Test cases in the test/active_record/ directory depend on having
|
||||
Test cases in the test/activerecord/ directory depend on having
|
||||
activerecord and sqlite installed. If Active Record is not in
|
||||
actionview/../activerecord directory, or the sqlite rubygem is not installed,
|
||||
these tests are skipped.
|
||||
|
@ -11,7 +11,7 @@ task :test => ["test:template", "test:integration:action_pack", "test:integratio
|
||||
|
||||
namespace :test do
|
||||
task :isolated do
|
||||
Dir.glob("test/{active_record,template}/**/*_test.rb").all? do |file|
|
||||
Dir.glob("test/{actionpack,activerecord,template}/**/*_test.rb").all? do |file|
|
||||
sh(Gem.ruby, '-w', '-Ilib:test', file)
|
||||
end or raise "Failures"
|
||||
end
|
||||
|
@ -5,7 +5,7 @@
|
||||
s.name = 'actionview'
|
||||
s.version = version
|
||||
s.summary = 'Rendering framework putting the V in MVC (part of Rails).'
|
||||
s.description = ''
|
||||
s.description = 'Simple, battle-tested conventions and helpers for building web pages.'
|
||||
|
||||
s.required_ruby_version = '>= 1.9.3'
|
||||
|
||||
|
@ -10,7 +10,10 @@ class Digestor
|
||||
|
||||
class << self
|
||||
def digest(name, format, finder, options = {})
|
||||
cache_key = ([name, format] + Array.wrap(options[:dependencies])).join('.')
|
||||
details_key = finder.details_key.hash
|
||||
dependencies = Array.wrap(options[:dependencies])
|
||||
cache_key = ([name, details_key, format] + dependencies).join('.')
|
||||
|
||||
# this is a correctly done double-checked locking idiom
|
||||
# (ThreadSafe::Cache's lookups have volatile semantics)
|
||||
@@cache[cache_key] || @@digest_monitor.synchronize do
|
||||
@ -32,13 +35,13 @@ def compute_and_store_digest(cache_key, name, format, finder, options) # called
|
||||
Digestor
|
||||
end
|
||||
|
||||
digest = klass.new(name, format, finder, options).digest
|
||||
# Store the actual digest if config.cache_template_loading is true
|
||||
klass.new(name, format, finder, options).digest.tap do |digest|
|
||||
@@cache[cache_key] = digest if ActionView::Resolver.caching?
|
||||
end
|
||||
rescue Exception
|
||||
@@cache.delete_pair(cache_key, false) if pre_stored # something went wrong, make sure not to corrupt the @@cache
|
||||
raise
|
||||
@@cache[cache_key] = stored_digest = digest if ActionView::Resolver.caching?
|
||||
digest
|
||||
ensure
|
||||
# something went wrong or ActionView::Resolver.caching? is false, make sure not to corrupt the @@cache
|
||||
@@cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -153,14 +153,14 @@ def auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {})
|
||||
#
|
||||
# ==== Examples
|
||||
#
|
||||
# favicon_link_tag '/myicon.ico'
|
||||
# favicon_link_tag 'myicon.ico'
|
||||
# # => <link href="/assets/myicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon" />
|
||||
#
|
||||
# Mobile Safari looks for a different <link> tag, pointing to an image that
|
||||
# will be used if you add the page to the home screen of an iPod Touch, iPhone, or iPad.
|
||||
# The following call would generate such a tag:
|
||||
#
|
||||
# favicon_link_tag '/mb-icon.png', rel: 'apple-touch-icon', type: 'image/png'
|
||||
# favicon_link_tag 'mb-icon.png', rel: 'apple-touch-icon', type: 'image/png'
|
||||
# # => <link href="/assets/mb-icon.png" rel="apple-touch-icon" type="image/png" />
|
||||
def favicon_link_tag(source='favicon.ico', options={})
|
||||
tag('link', {
|
||||
@ -224,14 +224,14 @@ def image_tag(source, options={})
|
||||
#
|
||||
# ==== Examples
|
||||
#
|
||||
# image_tag('rails.png')
|
||||
# # => <img alt="Rails" src="/assets/rails.png" />
|
||||
# image_alt('rails.png')
|
||||
# # => Rails
|
||||
#
|
||||
# image_tag('hyphenated-file-name.png')
|
||||
# # => <img alt="Hyphenated file name" src="/assets/hyphenated-file-name.png" />
|
||||
# image_alt('hyphenated-file-name.png')
|
||||
# # => Hyphenated file name
|
||||
#
|
||||
# image_tag('underscored_file_name.png')
|
||||
# # => <img alt="Underscored file name" src="/assets/underscored_file_name.png" />
|
||||
# image_alt('underscored_file_name.png')
|
||||
# # => Underscored file name
|
||||
def image_alt(src)
|
||||
File.basename(src, '.*').sub(/-[[:xdigit:]]{32}\z/, '').tr('-_', ' ').capitalize
|
||||
end
|
||||
|
@ -143,9 +143,9 @@ def asset_path(source, options = {})
|
||||
|
||||
"#{source}#{tail}"
|
||||
end
|
||||
alias_method :path_to_asset, :asset_path # aliased to avoid conflicts with a asset_path named route
|
||||
alias_method :path_to_asset, :asset_path # aliased to avoid conflicts with an asset_path named route
|
||||
|
||||
# Computes the full URL to a asset in the public directory. This
|
||||
# Computes the full URL to an asset in the public directory. This
|
||||
# will use +asset_path+ internally, so most of their behaviors
|
||||
# will be the same.
|
||||
def asset_url(source, options = {})
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user