Merge branch 'master' into fix_26964

This commit is contained in:
Kasper Timm Hansen 2016-12-29 20:09:43 +01:00 committed by GitHub
commit ca3eb2c156
458 changed files with 4085 additions and 2485 deletions

@ -6,6 +6,7 @@ AllCops:
Exclude:
- '**/templates/**/*'
- '**/vendor/**/*'
- 'actionpack/lib/action_dispatch/journey/parser.rb'
# Prefer &&/|| over and/or.
Style/AndOr:

@ -34,19 +34,19 @@ env:
- "JRUBY_OPTS='--dev -J-Xmx1024M'"
matrix:
- "GEM=railties"
- "GEM=ap"
- "GEM=ac"
- "GEM=ac:integration"
- "GEM=ap,ac"
- "GEM=am,amo,as,av,aj"
- "GEM=as PRESERVE_TIMEZONES=1"
- "GEM=ar:mysql2"
- "GEM=ar:sqlite3"
- "GEM=ar:postgresql"
- "GEM=guides"
- "GEM=ac:integration"
rvm:
- 2.2.6
- 2.3.3
- 2.4.0
- ruby-head
matrix:
@ -85,6 +85,7 @@ matrix:
allow_failures:
- rvm: ruby-head
- rvm: jruby-9.1.5.0
- env: "GEM=ac:integration"
fast_finish: true
notifications:

@ -29,9 +29,6 @@ gem "bcrypt", "~> 3.1.11", require: false
# sprockets.
gem "uglifier", ">= 1.3.0", require: false
# Track stable branch of sass because it doesn't have circular require warnings.
gem "sass", github: "sass/sass", branch: "stable", require: false
# FIXME: Remove this fork after https://github.com/nex3/rb-inotify/pull/49 is fixed.
gem "rb-inotify", github: "matthewd/rb-inotify", branch: "close-handling", require: false
@ -41,10 +38,10 @@ gem "json", ">= 2.0.0"
gem "rubocop", require: false
group :doc do
gem "sdoc", "1.0.0.beta2"
gem "sdoc", "1.0.0.rc1"
gem "redcarpet", "~> 3.2.3", platforms: :ruby
gem "w3c_validators"
gem "kindlerb", ">= 1.0.1"
gem "kindlerb", "~> 1.2.0"
end
# Active Support.

@ -40,7 +40,7 @@ GIT
GIT
remote: https://github.com/resque/resque.git
revision: 20d885065ac19e7f7d7a982f4ed1296083db0300
revision: 835a4a7e61a2e33832dbf11975ecfab54af293c6
specs:
resque (1.27.0)
mono_logger (~> 1.0)
@ -49,19 +49,12 @@ GIT
sinatra (>= 0.9.2)
vegas (~> 0.1.2)
GIT
remote: https://github.com/sass/sass.git
revision: 7716e67f3507c6f65878c69aa49ec358ebf675c7
branch: stable
specs:
sass (3.4.22)
PATH
remote: .
specs:
actioncable (5.1.0.alpha)
actionpack (= 5.1.0.alpha)
nio4r (~> 1.2)
nio4r (~> 2.0)
websocket-driver (~> 0.6.1)
actionmailer (5.1.0.alpha)
actionpack (= 5.1.0.alpha)
@ -121,7 +114,7 @@ GEM
addressable (2.5.0)
public_suffix (~> 2.0, >= 2.0.2)
amq-protocol (2.0.1)
arel (7.1.2)
arel (7.1.4)
ast (2.3.0)
backburner (1.3.1)
beaneater (~> 1.0)
@ -132,7 +125,7 @@ GEM
bcrypt (3.1.11-x86-mingw32)
beaneater (1.0.0)
benchmark-ips (2.7.2)
blade (0.6.1)
blade (0.7.0)
activesupport (>= 3.0.0)
blade-qunit_adapter (~> 2.0.1)
coffee-script
@ -141,17 +134,16 @@ GEM
eventmachine
faye
sprockets (>= 3.0)
sprockets-export (~> 0.9.1)
thin (>= 1.6.0)
thor (~> 0.19.1)
useragent (~> 0.16.7)
blade-qunit_adapter (2.0.1)
blade-sauce_labs_plugin (0.6.1)
blade-sauce_labs_plugin (0.6.2)
childprocess
faraday
selenium-webdriver
builder (3.2.2)
bunny (2.2.2)
bunny (2.6.2)
amq-protocol (>= 2.0.1)
byebug (9.0.6)
childprocess (0.5.9)
@ -162,9 +154,9 @@ GEM
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.10.0)
concurrent-ruby (1.0.2)
connection_pool (2.2.0)
coffee-script-source (1.12.2)
concurrent-ruby (1.0.4)
connection_pool (2.2.1)
cookiejar (0.3.3)
curses (1.0.2)
daemons (1.2.4)
@ -201,8 +193,6 @@ GEM
eventmachine (>= 0.12.0)
websocket-driver (>= 0.5.1)
ffi (1.9.14)
ffi (1.9.14-x64-mingw32)
ffi (1.9.14-x86-mingw32)
globalid (0.3.7)
activesupport (>= 4.1.0)
hiredis (0.6.1)
@ -213,7 +203,7 @@ GEM
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.0.2)
kindlerb (1.0.1)
kindlerb (1.2.0)
mustache
nokogiri
libxml-ruby (2.9.0)
@ -241,22 +231,22 @@ GEM
mysql2 (0.4.5)
mysql2 (0.4.5-x64-mingw32)
mysql2 (0.4.5-x86-mingw32)
nio4r (1.2.1)
nokogiri (1.6.8.1)
nio4r (2.0.0)
nokogiri (1.7.0)
mini_portile2 (~> 2.1.0)
nokogiri (1.6.8.1-x64-mingw32)
nokogiri (1.7.0-x64-mingw32)
mini_portile2 (~> 2.1.0)
nokogiri (1.6.8.1-x86-mingw32)
nokogiri (1.7.0-x86-mingw32)
mini_portile2 (~> 2.1.0)
parser (2.3.2.0)
parser (2.3.3.1)
ast (~> 2.2)
pg (0.19.0)
pg (0.19.0-x64-mingw32)
pg (0.19.0-x86-mingw32)
powerpack (0.1.1)
psych (2.1.1)
psych (2.2.2)
public_suffix (2.0.4)
puma (3.6.0)
puma (3.6.2)
qu (0.2.0)
multi_json
qu-redis (0.2.0)
@ -272,17 +262,17 @@ GEM
rack
rack-test (0.6.3)
rack (>= 1.0)
rails-dom-testing (2.0.1)
rails-dom-testing (2.0.2)
activesupport (>= 4.2.0, < 6.0)
nokogiri (~> 1.6.0)
nokogiri (~> 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
rainbow (2.1.0)
rake (11.3.0)
rb-fsevent (0.9.7)
rdoc (5.0.0.beta2)
rake (12.0.0)
rb-fsevent (0.9.8)
rdoc (5.0.0)
redcarpet (3.2.3)
redis (3.3.1)
redis (3.3.2)
redis-namespace (1.5.2)
redis (~> 3.0, >= 3.0.4)
resque-scheduler (4.3.0)
@ -290,49 +280,50 @@ GEM
redis (~> 3.3)
resque (~> 1.26)
rufus-scheduler (~> 3.2)
rubocop (0.45.0)
rubocop (0.46.0)
parser (>= 2.3.1.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.8.1)
ruby_dep (1.4.0)
ruby_dep (1.5.0)
rubyzip (1.2.0)
rufus-scheduler (3.2.2)
rufus-scheduler (3.3.1)
tzinfo
sass (3.4.23)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
sdoc (1.0.0.beta2)
rdoc (= 5.0.0.beta2)
selenium-webdriver (3.0.1)
sdoc (1.0.0.rc1)
rdoc (= 5.0.0)
selenium-webdriver (3.0.5)
childprocess (~> 0.5)
rubyzip (~> 1.0)
websocket (~> 1.0)
sequel (4.39.0)
sequel (4.41.0)
serverengine (1.5.11)
sigdump (~> 0.2.2)
sidekiq (4.2.2)
sidekiq (4.2.7)
concurrent-ruby (~> 1.0)
connection_pool (~> 2.2, >= 2.2.0)
rack-protection (~> 1.5)
rack-protection (>= 1.5.0)
redis (~> 3.2, >= 3.2.1)
sigdump (0.2.4)
simple_uuid (0.4.0)
sinatra (1.0)
rack (>= 1.0)
sneakers (2.3.5)
bunny (~> 2.2.0)
sneakers (2.4.0)
bunny (~> 2.6)
serverengine (~> 1.5.11)
thor
thread (~> 0.1.7)
sprockets (3.7.0)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-export (0.9.1)
sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
@ -347,7 +338,7 @@ GEM
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
thor (0.19.1)
thor (0.19.4)
thread (0.1.7)
thread_safe (0.3.5)
tilt (2.0.5)
@ -356,17 +347,17 @@ GEM
turbolinks-source (5.0.0)
tzinfo (1.2.2)
thread_safe (~> 0.1)
tzinfo-data (1.2016.7)
tzinfo-data (1.2016.10)
tzinfo (>= 1.0.0)
uglifier (3.0.2)
uglifier (3.0.4)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.1.1)
unicode-display_width (1.1.2)
useragent (0.16.8)
vegas (0.1.11)
rack (>= 1.0.0)
w3c_validators (1.2)
json
nokogiri
w3c_validators (1.3.1)
json (~> 2.0)
nokogiri (~> 1.6)
wdm (0.1.1)
websocket (1.2.3)
websocket-driver (0.6.4)
@ -396,7 +387,7 @@ DEPENDENCIES
hiredis
jquery-rails
json (>= 2.0.0)
kindlerb (>= 1.0.1)
kindlerb (~> 1.2.0)
libxml-ruby
listen (>= 3.0.5, < 3.2)
minitest (< 5.3.4)
@ -419,9 +410,8 @@ DEPENDENCIES
resque!
resque-scheduler
rubocop
sass!
sass-rails
sdoc (= 1.0.0.beta2)
sdoc (= 1.0.0.rc1)
sequel
sidekiq
sneakers
@ -436,4 +426,4 @@ DEPENDENCIES
websocket-client-simple!
BUNDLED WITH
1.13.6
1.13.7

@ -13,12 +13,12 @@
*Vladimir Dementyev*
* Buffer now writes to websocket connections, to avoid blocking threads
* Buffer now writes to WebSocket connections, to avoid blocking threads
that could be doing more useful things.
*Matthew Draper*, *Tinco Andringa*
* Protect against concurrent writes to a websocket connection from
* Protect against concurrent writes to a WebSocket connection from
multiple threads; the underlying OS write is not always threadsafe.
*Tinco Andringa*

@ -51,7 +51,7 @@ module ApplicationCable
self.current_user = find_verified_user
end
protected
private
def find_verified_user
if current_user = User.find_by(id: cookies.signed[:user_id])
current_user

@ -20,6 +20,6 @@
s.add_dependency "actionpack", version
s.add_dependency "nio4r", "~> 1.2"
s.add_dependency "nio4r", "~> 2.0"
s.add_dependency "websocket-driver", "~> 0.6.1"
end

@ -122,16 +122,16 @@ def action_methods
end
end
protected
private
# action_methods are cached and there is sometimes need to refresh
# them. ::clear_action_methods! allows you to do that, so next time
# you run action_methods, they will be recalculated.
def clear_action_methods!
def clear_action_methods! # :doc:
@action_methods = nil
end
# Refresh the cached action_methods when a new action_method is added.
def method_added(name)
def method_added(name) # :doc:
super
clear_action_methods!
end
@ -189,22 +189,22 @@ def unsubscribe_from_channel # :nodoc:
end
end
protected
private
# Called once a consumer has become a subscriber of the channel. Usually the place to setup any streams
# you want this channel to be sending to the subscriber.
def subscribed
def subscribed # :doc:
# Override in subclasses
end
# Called once a consumer has cut its cable connection. Can be used for cleaning up connections or marking
# users as offline or the like.
def unsubscribed
def unsubscribed # :doc:
# Override in subclasses
end
# Transmit a hash of data to the subscriber. The hash will automatically be wrapped in a JSON envelope with
# the proper channel identifier marked as the recipient.
def transmit(data, via: nil)
def transmit(data, via: nil) # :doc:
logger.info "#{self.class.name} transmitting #{data.inspect.truncate(300)}".tap { |m| m << " (via #{via})" if via }
payload = { channel_class: self.class.name, data: data, via: via }
@ -213,33 +213,32 @@ def transmit(data, via: nil)
end
end
def ensure_confirmation_sent
def ensure_confirmation_sent # :doc:
return if subscription_rejected?
@defer_subscription_confirmation_counter.decrement
transmit_subscription_confirmation unless defer_subscription_confirmation?
end
def defer_subscription_confirmation!
def defer_subscription_confirmation! # :doc:
@defer_subscription_confirmation_counter.increment
end
def defer_subscription_confirmation?
def defer_subscription_confirmation? # :doc:
@defer_subscription_confirmation_counter.value > 0
end
def subscription_confirmation_sent?
def subscription_confirmation_sent? # :doc:
@subscription_confirmation_sent
end
def reject
def reject # :doc:
@reject_subscription = true
end
def subscription_rejected?
def subscription_rejected? # :doc:
@reject_subscription
end
private
def delegate_connection_identifiers
connection.identifiers.each do |identifier|
define_singleton_method(identifier) do

@ -22,13 +22,10 @@ module Connection
# # Any cleanup work needed when the cable connection is cut.
# end
#
# protected
# private
# def find_verified_user
# if current_user = User.find_by_identity cookies.signed[:identity_id]
# current_user
# else
# User.find_by_identity(cookies.signed[:identity_id]) ||
# reject_unauthorized_connection
# end
# end
# end
# end
@ -136,9 +133,15 @@ def on_close(reason, code) # :nodoc:
send_async :handle_close
end
# TODO Change this to private once we've dropped Ruby 2.2 support.
# Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :websocket
attr_reader :message_buffer
private
# The request that initiated the WebSocket connection is available here. This gives access to the environment, cookies, etc.
def request
def request # :doc:
@request ||= begin
environment = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
ActionDispatch::Request.new(environment || env)
@ -146,14 +149,10 @@ def request
end
# The cookies of the request that initiated the WebSocket connection. Useful for performing authorization checks.
def cookies
def cookies # :doc:
request.cookie_jar
end
attr_reader :websocket
attr_reader :message_buffer
private
def encode(cable_message)
@coder.encode cable_message
end

@ -28,6 +28,8 @@ def process!
receive_buffered_messages
end
# TODO Change this to private once we've dropped Ruby 2.2 support.
# Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :connection
attr_reader :buffered_messages

@ -61,6 +61,8 @@ def unsubscribe_from_all
subscriptions.each { |id, channel| remove_subscription(channel) }
end
# TODO Change this to private once we've dropped Ruby 2.2 support.
# Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :connection, :subscriptions

@ -31,8 +31,8 @@ def tag(logger)
end
end
protected
def log(type, message)
private
def log(type, message) # :doc:
tag(@logger) { @logger.send type, message }
end
end

@ -32,6 +32,8 @@ def rack_response
websocket.rack_response
end
# TODO Change this to private once we've dropped Ruby 2.2 support.
# Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :websocket
end

@ -3,7 +3,7 @@ Description:
Stubs out a new cable channel for the server (in Ruby) and client (in CoffeeScript).
Pass the channel name, either CamelCased or under_scored, and an optional list of channel actions as arguments.
Note: Turn on the cable connection in app/assets/javascript/cable.js after generating any channels.
Note: Turn on the cable connection in app/assets/javascripts/cable.js after generating any channels.
Example:
========
@ -11,4 +11,4 @@ Example:
creates a Chat channel class and CoffeeScript asset:
Channel: app/channels/chat_channel.rb
Assets: app/assets/javascript/channels/chat.coffee
Assets: app/assets/javascripts/channels/chat.coffee

@ -23,7 +23,7 @@ def create_channel_file
generate_application_cable_files
end
protected
private
def file_name
@_file_name ||= super.gsub(/_channel/i, "")
end

@ -53,7 +53,7 @@ def connect
end
end
protected
private
def open_connection_with_stubbed_pubsub
server = TestServer.new
server.stubs(:adapter).returns(stub_everything("adapter"))

@ -19,7 +19,7 @@ def connect
end
end
protected
private
def open_connection_with_stubbed_pubsub
server = TestServer.new
server.stubs(:pubsub).returns(stub_everything("pubsub"))

@ -21,7 +21,7 @@ def send_async(method, *args)
end
end
protected
private
def open_connection_with_stubbed_pubsub
@server = TestServer.new
@server.stubs(:pubsub).returns(stub_everything("pubsub"))

@ -544,9 +544,9 @@ def deliver_mail(mail) #:nodoc:
end
end
protected
private
def set_payload_for_mail(payload, mail) #:nodoc:
def set_payload_for_mail(payload, mail)
payload[:mailer] = name
payload[:message_id] = mail.message_id
payload[:subject] = mail.subject
@ -558,7 +558,7 @@ def set_payload_for_mail(payload, mail) #:nodoc:
payload[:mail] = mail.encoded
end
def method_missing(method_name, *args) # :nodoc:
def method_missing(method_name, *args)
if action_methods.include?(method_name.to_s)
MessageDelivery.new(self, method_name, *args)
else
@ -566,9 +566,7 @@ def method_missing(method_name, *args) # :nodoc:
end
end
private
def respond_to_missing?(method, include_all = false) #:nodoc:
def respond_to_missing?(method, include_all = false)
action_methods.include?(method.to_s)
end
end
@ -830,7 +828,7 @@ def mail(headers = {}, &block)
message
end
protected
private
# Used by #mail to set the content type of the message.
#
@ -841,7 +839,7 @@ def mail(headers = {}, &block)
# If there is no content type passed in via headers, and there are no
# attachments, or the message is multipart, then the default content type is
# used.
def set_content_type(m, user_content_type, class_default)
def set_content_type(m, user_content_type, class_default) # :doc:
params = m.content_type_parameters || {}
case
when user_content_type.present?
@ -863,18 +861,16 @@ def set_content_type(m, user_content_type, class_default)
# If it does not find a translation for the +subject+ under the specified scope it will default to a
# humanized version of the <tt>action_name</tt>.
# If the subject has interpolations, you can pass them through the +interpolations+ parameter.
def default_i18n_subject(interpolations = {})
def default_i18n_subject(interpolations = {}) # :doc:
mailer_scope = self.class.mailer_name.tr("/", ".")
I18n.t(:subject, interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
end
# Emails do not support relative path links.
def self.supports_path?
def self.supports_path? # :doc:
false
end
private
def apply_defaults(headers)
default_values = self.class.default.map do |key, value|
[

@ -94,22 +94,22 @@ def preview_name
name.sub(/Preview$/, "").underscore
end
protected
def load_previews #:nodoc:
private
def load_previews
if preview_path
Dir["#{preview_path}/**/*_preview.rb"].each { |file| require_dependency file }
end
end
def preview_path #:nodoc:
def preview_path
Base.preview_path
end
def show_previews #:nodoc:
def show_previews
Base.show_previews
end
def inform_preview_interceptors(message) #:nodoc:
def inform_preview_interceptors(message)
Base.preview_interceptors.each do |interceptor|
interceptor.previewing_email(message)
end

@ -73,38 +73,36 @@ def determine_default_mailer(name)
end
end
protected
private
def initialize_test_deliveries # :nodoc:
def initialize_test_deliveries
set_delivery_method :test
@old_perform_deliveries = ActionMailer::Base.perform_deliveries
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.deliveries.clear
end
def restore_test_deliveries # :nodoc:
def restore_test_deliveries
restore_delivery_method
ActionMailer::Base.perform_deliveries = @old_perform_deliveries
end
def set_delivery_method(method) # :nodoc:
def set_delivery_method(method)
@old_delivery_method = ActionMailer::Base.delivery_method
ActionMailer::Base.delivery_method = method
end
def restore_delivery_method # :nodoc:
def restore_delivery_method
ActionMailer::Base.deliveries.clear
ActionMailer::Base.delivery_method = @old_delivery_method
end
def set_expected_mail # :nodoc:
def set_expected_mail
@expected = Mail.new
@expected.content_type ["text", "plain", { "charset" => charset }]
@expected.mime_version = "1.0"
end
private
def charset
"UTF-8"
end

@ -19,12 +19,11 @@ def create_mailer_file
hook_for :template_engine, :test_framework
protected
def file_name
private
def file_name # :doc:
@_file_name ||= super.gsub(/_mailer/i, "")
end
private
def application_mailer_file_name
@_application_mailer_file_name ||= if mountable_engine?
"app/mailers/#{namespaced_path}/application_mailer.rb"

@ -829,7 +829,7 @@ def a_callback
assert_equal "special indeed!", mail["X-Special-Header"].to_s
end
protected
private
# Execute the block setting the given values and restoring old values after
# the block is executed.

@ -66,7 +66,7 @@ def test_send_mail
end
end
protected
private
def with_translation(locale, data)
I18n.backend.store_translations(locale, data)

@ -65,7 +65,7 @@ def use_cache
end
end
protected
private
def mail_with_defaults(&block)
mail(to: "test@localhost", from: "tester@example.com",

@ -1,15 +1,15 @@
* Use accept header in integration tests with `as: :json`
Instead of appending the `format` to the request path. Rails will figure
Instead of appending the `format` to the request path, Rails will figure
out the format from the header instead.
This allows devs to use `:as` on routes that don't have a format.
Fixes #27144.
*Kasper Timm Hansen*
* Reset a new session directly after its creation in ActionDispatch::IntegrationTest#open_session.
* Reset a new session directly after its creation in `ActionDispatch::IntegrationTest#open_session`.
Fixes #22742.

@ -52,9 +52,9 @@ def view_cache_dependencies
self.class._view_cache_dependencies.map { |dep| instance_exec(&dep) }.compact
end
protected
private
# Convenience accessor.
def cache(key, options = {}, &block)
def cache(key, options = {}, &block) # :doc:
if cache_configured?
cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller), options, &block)
else

@ -19,7 +19,7 @@ def #{sym}(*args, &block)
generate_method_for_mime(mime) unless instance_methods.include?(mime.to_sym)
end
protected
private
def method_missing(symbol, &block)
unless mime_constant = Mime[symbol]

@ -139,8 +139,8 @@ def self.make_response!(request)
end
end
def self.encoding_for_param(action, param) # :nodoc:
::Encoding::UTF_8
def self.binary_params_for?(action) # :nodoc:
false
end
# Delegates to the class' <tt>controller_name</tt>

@ -11,7 +11,7 @@ module DataStreaming
DEFAULT_SEND_FILE_TYPE = "application/octet-stream".freeze #:nodoc:
DEFAULT_SEND_FILE_DISPOSITION = "attachment".freeze #:nodoc:
protected
private
# Sends the file. This uses a server-appropriate method (such as X-Sendfile)
# via the Rack::Sendfile middleware. The header to use is set via
# +config.action_dispatch.x_sendfile_header+.
@ -70,7 +70,6 @@ def send_file(path, options = {}) #:doc:
send_file_headers! options
self.status = options[:status] || 200
self.content_type = options[:type] if options.key?(:type)
self.content_type = options[:content_type] if options.key?(:content_type)
response.send_file path
end
@ -109,10 +108,12 @@ def send_data(data, options = {}) #:doc:
render options.slice(:status, :content_type).merge(body: data)
end
private
def send_file_headers!(options)
type_provided = options.has_key?(:type)
self.content_type = DEFAULT_SEND_FILE_TYPE
response.sending_file = true
content_type = options.fetch(:type, DEFAULT_SEND_FILE_TYPE)
raise ArgumentError, ":type option required" if content_type.nil?
@ -137,8 +138,6 @@ def send_file_headers!(options)
headers["Content-Transfer-Encoding"] = "binary"
response.sending_file = true
# Fix a problem with IE 6.0 on opening downloaded files:
# If Cache-Control: no-cache is set (which Rails does by default),
# IE removes the file it just downloaded from its cache immediately

@ -42,7 +42,7 @@ def add_flash_types(*types)
end
end
protected
private
def redirect_to(options = {}, response_status_and_flash = {}) #:doc:
self.class._flash_types.each do |flash_type|
if type = response_status_and_flash.delete(flash_type)

@ -28,7 +28,7 @@ module HttpAuthentication
# class ApplicationController < ActionController::Base
# before_action :set_account, :authenticate
#
# protected
# private
# def set_account
# @account = Account.find_by(url_name: request.subdomains.first)
# end
@ -363,7 +363,7 @@ def opaque(secret_key)
# class ApplicationController < ActionController::Base
# before_action :set_account, :authenticate
#
# protected
# private
# def set_account
# @account = Account.find_by(url_name: request.subdomains.first)
# end

@ -83,14 +83,14 @@ def halted_callback_hook(filter)
# end
#
# :api: plugin
def cleanup_view_runtime #:nodoc:
def cleanup_view_runtime
yield
end
# Every time after an action is processed, this method is invoked
# with the payload, so you can add more information.
# :api: plugin
def append_info_to_payload(payload) #:nodoc:
def append_info_to_payload(payload)
payload[:view_runtime] = view_runtime
end

@ -1,5 +1,5 @@
module ActionController
# Allows encoding to be specified per parameter per action.
# Specify binary encoding for parameters for a given action.
module ParameterEncoding
extend ActiveSupport::Concern
@ -13,17 +13,36 @@ def setup_param_encode # :nodoc:
@_parameter_encodings = {}
end
def encoding_for_param(action, param) # :nodoc:
if @_parameter_encodings[action.to_s] && @_parameter_encodings[action.to_s][param.to_s]
@_parameter_encodings[action.to_s][param.to_s]
else
super
end
def binary_params_for?(action) # :nodoc:
@_parameter_encodings[action.to_s]
end
def parameter_encoding(action, param_name, encoding)
@_parameter_encodings[action.to_s] ||= {}
@_parameter_encodings[action.to_s][param_name.to_s] = encoding
# Specify that a given action's parameters should all be encoded as
# ASCII-8BIT (it "skips" the encoding default of UTF-8).
#
# For example, a controller would use it like this:
#
# class RepositoryController < ActionController::Base
# skip_parameter_encoding :show
#
# def show
# @repo = Repository.find_by_filesystem_path params[:file_path]
#
# # `repo_name` is guaranteed to be UTF-8, but was ASCII-8BIT, so
# # tag it as such
# @repo_name = params[:repo_name].force_encoding 'UTF-8'
# end
#
# def index
# @repositories = Repository.all
# end
# end
#
# The show action in the above controller would have all parameter values
# encoded as ASCII-8BIT. This is useful in the case where an application
# must handle data but encoding of the data is unknown, like file system data.
def skip_parameter_encoding(action)
@_parameter_encodings[action.to_s] = true
end
end
end

@ -135,7 +135,7 @@ def name
#
# This method also does namespace lookup. Foo::Bar::UsersController will
# try to find Foo::Bar::User, Foo::User and finally User.
def _default_wrap_model #:nodoc:
def _default_wrap_model
return nil if klass.anonymous?
model_name = klass.name.sub(/Controller$/, "").classify

@ -104,7 +104,7 @@ module ClassMethods
#
# Since <tt>ActionController::Metal</tt> controllers cannot render, the controller
# must include <tt>AbstractController::Rendering</tt>, <tt>ActionController::Rendering</tt>,
# and <tt>ActionController::Renderers</tt>, and have at lest one renderer.
# and <tt>ActionController::Renderers</tt>, and have at least one renderer.
#
# Rather than including <tt>ActionController::Renderers::All</tt> and including all renderers,
# you may specify which renderers to include by passing the renderer name or names to

@ -67,20 +67,20 @@ def _set_html_content_type
end
def _set_rendered_content_type(format)
unless response.content_type
if format && !response.content_type
self.content_type = format.to_s
end
end
# Normalize arguments by catching blocks and setting them on :update.
def _normalize_args(action = nil, options = {}, &blk) #:nodoc:
def _normalize_args(action = nil, options = {}, &blk)
options = super
options[:update] = blk if block_given?
options
end
# Normalize both text and status options.
def _normalize_options(options) #:nodoc:
def _normalize_options(options)
_normalize_text(options)
if options[:html]
@ -103,7 +103,7 @@ def _normalize_text(options)
end
# Process controller specific options, as status, content-type and location.
def _process_options(options) #:nodoc:
def _process_options(options)
status, content_type, location = options.values_at(:status, :content_type, :location)
self.status = status if status

@ -152,7 +152,7 @@ def handle_unverified_request
request.cookie_jar = NullCookieJar.build(request, {})
end
protected
private
class NullSessionHash < Rack::Session::Abstract::SessionHash #:nodoc:
def initialize(req)
@ -197,7 +197,7 @@ def handle_unverified_request
end
end
protected
private
# The actual before_action that is used to verify the CSRF token.
# Don't override this directly. Provide your own forgery protection
# strategy instead. If you override, you'll disable same-origin
@ -208,7 +208,7 @@ def handle_unverified_request
# enabled on an action, this before_action flags its after_action to
# verify that JavaScript responses are for XHR requests, ensuring they
# follow the browser's same-origin policy.
def verify_authenticity_token
def verify_authenticity_token # :doc:
mark_for_same_origin_verification!
if !verified_request?
@ -219,7 +219,7 @@ def verify_authenticity_token
end
end
def handle_unverified_request
def handle_unverified_request # :doc:
forgery_protection_strategy.new(self).handle_unverified_request
end
@ -233,7 +233,7 @@ def handle_unverified_request
# If `verify_authenticity_token` was run (indicating that we have
# forgery protection enabled for this request) then also verify that
# we aren't serving an unauthorized cross-origin response.
def verify_same_origin_request
def verify_same_origin_request # :doc:
if marked_for_same_origin_verification? && non_xhr_javascript_response?
if logger && log_warning_on_csrf_failure
logger.warn CROSS_ORIGIN_JAVASCRIPT_WARNING
@ -243,18 +243,18 @@ def verify_same_origin_request
end
# GET requests are checked for cross-origin JavaScript after rendering.
def mark_for_same_origin_verification!
def mark_for_same_origin_verification! # :doc:
@marked_for_same_origin_verification = request.get?
end
# If the `verify_authenticity_token` before_action ran, verify that
# JavaScript responses are only served to same-origin GET requests.
def marked_for_same_origin_verification?
def marked_for_same_origin_verification? # :doc:
@marked_for_same_origin_verification ||= false
end
# Check for cross-origin JavaScript responses.
def non_xhr_javascript_response?
def non_xhr_javascript_response? # :doc:
content_type =~ %r(\Atext/javascript) && !request.xhr?
end
@ -265,20 +265,20 @@ def non_xhr_javascript_response?
# * Is it a GET or HEAD request? Gets should be safe and idempotent
# * Does the form_authenticity_token match the given token value from the params?
# * Does the X-CSRF-Token header match the form_authenticity_token
def verified_request?
def verified_request? # :doc:
!protect_against_forgery? || request.get? || request.head? ||
(valid_request_origin? && any_authenticity_token_valid?)
end
# Checks if any of the authenticity tokens from the request are valid.
def any_authenticity_token_valid?
def any_authenticity_token_valid? # :doc:
request_authenticity_tokens.any? do |token|
valid_authenticity_token?(session, token)
end
end
# Possible authenticity tokens sent in the request.
def request_authenticity_tokens
def request_authenticity_tokens # :doc:
[form_authenticity_param, request.x_csrf_token]
end
@ -290,7 +290,7 @@ def form_authenticity_token(form_options: {})
# Creates a masked version of the authenticity token that varies
# on each request. The masking is used to mitigate SSL attacks
# like BREACH.
def masked_authenticity_token(session, form_options: {})
def masked_authenticity_token(session, form_options: {}) # :doc:
action, method = form_options.values_at(:action, :method)
raw_token = if per_form_csrf_tokens && action && method
@ -309,7 +309,7 @@ def masked_authenticity_token(session, form_options: {})
# Checks the client's masked token to see if it matches the
# session token. Essentially the inverse of
# +masked_authenticity_token+.
def valid_authenticity_token?(session, encoded_masked_token)
def valid_authenticity_token?(session, encoded_masked_token) # :doc:
if encoded_masked_token.nil? || encoded_masked_token.empty? || !encoded_masked_token.is_a?(String)
return false
end
@ -340,7 +340,7 @@ def valid_authenticity_token?(session, encoded_masked_token)
end
end
def unmask_token(masked_token)
def unmask_token(masked_token) # :doc:
# Split the token into the one-time pad and the encrypted
# value and decrypt it
one_time_pad = masked_token[0...AUTHENTICITY_TOKEN_LENGTH]
@ -348,11 +348,11 @@ def unmask_token(masked_token)
xor_byte_strings(one_time_pad, encrypted_csrf_token)
end
def compare_with_real_token(token, session)
def compare_with_real_token(token, session) # :doc:
ActiveSupport::SecurityUtils.secure_compare(token, real_csrf_token(session))
end
def valid_per_form_csrf_token?(token, session)
def valid_per_form_csrf_token?(token, session) # :doc:
if per_form_csrf_tokens
correct_token = per_form_csrf_token(
session,
@ -366,12 +366,12 @@ def valid_per_form_csrf_token?(token, session)
end
end
def real_csrf_token(session)
def real_csrf_token(session) # :doc:
session[:_csrf_token] ||= SecureRandom.base64(AUTHENTICITY_TOKEN_LENGTH)
Base64.strict_decode64(session[:_csrf_token])
end
def per_form_csrf_token(session, action_path, method)
def per_form_csrf_token(session, action_path, method) # :doc:
OpenSSL::HMAC.digest(
OpenSSL::Digest::SHA256.new,
real_csrf_token(session),
@ -379,25 +379,25 @@ def per_form_csrf_token(session, action_path, method)
)
end
def xor_byte_strings(s1, s2)
def xor_byte_strings(s1, s2) # :doc:
s2_bytes = s2.bytes
s1.each_byte.with_index { |c1, i| s2_bytes[i] ^= c1 }
s2_bytes.pack("C*")
end
# The form's authenticity parameter. Override to provide your own.
def form_authenticity_param
def form_authenticity_param # :doc:
params[request_forgery_protection_token]
end
# Checks if the controller allows forgery protection.
def protect_against_forgery?
def protect_against_forgery? # :doc:
allow_forgery_protection
end
# Checks if the request originated from the same origin by looking at the
# Origin header.
def valid_request_origin?
def valid_request_origin? # :doc:
if forgery_protection_origin_check
# We accept blank origin headers because some user agents don't send it.
request.origin.nil? || request.origin == request.base_url
@ -406,7 +406,7 @@ def valid_request_origin?
end
end
def normalize_action_path(action_path)
def normalize_action_path(action_path) # :doc:
uri = URI.parse(action_path)
uri.path.chomp("/")
end

@ -193,10 +193,10 @@ module ActionController #:nodoc:
module Streaming
extend ActiveSupport::Concern
protected
private
# Set proper cache control and transfer encoding when streaming
def _process_options(options) #:nodoc:
def _process_options(options)
super
if options[:stream]
if request.version == "HTTP/1.0"
@ -210,7 +210,7 @@ def _process_options(options) #:nodoc:
end
# Call render_body if we are streaming instead of usual +render+.
def _render_template(options) #:nodoc:
def _render_template(options)
if options.delete(:stream)
Rack::Chunked::Body.new view_renderer.render_body(view_context, options)
else

@ -3,6 +3,7 @@
require "active_support/core_ext/object/to_query"
require "active_support/core_ext/module/anonymous"
require "active_support/core_ext/hash/keys"
require "active_support/testing/constant_lookup"
require "action_controller/template_assertions"
require "rails-dom-testing"
@ -514,8 +515,6 @@ def process(action, method: "GET", params: {}, session: nil, body: nil, flash: {
@request = @controller.request
@response = @controller.response
@request.delete_header "HTTP_COOKIE"
if @request.have_cookie_jar?
unless @request.cookie_jar.committed?
@request.cookie_jar.write(@response)

@ -51,28 +51,28 @@ def filtered_path
@filtered_path ||= query_string.empty? ? path : "#{path}?#{filtered_query_string}"
end
protected
private
def parameter_filter
def parameter_filter # :doc:
parameter_filter_for fetch_header("action_dispatch.parameter_filter") {
return NULL_PARAM_FILTER
}
end
def env_filter
def env_filter # :doc:
user_key = fetch_header("action_dispatch.parameter_filter") {
return NULL_ENV_FILTER
}
parameter_filter_for(Array(user_key) + ENV_MATCH)
end
def parameter_filter_for(filters)
def parameter_filter_for(filters) # :doc:
ParameterFilter.new(filters)
end
KV_RE = "[^&;=]+"
PAIR_RE = %r{(#{KV_RE})=(#{KV_RE})}
def filtered_query_string
def filtered_query_string # :doc:
query_string.gsub(PAIR_RE) do |_|
parameter_filter.filter([[$1, $2]]).first.join("=")
end

@ -150,20 +150,20 @@ def negotiate_mime(order)
order.include?(Mime::ALL) ? format : nil
end
protected
private
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
def valid_accept_header
def valid_accept_header # :doc:
(xhr? && (accept.present? || content_mime_type)) ||
(accept.present? && accept !~ BROWSER_LIKE_ACCEPTS)
end
def use_accept_header
def use_accept_header # :doc:
!self.class.ignore_accept_header
end
def format_from_path_extension
def format_from_path_extension # :doc:
path = get_header("action_dispatch.original_path") || get_header("PATH_INFO")
if match = path && path.match(/\.(\w+)\z/)
Mime[match.captures.first]

@ -278,6 +278,8 @@ def html?
def all?; false; end
# TODO Change this to private once we've dropped Ruby 2.2 support.
# Workaround for Ruby 2.2 "private attribute?" warning.
protected
attr_reader :string, :synonyms
@ -295,7 +297,7 @@ def method_missing(method, *args)
end
end
def respond_to_missing?(method, include_private = false) #:nodoc:
def respond_to_missing?(method, include_private = false)
method.to_s.ends_with? "?"
end
end

@ -45,7 +45,7 @@ def parameters
query_parameters.dup
end
params.merge!(path_parameters)
params = set_custom_encoding(params)
params = set_binary_encoding(params)
set_header("action_dispatch.request.parameters", params)
params
end
@ -73,21 +73,16 @@ def path_parameters
private
def set_custom_encoding(params)
def set_binary_encoding(params)
action = params[:action]
params.each do |k, v|
if v.is_a?(String) && v.encoding != encoding_template(action, k)
params[k] = v.force_encoding(encoding_template(action, k))
if controller_class.binary_params_for?(action)
ActionDispatch::Request::Utils.each_param_value(params) do |param|
param.force_encoding ::Encoding::ASCII_8BIT
end
end
params
end
def encoding_template(action, param)
controller_class.encoding_for_param(action, param)
end
def parse_formatted_parameters(parsers)
return yield if content_length.zero? || content_mime_type.nil?

@ -69,7 +69,7 @@ def commit_cookie_jar! # :nodoc:
PASS_NOT_FOUND = Class.new { # :nodoc:
def self.action(_); self; end
def self.call(_); [404, { "X-Cascade" => "pass" }, []]; end
def self.encoding_for_param(action, param); ::Encoding::UTF_8; end
def self.binary_params_for?(action); false; end
}
def controller_class
@ -85,6 +85,9 @@ def controller_class
end
end
# Returns true if the request has a header matching the given key parameter.
#
# request.key? :ip_spoofing_check # => true
def key?(key)
has_header? key
end

@ -227,7 +227,9 @@ def content_type=(content_type)
return unless content_type
new_header_info = parse_content_type(content_type.to_s)
prev_header_info = parsed_content_type_header
set_content_type new_header_info.mime_type, new_header_info.charset || prev_header_info.charset || self.class.default_charset
charset = new_header_info.charset || prev_header_info.charset
charset ||= self.class.default_charset unless prev_header_info.mime_type
set_content_type new_header_info.mime_type, charset
end
# Sets the HTTP response's content MIME type. For example, in the controller
@ -408,7 +410,7 @@ def cookies
def parse_content_type(content_type)
if content_type
type, charset = content_type.split(/;\s*charset=/)
type = nil if type.empty?
type = nil if type && type.empty?
ContentTypeHeader.new(type, charset)
else
NullContentTypeHeader

@ -36,7 +36,7 @@ def generate(name, options, path_parameters, parameterize = nil)
route.parts.reverse_each do |key|
break if defaults[key].nil? && parameterized_parts[key].present?
break if parameterized_parts[key].to_s != defaults[key].to_s
next if parameterized_parts[key].to_s != defaults[key].to_s
break if required_parts.include?(key)
parameterized_parts.delete(key)
@ -92,7 +92,11 @@ def match_route(name, options)
else
routes = non_recursive(cache, options)
hash = routes.group_by { |_, r| r.score(options) }
supplied_keys = options.each_with_object({}) do |(k, v), h|
h[k.to_s] = true if v
end
hash = routes.group_by { |_, r| r.score(supplied_keys) }
hash.keys.sort.reverse_each do |score|
break if score < 0

@ -1,198 +1,199 @@
#
# DO NOT MODIFY!!!!
# This file is automatically generated by Racc 1.4.11
# This file is automatically generated by Racc 1.4.14
# from Racc grammer file "".
#
require "racc/parser.rb"
require 'racc/parser.rb'
# :stopdoc:
require "action_dispatch/journey/parser_extras"
module ActionDispatch
# :stopdoc:
module Journey
class Parser < Racc::Parser
##### State transition tables begin ###
##### State transition tables begin ###
racc_action_table = [
13, 15, 14, 7, 21, 16, 8, 19, 13, 15,
14, 7, 17, 16, 8, 13, 15, 14, 7, 24,
16, 8, 13, 15, 14, 7, 19, 16, 8 ]
racc_action_table = [
13, 15, 14, 7, 19, 16, 8, 19, 13, 15,
14, 7, 17, 16, 8, 13, 15, 14, 7, 21,
16, 8, 13, 15, 14, 7, 24, 16, 8 ]
racc_action_check = [
2, 2, 2, 2, 17, 2, 2, 2, 0, 0,
0, 0, 1, 0, 0, 19, 19, 19, 19, 20,
19, 19, 7, 7, 7, 7, 22, 7, 7 ]
racc_action_check = [
2, 2, 2, 2, 22, 2, 2, 2, 19, 19,
19, 19, 1, 19, 19, 7, 7, 7, 7, 17,
7, 7, 0, 0, 0, 0, 20, 0, 0 ]
racc_action_pointer = [
6, 12, -2, nil, nil, nil, nil, 20, nil, nil,
nil, nil, nil, nil, nil, nil, nil, 4, nil, 13,
13, nil, 17, nil, nil ]
racc_action_pointer = [
20, 12, -2, nil, nil, nil, nil, 13, nil, nil,
nil, nil, nil, nil, nil, nil, nil, 19, nil, 6,
20, nil, -5, nil, nil ]
racc_action_default = [
-19, -19, -2, -3, -4, -5, -6, -19, -10, -11,
-12, -13, -14, -15, -16, -17, -18, -19, -1, -19,
-19, 25, -8, -9, -7 ]
racc_action_default = [
-19, -19, -2, -3, -4, -5, -6, -19, -10, -11,
-12, -13, -14, -15, -16, -17, -18, -19, -1, -19,
-19, 25, -8, -9, -7 ]
racc_goto_table = [
1, 22, 18, 23, nil, nil, nil, 20 ]
racc_goto_table = [
1, 22, 18, 23, nil, nil, nil, 20 ]
racc_goto_check = [
1, 2, 1, 3, nil, nil, nil, 1 ]
racc_goto_check = [
1, 2, 1, 3, nil, nil, nil, 1 ]
racc_goto_pointer = [
nil, 0, -18, -16, nil, nil, nil, nil, nil, nil,
nil ]
racc_goto_pointer = [
nil, 0, -18, -16, nil, nil, nil, nil, nil, nil,
nil ]
racc_goto_default = [
nil, nil, 2, 3, 4, 5, 6, 9, 10, 11,
12 ]
racc_goto_default = [
nil, nil, 2, 3, 4, 5, 6, 9, 10, 11,
12 ]
racc_reduce_table = [
0, 0, :racc_error,
2, 11, :_reduce_1,
1, 11, :_reduce_2,
1, 11, :_reduce_none,
1, 12, :_reduce_none,
1, 12, :_reduce_none,
1, 12, :_reduce_none,
3, 15, :_reduce_7,
3, 13, :_reduce_8,
3, 13, :_reduce_9,
1, 16, :_reduce_10,
1, 14, :_reduce_none,
1, 14, :_reduce_none,
1, 14, :_reduce_none,
1, 14, :_reduce_none,
1, 19, :_reduce_15,
1, 17, :_reduce_16,
1, 18, :_reduce_17,
1, 20, :_reduce_18 ]
racc_reduce_table = [
0, 0, :racc_error,
2, 11, :_reduce_1,
1, 11, :_reduce_2,
1, 11, :_reduce_none,
1, 12, :_reduce_none,
1, 12, :_reduce_none,
1, 12, :_reduce_none,
3, 15, :_reduce_7,
3, 13, :_reduce_8,
3, 13, :_reduce_9,
1, 16, :_reduce_10,
1, 14, :_reduce_none,
1, 14, :_reduce_none,
1, 14, :_reduce_none,
1, 14, :_reduce_none,
1, 19, :_reduce_15,
1, 17, :_reduce_16,
1, 18, :_reduce_17,
1, 20, :_reduce_18 ]
racc_reduce_n = 19
racc_reduce_n = 19
racc_shift_n = 25
racc_shift_n = 25
racc_token_table = {
false => 0,
:error => 1,
:SLASH => 2,
:LITERAL => 3,
:SYMBOL => 4,
:LPAREN => 5,
:RPAREN => 6,
:DOT => 7,
:STAR => 8,
:OR => 9 }
racc_token_table = {
false => 0,
:error => 1,
:SLASH => 2,
:LITERAL => 3,
:SYMBOL => 4,
:LPAREN => 5,
:RPAREN => 6,
:DOT => 7,
:STAR => 8,
:OR => 9 }
racc_nt_base = 10
racc_nt_base = 10
racc_use_result_var = false
racc_use_result_var = false
Racc_arg = [
racc_action_table,
racc_action_check,
racc_action_default,
racc_action_pointer,
racc_goto_table,
racc_goto_check,
racc_goto_default,
racc_goto_pointer,
racc_nt_base,
racc_reduce_table,
racc_token_table,
racc_shift_n,
racc_reduce_n,
racc_use_result_var ]
Racc_arg = [
racc_action_table,
racc_action_check,
racc_action_default,
racc_action_pointer,
racc_goto_table,
racc_goto_check,
racc_goto_default,
racc_goto_pointer,
racc_nt_base,
racc_reduce_table,
racc_token_table,
racc_shift_n,
racc_reduce_n,
racc_use_result_var ]
Racc_token_to_s_table = [
"$end",
"error",
"SLASH",
"LITERAL",
"SYMBOL",
"LPAREN",
"RPAREN",
"DOT",
"STAR",
"OR",
"$start",
"expressions",
"expression",
"or",
"terminal",
"group",
"star",
"symbol",
"literal",
"slash",
"dot" ]
Racc_token_to_s_table = [
"$end",
"error",
"SLASH",
"LITERAL",
"SYMBOL",
"LPAREN",
"RPAREN",
"DOT",
"STAR",
"OR",
"$start",
"expressions",
"expression",
"or",
"terminal",
"group",
"star",
"symbol",
"literal",
"slash",
"dot" ]
Racc_debug_parser = false
Racc_debug_parser = false
##### State transition tables end #####
##### State transition tables end #####
# reduce 0 omitted
# reduce 0 omitted
def _reduce_1(val, _values)
Cat.new(val.first, val.last)
end
def _reduce_1(val, _values)
Cat.new(val.first, val.last)
end
def _reduce_2(val, _values)
val.first
end
def _reduce_2(val, _values)
val.first
end
# reduce 3 omitted
# reduce 3 omitted
# reduce 4 omitted
# reduce 4 omitted
# reduce 5 omitted
# reduce 5 omitted
# reduce 6 omitted
# reduce 6 omitted
def _reduce_7(val, _values)
Group.new(val[1])
end
def _reduce_7(val, _values)
Group.new(val[1])
end
def _reduce_8(val, _values)
Or.new([val.first, val.last])
end
def _reduce_8(val, _values)
Or.new([val.first, val.last])
end
def _reduce_9(val, _values)
Or.new([val.first, val.last])
end
def _reduce_9(val, _values)
Or.new([val.first, val.last])
end
def _reduce_10(val, _values)
Star.new(Symbol.new(val.last))
end
def _reduce_10(val, _values)
Star.new(Symbol.new(val.last))
end
# reduce 11 omitted
# reduce 11 omitted
# reduce 12 omitted
# reduce 12 omitted
# reduce 13 omitted
# reduce 13 omitted
# reduce 14 omitted
# reduce 14 omitted
def _reduce_15(val, _values)
Slash.new("/")
end
def _reduce_15(val, _values)
Slash.new(val.first)
end
def _reduce_16(val, _values)
Symbol.new(val.first)
end
def _reduce_16(val, _values)
Symbol.new(val.first)
end
def _reduce_17(val, _values)
Literal.new(val.first)
end
def _reduce_17(val, _values)
Literal.new(val.first)
end
def _reduce_18(val, _values)
Dot.new(val.first)
end
def _reduce_18(val, _values)
Dot.new(val.first)
end
def _reduce_none(val, _values)
val[0]
end
def _reduce_none(val, _values)
val[0]
end
end # class Parser
end # module Journey
# :startdoc:
end # module ActionDispatch
end # module Journey
end # module ActionDispatch

@ -30,7 +30,7 @@ rule
| dot
;
slash
: SLASH { Slash.new('/') }
: SLASH { Slash.new(val.first) }
;
symbol
: SYMBOL { Symbol.new(val.first) }
@ -45,5 +45,6 @@ rule
end
---- header
# :stopdoc:
require 'action_dispatch/journey/parser_extras'
require "action_dispatch/journey/parser_extras"

@ -96,13 +96,18 @@ def required_keys
required_parts + required_defaults.keys
end
def score(constraints)
def score(supplied_keys)
required_keys = path.required_names
supplied_keys = constraints.map { |k, v| v && k.to_s }.compact
return -1 unless (required_keys - supplied_keys).empty?
required_keys.each do |k|
return -1 unless supplied_keys.include?(k)
end
score = 0
path.names.each do |k|
score += 1 if supplied_keys.include?(k)
end
score = (supplied_keys & path.names).length
score + (required_defaults.length * 2)
end

@ -58,12 +58,12 @@ def unescape_uri(uri)
uri.gsub(ESCAPED) { |match| [match[1, 2].hex].pack("C") }.force_encoding(encoding)
end
protected
def escape(component, pattern)
private
def escape(component, pattern) # :doc:
component.gsub(pattern) { |unsafe| percent_encode(unsafe) }.force_encoding(US_ASCII)
end
def percent_encode(unsafe)
def percent_encode(unsafe) # :doc:
safe = EMPTY.dup
unsafe.each_byte { |b| safe << DEC2HEX[b] }
safe

@ -1,3 +1,4 @@
# frozen_string_literal: true
require "strscan"
module ActionDispatch
@ -35,22 +36,23 @@ def next_token
def scan
case
# /
when text = @ss.scan(/\//)
[:SLASH, text]
when @ss.skip(/\//)
[:SLASH, "/"]
when @ss.skip(/\(/)
[:LPAREN, "("]
when @ss.skip(/\)/)
[:RPAREN, ")"]
when @ss.skip(/\|/)
[:OR, "|"]
when @ss.skip(/\./)
[:DOT, "."]
when text = @ss.scan(/:\w+/)
[:SYMBOL, text]
when text = @ss.scan(/\*\w+/)
[:STAR, text]
when text = @ss.scan(/(?<!\\)\(/)
[:LPAREN, text]
when text = @ss.scan(/(?<!\\)\)/)
[:RPAREN, text]
when text = @ss.scan(/\|/)
[:OR, text]
when text = @ss.scan(/\./)
[:DOT, text]
when text = @ss.scan(/(?<!\\):\w+/)
[:SYMBOL, text]
when text = @ss.scan(/(?:[\w%\-~!$&'*+,;=@]|\\:|\\\(|\\\))+/)
[:LITERAL, text.tr('\\', "")]
when text = @ss.scan(/(?:[\w%\-~!$&'*+,;=@]|\\[:()])+/)
text.tr! "\\", ""
[:LITERAL, text]
# any char
when text = @ss.scan(/./)
[:LITERAL, text]

@ -281,7 +281,8 @@ def now_is_loaded?
@now
end
def stringify_array(array)
private
def stringify_array(array) # :doc:
array.map do |item|
item.kind_of?(Symbol) ? item.to_s : item
end

@ -153,9 +153,9 @@ def to_s
@ip ||= calculate_ip
end
protected
private
def ips_from(header)
def ips_from(header) # :doc:
return [] unless header
# Split the comma-separated list into an array of strings
ips = header.strip.split(/[,\s]+/)
@ -171,7 +171,7 @@ def ips_from(header)
end
end
def filter_proxies(ips)
def filter_proxies(ips) # :doc:
ips.reject do |ip|
@proxies.any? { |proxy| proxy === ip }
end

@ -27,17 +27,16 @@ def generate_sid
sid
end
protected
private
def initialize_sid
def initialize_sid # :doc:
@default_options.delete(:sidbits)
@default_options.delete(:secure_random)
end
private
def make_request(env)
ActionDispatch::Request.new env
end
def make_request(env)
ActionDispatch::Request.new env
end
end
module StaleSessionCheck

@ -4,6 +4,17 @@ class Utils # :nodoc:
mattr_accessor :perform_deep_munge
self.perform_deep_munge = true
def self.each_param_value(params, &block)
case params
when Array
params.each { |element| each_param_value(element, &block) }
when Hash
params.each_value { |value| each_param_value(value, &block) }
when String
block.call params
end
end
def self.normalize_encode_params(params)
if perform_deep_munge
NoNilParamEncoder.normalize_encode_params params

@ -1,4 +1,4 @@
require 'active_support/core_ext/string/filters'
require "active_support/core_ext/string/filters"
module ActionDispatch
# The routing module provides URL rewriting in native Ruby. It's a way to

@ -996,65 +996,65 @@ def defaults(defaults = {})
end
private
def merge_path_scope(parent, child) #:nodoc:
def merge_path_scope(parent, child)
Mapper.normalize_path("#{parent}/#{child}")
end
def merge_shallow_path_scope(parent, child) #:nodoc:
def merge_shallow_path_scope(parent, child)
Mapper.normalize_path("#{parent}/#{child}")
end
def merge_as_scope(parent, child) #:nodoc:
def merge_as_scope(parent, child)
parent ? "#{parent}_#{child}" : child
end
def merge_shallow_prefix_scope(parent, child) #:nodoc:
def merge_shallow_prefix_scope(parent, child)
parent ? "#{parent}_#{child}" : child
end
def merge_module_scope(parent, child) #:nodoc:
def merge_module_scope(parent, child)
parent ? "#{parent}/#{child}" : child
end
def merge_controller_scope(parent, child) #:nodoc:
def merge_controller_scope(parent, child)
child
end
def merge_action_scope(parent, child) #:nodoc:
def merge_action_scope(parent, child)
child
end
def merge_via_scope(parent, child) #:nodoc:
def merge_via_scope(parent, child)
child
end
def merge_format_scope(parent, child) #:nodoc:
def merge_format_scope(parent, child)
child
end
def merge_path_names_scope(parent, child) #:nodoc:
def merge_path_names_scope(parent, child)
merge_options_scope(parent, child)
end
def merge_constraints_scope(parent, child) #:nodoc:
def merge_constraints_scope(parent, child)
merge_options_scope(parent, child)
end
def merge_defaults_scope(parent, child) #:nodoc:
def merge_defaults_scope(parent, child)
merge_options_scope(parent, child)
end
def merge_blocks_scope(parent, child) #:nodoc:
def merge_blocks_scope(parent, child)
merged = parent ? parent.dup : []
merged << child if child
merged
end
def merge_options_scope(parent, child) #:nodoc:
def merge_options_scope(parent, child)
(parent || {}).merge(child)
end
def merge_shallow_scope(parent, child) #:nodoc:
def merge_shallow_scope(parent, child)
child ? true : false
end
@ -1619,13 +1619,13 @@ def root(path, options = {})
end
end
protected
private
def parent_resource #:nodoc:
def parent_resource
@scope[:scope_level_resource]
end
def apply_common_behavior_for(method, resources, options, &block) #:nodoc:
def apply_common_behavior_for(method, resources, options, &block)
if resources.length > 1
resources.each { |r| send(method, r, options, &block) }
return true
@ -1658,39 +1658,39 @@ def apply_common_behavior_for(method, resources, options, &block) #:nodoc:
false
end
def apply_action_options(options) # :nodoc:
def apply_action_options(options)
return options if action_options? options
options.merge scope_action_options
end
def action_options?(options) #:nodoc:
def action_options?(options)
options[:only] || options[:except]
end
def scope_action_options #:nodoc:
def scope_action_options
@scope[:action_options] || {}
end
def resource_scope? #:nodoc:
def resource_scope?
@scope.resource_scope?
end
def resource_method_scope? #:nodoc:
def resource_method_scope?
@scope.resource_method_scope?
end
def nested_scope? #:nodoc:
def nested_scope?
@scope.nested?
end
def with_scope_level(kind)
def with_scope_level(kind) # :doc:
@scope = @scope.new_level(kind)
yield
ensure
@scope = @scope.parent
end
def resource_scope(resource) #:nodoc:
def resource_scope(resource)
@scope = @scope.new(scope_level_resource: resource)
controller(resource.resource_scope) { yield }
@ -1698,7 +1698,7 @@ def resource_scope(resource) #:nodoc:
@scope = @scope.parent
end
def nested_options #:nodoc:
def nested_options
options = { as: parent_resource.member_name }
options[:constraints] = {
parent_resource.nested_param => param_constraint
@ -1707,25 +1707,25 @@ def nested_options #:nodoc:
options
end
def shallow_nesting_depth #:nodoc:
def shallow_nesting_depth
@scope.find_all { |node|
node.frame[:scope_level_resource]
}.count { |node| node.frame[:scope_level_resource].shallow? }
end
def param_constraint? #:nodoc:
def param_constraint?
@scope[:constraints] && @scope[:constraints][parent_resource.param].is_a?(Regexp)
end
def param_constraint #:nodoc:
def param_constraint
@scope[:constraints][parent_resource.param]
end
def canonical_action?(action) #:nodoc:
def canonical_action?(action)
resource_method_scope? && CANONICAL_ACTIONS.include?(action.to_s)
end
def shallow_scope #:nodoc:
def shallow_scope
scope = { as: @scope[:shallow_prefix],
path: @scope[:shallow_path] }
@scope = @scope.new scope
@ -1735,7 +1735,7 @@ def shallow_scope #:nodoc:
@scope = @scope.parent
end
def path_for_action(action, path) #:nodoc:
def path_for_action(action, path)
return "#{@scope[:path]}/#{path}" if path
if canonical_action?(action)
@ -1745,11 +1745,11 @@ def path_for_action(action, path) #:nodoc:
end
end
def action_path(name) #:nodoc:
def action_path(name)
@scope[:path_names][name.to_sym] || name
end
def prefix_name_for_action(as, action) #:nodoc:
def prefix_name_for_action(as, action)
if as
prefix = as
elsif !canonical_action?(action)
@ -1761,7 +1761,7 @@ def prefix_name_for_action(as, action) #:nodoc:
end
end
def name_for_action(as, action) #:nodoc:
def name_for_action(as, action)
prefix = prefix_name_for_action(as, action)
name_prefix = @scope[:as]
@ -1787,7 +1787,7 @@ def name_for_action(as, action) #:nodoc:
end
end
def set_member_mappings_for_resource
def set_member_mappings_for_resource # :doc:
member do
get :edit if parent_resource.actions.include?(:edit)
get :show if parent_resource.actions.include?(:show)
@ -1799,12 +1799,10 @@ def set_member_mappings_for_resource
end
end
def api_only?
def api_only? # :doc:
@set.api_only?
end
private
def path_scope(path)
@scope = @scope.new(path: merge_path_scope(@scope[:path], path))
yield
@ -1868,7 +1866,7 @@ def using_match_shorthand?(path)
path =~ %r{^/?[-\w]+/[-\w/]+$}
end
def decomposed_match(path, controller, options, _path, to, via, formatted, anchor, options_constraints) # :nodoc:
def decomposed_match(path, controller, options, _path, to, via, formatted, anchor, options_constraints)
if on = options.delete(:on)
send(on) { decomposed_match(path, controller, options, _path, to, via, formatted, anchor, options_constraints) }
else
@ -1883,7 +1881,7 @@ def decomposed_match(path, controller, options, _path, to, via, formatted, ancho
end
end
def add_route(action, controller, options, _path, to, via, formatted, anchor, options_constraints) # :nodoc:
def add_route(action, controller, options, _path, to, via, formatted, anchor, options_constraints)
path = path_for_action(action, _path)
raise ArgumentError, "path is required" if path.blank?

@ -198,14 +198,16 @@ def optimize_routes_generation?
_routes.optimize_routes_generation? && default_url_options.empty?
end
def _with_routes(routes)
private
def _with_routes(routes) # :doc:
old_routes, @_routes = @_routes, routes
yield
ensure
@_routes = old_routes
end
def _routes_context
def _routes_context # :doc:
self
end
end

@ -69,7 +69,7 @@ class Session
DEFAULT_HOST = "www.example.com"
include Minitest::Assertions
include RequestHelpers, Assertions
include TestProcess, RequestHelpers, Assertions
%w( status status_message headers body redirect? ).each do |method|
delegate method, to: :response, allow_nil: true
@ -598,7 +598,7 @@ def method_missing(sym, *args, &block)
# Consult the Rails Testing Guide for more.
class IntegrationTest < ActiveSupport::TestCase
include TestProcess
include TestProcess::FixtureFile
module UrlOptions
extend ActiveSupport::Concern

@ -3,6 +3,26 @@
module ActionDispatch
module TestProcess
module FixtureFile
# Shortcut for <tt>Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.fixture_path, path), type)</tt>:
#
# post :change_avatar, avatar: fixture_file_upload('files/spongebob.png', 'image/png')
#
# To upload binary files on Windows, pass <tt>:binary</tt> as the last parameter.
# This will not affect other platforms:
#
# post :change_avatar, avatar: fixture_file_upload('files/spongebob.png', 'image/png', :binary)
def fixture_file_upload(path, mime_type = nil, binary = false)
if self.class.respond_to?(:fixture_path) && self.class.fixture_path &&
!File.exist?(path)
path = File.join(self.class.fixture_path, path)
end
Rack::Test::UploadedFile.new(path, mime_type, binary)
end
end
include FixtureFile
def assigns(key = nil)
raise NoMethodError,
"assigns has been extracted to a gem. To continue using it,
@ -24,21 +44,5 @@ def cookies
def redirect_to_url
@response.redirect_url
end
# Shortcut for <tt>Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.fixture_path, path), type)</tt>:
#
# post :change_avatar, avatar: fixture_file_upload('files/spongebob.png', 'image/png')
#
# To upload binary files on Windows, pass <tt>:binary</tt> as the last parameter.
# This will not affect other platforms:
#
# post :change_avatar, avatar: fixture_file_upload('files/spongebob.png', 'image/png', :binary)
def fixture_file_upload(path, mime_type = nil, binary = false)
if self.class.respond_to?(:fixture_path) && self.class.fixture_path &&
!File.exist?(path)
path = File.join(self.class.fixture_path, path)
end
Rack::Test::UploadedFile.new(path, mime_type, binary)
end
end
end

@ -55,7 +55,7 @@ class TestMultipleFiltersController < ActionController::Base
end
end
protected
private
(1..3).each do |i|
define_method "try_#{i}" do
instance_variable_set :@try, i
@ -296,7 +296,7 @@ def change_password
render inline: "ran action"
end
protected
private
def find_user
@ran_filter ||= []
@ran_filter << "find_user"
@ -428,7 +428,7 @@ def bar
render plain: "bar"
end
protected
private
def first
@first = true
end
@ -1040,7 +1040,7 @@ def test_last_action_in_multiple_before_action_chain_halts
assert_equal 3, controller.instance_variable_get(:@try)
end
protected
private
def test_process(controller, action = "show")
@controller = controller.is_a?(Class) ? controller.new : controller
process(action)

@ -63,10 +63,10 @@ def test_to_session_value
assert_equal({ "flashes" => { "foo" => "bar" }, "discard" => [] }, @hash.to_session_value)
@hash.discard("foo")
assert_equal(nil, @hash.to_session_value)
assert_nil(@hash.to_session_value)
@hash.sweep
assert_equal(nil, @hash.to_session_value)
assert_nil(@hash.to_session_value)
end
def test_from_session_value
@ -75,7 +75,7 @@ def test_from_session_value
session = Marshal.load(Base64.decode64(rails_3_2_cookie))
hash = Flash::FlashHash.from_session_value(session["flash"])
assert_equal({ "greeting" => "Hello" }, hash.to_hash)
assert_equal(nil, hash.to_session_value)
assert_nil(hash.to_session_value)
end
def test_from_session_value_on_json_serializer
@ -84,7 +84,7 @@ def test_from_session_value_on_json_serializer
hash = Flash::FlashHash.from_session_value(session["flash"])
assert_equal({ "greeting" => "Hello" }, hash.to_hash)
assert_equal(nil, hash.to_session_value)
assert_nil(hash.to_session_value)
assert_equal "Hello", hash[:greeting]
assert_equal "Hello", hash["greeting"]
end

@ -166,8 +166,7 @@ def authenticate_long_credentials
test "token_and_options returns nil with no value after the equal sign" do
actual = ActionController::HttpAuthentication::Token.token_and_options(malformed_request).first
expected = nil
assert_equal(expected, actual)
assert_nil actual
end
test "raw_params returns a tuple of two key value pair strings" do

@ -289,7 +289,7 @@ def test_post
assert_response :success
assert_equal "bar", body
assert_equal nil, headers["Set-Cookie"]
assert_nil headers["Set-Cookie"]
assert_equal({ "foo" => "bar" }, cookies.to_hash)
end
end
@ -308,7 +308,7 @@ def test_post
assert_response :success
assert_equal "bar", body
assert_equal nil, headers["Set-Cookie"]
assert_nil headers["Set-Cookie"]
assert_equal({ "foo" => "bar" }, cookies.to_hash)
end
end

@ -40,7 +40,7 @@ def index
respond_to(:html, :iphone, :js)
end
protected
private
def with_iphone
request.format = "iphone" if request.env["HTTP_ACCEPT"] == "text/iphone"

@ -273,7 +273,7 @@ def format_any_variant_any
end
end
protected
private
def set_layout
case action_name
when "all_types_with_layout", "iphone_with_html_response_type"

@ -52,7 +52,7 @@ class BareEmptyTest < ActiveSupport::TestCase
controller.set_request!(ActionDispatch::Request.empty)
controller.set_response!(BareController.make_response!(controller.request))
controller.index
assert_equal nil, controller.response_body
assert_nil controller.response_body
end
end

@ -25,7 +25,7 @@ def show_actions
render body: "actions: #{action_methods.to_a.sort.join(', ')}"
end
protected
private
def authenticate
end
end

@ -26,16 +26,14 @@ def with_layout
render action: "hello_world", layout: "basic"
end
protected
protected def __controller_method__
"controller context!"
end
# 3) Set view_context to self
def view_context
self
end
def __controller_method__
"controller context!"
end
# 3) Set view_context to self
private def view_context
self
end
end
class RenderContextTest < Rack::TestCase

@ -101,12 +101,12 @@ class StreamingTest < Rack::TestCase
assert_body "Hello world, I'm here!"
assert_status 200
assert_equal "22", headers["Content-Length"]
assert_equal nil, headers["Transfer-Encoding"]
assert_nil headers["Transfer-Encoding"]
end
def assert_streaming!(cache = "no-cache")
assert_status 200
assert_equal nil, headers["Content-Length"]
assert_nil headers["Content-Length"]
assert_equal "chunked", headers["Transfer-Encoding"]
assert_equal cache, headers["Cache-Control"]
end

@ -1,9 +1,8 @@
require "abstract_unit"
class ParameterEncodingController < ActionController::Base
parameter_encoding :test_bar, :bar, Encoding::ASCII_8BIT
parameter_encoding :test_baz, :baz, Encoding::ISO_8859_1
parameter_encoding :test_baz_to_ascii, :baz, Encoding::ASCII_8BIT
skip_parameter_encoding :test_bar
skip_parameter_encoding :test_all_values_encoding
def test_foo
render body: params[:foo].encoding
@ -13,16 +12,8 @@ def test_bar
render body: params[:bar].encoding
end
def test_baz
render body: params[:baz].encoding
end
def test_no_change_to_baz
render body: params[:baz].encoding
end
def test_baz_to_ascii
render body: params[:baz].encoding
def test_all_values_encoding
render body: ::JSON.dump(params.values.map(&:encoding).map(&:name))
end
end
@ -36,32 +27,18 @@ class ParameterEncodingTest < ActionController::TestCase
assert_equal "UTF-8", @response.body
end
test "properly transcodes ASCII_8BIT parameters into declared encodings" do
test "properly encodes ASCII_8BIT parameters into binary" do
post :test_bar, params: { "foo" => "foo", "bar" => "bar", "baz" => "baz" }
assert_response :success
assert_equal "ASCII-8BIT", @response.body
end
test "properly transcodes ISO_8859_1 parameters into declared encodings" do
post :test_baz, params: { "foo" => "foo", "bar" => "bar", "baz" => "baz" }
test "properly encodes all ASCII_8BIT parameters into binary" do
post :test_all_values_encoding, params: { "foo" => "foo", "bar" => "bar", "baz" => "baz" }
assert_response :success
assert_equal "ISO-8859-1", @response.body
end
test "does not transcode parameters when not specified" do
post :test_no_change_to_baz, params: { "foo" => "foo", "bar" => "bar", "baz" => "baz" }
assert_response :success
assert_equal "UTF-8", @response.body
end
test "respects different encoding declarations for a param per action" do
post :test_baz_to_ascii, params: { "foo" => "foo", "bar" => "bar", "baz" => "baz" }
assert_response :success
assert_equal "ASCII-8BIT", @response.body
assert_equal ["ASCII-8BIT"], JSON.parse(@response.body).uniq
end
test "does not raise an error when passed a param declared as ASCII-8BIT that contains invalid bytes" do

@ -141,7 +141,7 @@ def walk_permitted(params)
permitted = params.permit(:a, c: [], b: [])
assert_equal 1, permitted[:a]
assert_equal [1, 2, 3], permitted[:b]
assert_equal nil, permitted[:c]
assert_nil permitted[:c]
end
test "key to empty array: arrays of permitted scalars pass" do
@ -216,7 +216,7 @@ def walk_permitted(params)
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]
assert_nil params[:foo]
end
test "hashes in array values get wrapped" do
@ -254,8 +254,8 @@ def walk_permitted(params)
end
test "fetch doesnt raise ParameterMissing exception if there is a default that is nil" do
assert_equal nil, @params.fetch(:foo, nil)
assert_equal nil, @params.fetch(:foo) { nil }
assert_nil @params.fetch(:foo, nil)
assert_nil @params.fetch(:foo) { nil }
end
test "KeyError in fetch block should not be covered up" do

@ -50,7 +50,7 @@ def test_filtered_parameters
with_default_wrapper_options do
@request.env["CONTENT_TYPE"] = "application/json"
post :parse, params: { "username" => "sikachu" }
assert_equal @request.filtered_parameters, "controller" => "params_wrapper_test/users", "action" => "parse", "username" => "sikachu", "user" => { "username" => "sikachu" }
assert_equal({ "controller" => "params_wrapper_test/users", "action" => "parse", "username" => "sikachu", "user" => { "username" => "sikachu" } }, @request.filtered_parameters)
end
end

@ -123,7 +123,7 @@ def redirect_with_null_bytes
def rescue_errors(e) raise e end
protected
private
def dashbord_url(id, message)
url_for action: "dashboard", params: { "id" => id, "message" => message }
end

@ -8,7 +8,7 @@ def test_test_request_has_session_options_initialized
def test_mutating_session_options_does_not_affect_default_options
@request.session_options[:myparam] = 123
assert_equal nil, ActionController::TestSession::DEFAULT_OPTIONS[:myparam]
assert_nil ActionController::TestSession::DEFAULT_OPTIONS[:myparam]
end
def test_content_length_has_bytes_count_value
@ -17,8 +17,8 @@ def test_content_length_has_bytes_count_value
@request.set_header "CONTENT_TYPE", "application/json"
@request.assign_parameters(@routes, "test", "create", non_ascii_parameters,
"/test", [:data, :controller, :action])
assert_equal(@request.get_header("CONTENT_LENGTH"),
StringIO.new(non_ascii_parameters.to_json).length.to_s)
assert_equal(StringIO.new(non_ascii_parameters.to_json).length.to_s,
@request.get_header("CONTENT_LENGTH"))
end
ActionDispatch::Session::AbstractStore::DEFAULT_OPTIONS.each_key do |option|

@ -92,7 +92,7 @@ def index
render inline: "OK"
end
protected
private
def add_called_callback(name)
@called_callbacks ||= []

@ -149,7 +149,7 @@ def exception_with_no_handler_for_wrapper
raise RangeError
end
protected
private
def deny_access
head :forbidden
end
@ -327,7 +327,7 @@ def b00m
raise "b00m"
end
protected
private
def show_errors(exception)
render plain: exception.message
end

@ -1089,7 +1089,7 @@ def test_singleton_resource_name_is_not_singularized
end
end
protected
private
def with_restful_routing(*args)
options = args.extract_options!
collection_methods = options.delete(:collection)

@ -241,10 +241,17 @@ def test_send_file_charset_with_type_options_key
assert_equal "text/calendar; charset=utf-8", response.headers["Content-Type"]
end
def test_send_file_charset_with_type_options_key_without_charset
@controller = SendFileWithActionControllerLive.new
@controller.options = { type: "image/png" }
response = process("file")
assert_equal "image/png", response.headers["Content-Type"]
end
def test_send_file_charset_with_content_type_options_key
@controller = SendFileWithActionControllerLive.new
@controller.options = { content_type: "text/calendar" }
response = process("file")
assert_equal "text/calendar; charset=utf-8", response.headers["Content-Type"]
assert_equal "text/calendar", response.headers["Content-Type"]
end
end

@ -100,11 +100,11 @@ def test_html_output
end
def test_xml_output
response.content_type = "application/xml"
response.content_type = params[:response_as]
render plain: <<XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
<area>area is an empty tag in HTML, raising an error if not in xml mode</area>
<area><p>area is an empty tag in HTML, so it won't contain this content</p></area>
</root>
XML
end
@ -374,18 +374,18 @@ def test_multiple_calls
assert_equal "OK", @response.body
end
def test_should_impose_childless_html_tags_in_html
process :test_xml_output, params: { response_as: "text/html" }
# <area> auto-closes, so the <p> becomes a sibling
assert_select "root > area + p"
end
def test_should_not_impose_childless_html_tags_in_xml
process :test_xml_output
process :test_xml_output, params: { response_as: "application/xml" }
begin
$stderr = StringIO.new
assert_select "area" #This will cause a warning if content is processed as HTML
$stderr.rewind && err = $stderr.read
ensure
$stderr = STDERR
end
assert err.empty?, err.inspect
# <area> is not special, so the <p> is its child
assert_select "root > area > p"
end
def test_assert_generates

@ -487,6 +487,27 @@ def test_url_for_with_array_is_unmodified
end
end
def test_default_params_first_empty
with_routing do |set|
set.draw do
get "(:param1)/test(/:param2)" => "index#index",
defaults: {
param1: 1,
param2: 2
},
constraints: {
param1: /\d*/,
param2: /\d+/
}
end
kls = Class.new { include set.url_helpers }
kls.default_url_options[:host] = "www.basecamphq.com"
assert_equal "http://www.basecamphq.com/test", kls.new.url_for(controller: "index", param1: "1")
end
end
private
def extract_params(url)
url.split("?", 2).last.split("&").sort

@ -272,6 +272,10 @@ def string_key_mock
def noop
head :ok
end
def encrypted_cookie
cookies.encrypted["foo"]
end
end
tests TestController
@ -940,8 +944,8 @@ def test_legacy_signed_cookie_is_treated_as_nil_by_signed_cookie_jar_if_tampered
@request.headers["Cookie"] = "user_id=45"
get :get_signed_cookie
assert_equal nil, @controller.send(:cookies).signed[:user_id]
assert_equal nil, @response.cookies["user_id"]
assert_nil @controller.send(:cookies).signed[:user_id]
assert_nil @response.cookies["user_id"]
end
def test_legacy_signed_cookie_is_treated_as_nil_by_encrypted_cookie_jar_if_tampered
@ -951,8 +955,8 @@ def test_legacy_signed_cookie_is_treated_as_nil_by_encrypted_cookie_jar_if_tampe
@request.headers["Cookie"] = "foo=baz"
get :get_encrypted_cookie
assert_equal nil, @controller.send(:cookies).encrypted[:foo]
assert_equal nil, @response.cookies["foo"]
assert_nil @controller.send(:cookies).encrypted[:foo]
assert_nil @response.cookies["foo"]
end
def test_cookie_with_all_domain_option
@ -1189,6 +1193,12 @@ def test_cookies_precedence_over_request_cookies
assert_equal "david", cookies[:user_name]
end
def test_cookies_are_not_cleared
cookies.encrypted["foo"] = "bar"
get :noop
assert_equal "bar", @controller.encrypted_cookie
end
private
def assert_cookie_header(expected)
header = @response.headers["Set-Cookie"]

@ -129,7 +129,7 @@ def teardown
params = parse_multipart("none")
assert_equal %w(submit-name), params.keys.sort
assert_equal "Larry", params["submit-name"]
assert_equal nil, params["files"]
assert_nil params["files"]
end
test "parses empty upload file" do

@ -18,7 +18,7 @@ def url_for(options = {})
ActionDispatch::Http::URL.url_for(options)
end
protected
private
def stub_request(env = {})
ip_spoofing_check = env.key?(:ip_spoofing_check) ? env.delete(:ip_spoofing_check) : true
@trusted_proxies ||= nil
@ -94,13 +94,13 @@ class RequestIP < BaseRequestTest
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "unknown,192.168.0.1"
assert_equal nil, request.remote_ip
assert_nil request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "9.9.9.9, 3.4.5.6, 172.31.4.4, 10.0.0.1"
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "not_ip_address"
assert_equal nil, request.remote_ip
assert_nil request.remote_ip
end
test "remote ip spoof detection" do
@ -154,7 +154,7 @@ class RequestIP < BaseRequestTest
assert_equal "fe80:0000:0000:0000:0202:b3ff:fe1e:8329", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "unknown,::1"
assert_equal nil, request.remote_ip
assert_nil request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "2001:0db8:85a3:0000:0000:8a2e:0370:7334, fe80:0000:0000:0000:0202:b3ff:fe1e:8329, ::1, fc00::, fc01::, fdff"
assert_equal "fe80:0000:0000:0000:0202:b3ff:fe1e:8329", request.remote_ip
@ -163,7 +163,7 @@ class RequestIP < BaseRequestTest
assert_equal "FE00::", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "not_ip_address"
assert_equal nil, request.remote_ip
assert_nil request.remote_ip
end
test "remote ip v6 spoof detection" do
@ -200,7 +200,7 @@ class RequestIP < BaseRequestTest
assert_equal "3.4.5.6", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "67.205.106.73,unknown"
assert_equal nil, request.remote_ip
assert_nil request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "9.9.9.9, 3.4.5.6, 10.0.0.1, 67.205.106.73"
assert_equal "3.4.5.6", request.remote_ip
@ -222,7 +222,7 @@ class RequestIP < BaseRequestTest
assert_equal "::1", request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329"
assert_equal nil, request.remote_ip
assert_nil request.remote_ip
request = stub_request "HTTP_X_FORWARDED_FOR" => "fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334"
assert_equal "2001:0db8:85a3:0000:0000:8a2e:0370:7334", request.remote_ip
@ -345,7 +345,7 @@ class RequestPort < BaseRequestTest
test "optional port" do
request = stub_request "HTTP_HOST" => "www.example.org:80"
assert_equal nil, request.optional_port
assert_nil request.optional_port
request = stub_request "HTTP_HOST" => "www.example.org:8080"
assert_equal 8080, request.optional_port
@ -537,7 +537,7 @@ class RequestCGI < BaseRequestTest
assert_equal "Basic", request.auth_type
assert_equal 0, request.content_length
assert_equal nil, request.content_mime_type
assert_nil request.content_mime_type
assert_equal "CGI/1.1", request.gateway_interface
assert_equal "*/*", request.accept
assert_equal "UTF-8", request.accept_charset
@ -957,7 +957,7 @@ class RequestMimeType < BaseRequestTest
end
test "no content type" do
assert_equal nil, stub_request.content_mime_type
assert_nil stub_request.content_mime_type
end
test "content type is XML" do
@ -978,7 +978,7 @@ class RequestMimeType < BaseRequestTest
"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"
)
assert_equal nil, request.negotiate_mime([Mime[:xml], Mime[:json]])
assert_nil request.negotiate_mime([Mime[:xml], Mime[:json]])
assert_equal Mime[:html], request.negotiate_mime([Mime[:xml], Mime[:html]])
assert_equal Mime[:html], request.negotiate_mime([Mime[:xml], Mime::ALL])
end
@ -1192,7 +1192,7 @@ class RequestEtag < BaseRequestTest
test "doesn't match absent If-None-Match" do
request = stub_request
assert_equal nil, request.if_none_match
assert_nil request.if_none_match
assert_equal [], request.if_none_match_etags
assert_not request.etag_matches?("foo")

@ -74,7 +74,7 @@ def test_read_body_during_action
@response.body = "Hello, World!"
# even though there's no explicitly set content-type,
assert_equal nil, @response.content_type
assert_nil @response.content_type
# after the action reads back @response.body,
assert_equal "Hello, World!", @response.body
@ -110,6 +110,11 @@ def test_setting_content_type_header_impacts_content_type_method
assert_equal "application/aaron", @response.content_type
end
def test_empty_content_type_returns_nil
@response.headers["Content-Type"] = ""
assert_nil @response.content_type
end
test "simple output" do
@response.body = "Hello, World!"

@ -7,7 +7,7 @@ class IPv6IntegrationTest < ActionDispatch::IntegrationTest
class ::BadRouteRequestController < ActionController::Base
include Routes.url_helpers
def index
render text: foo_path
render plain: foo_path
end
def foo

@ -4189,7 +4189,7 @@ def app; APP end
test "parameters are reset between constraint checks" do
get "/bar"
assert_equal nil, @request.params[:foo]
assert_nil @request.params[:foo]
assert_equal "bar", @request.params[:bar]
end
end

@ -142,20 +142,20 @@ def test_doesnt_write_session_cookie_if_session_id_is_already_exists
get "/get_session_value"
assert_response :success
assert_equal nil, headers["Set-Cookie"], "should not resend the cookie again if session_id cookie is already exists"
assert_nil headers["Set-Cookie"], "should not resend the cookie again if session_id cookie is already exists"
end
end
def test_prevents_session_fixation
with_test_route_set do
assert_equal nil, @cache.read("_session_id:0xhax")
assert_nil @cache.read("_session_id:0xhax")
cookies["_session_id"] = "0xhax"
get "/set_session_value"
assert_response :success
assert_not_equal "0xhax", cookies["_session_id"]
assert_equal nil, @cache.read("_session_id:0xhax")
assert_nil @cache.read("_session_id:0xhax")
assert_equal({ "foo" => "bar" }, @cache.read("_session_id:#{cookies['_session_id']}"))
end
end

@ -108,7 +108,7 @@ def test_does_not_set_secure_cookies_over_http
with_test_route_set(secure: true) do
get "/set_session_value"
assert_response :success
assert_equal nil, headers["Set-Cookie"]
assert_nil headers["Set-Cookie"]
end
end
@ -169,7 +169,7 @@ def test_doesnt_write_session_cookie_if_session_is_not_accessed
with_test_route_set do
get "/no_session_access"
assert_response :success
assert_equal nil, headers["Set-Cookie"]
assert_nil headers["Set-Cookie"]
end
end
@ -179,7 +179,7 @@ def test_doesnt_write_session_cookie_if_session_is_unchanged
"fef868465920f415f2c0652d6910d3af288a0367"
get "/no_session_access"
assert_response :success
assert_equal nil, headers["Set-Cookie"]
assert_nil headers["Set-Cookie"]
end
end

@ -157,7 +157,7 @@ def test_doesnt_write_session_cookie_if_session_id_is_already_exists
get "/get_session_value"
assert_response :success
assert_equal nil, headers["Set-Cookie"], "should not resend the cookie again if session_id cookie is already exists"
assert_nil headers["Set-Cookie"], "should not resend the cookie again if session_id cookie is already exists"
end
rescue Dalli::RingError => ex
skip ex.message, ex.backtrace

@ -177,9 +177,9 @@ def test_serves_gzip_files_with_not_modified
last_modified = File.mtime(File.join(@root, "#{file_name}.gz"))
response = get(file_name, "HTTP_ACCEPT_ENCODING" => "gzip", "HTTP_IF_MODIFIED_SINCE" => last_modified.httpdate)
assert_equal 304, response.status
assert_equal nil, response.headers["Content-Type"]
assert_equal nil, response.headers["Content-Encoding"]
assert_equal nil, response.headers["Vary"]
assert_nil response.headers["Content-Type"]
assert_nil response.headers["Content-Encoding"]
assert_nil response.headers["Vary"]
end
def test_serves_files_with_headers

@ -30,7 +30,7 @@ class TestRequestTest < ActiveSupport::TestCase
req = ActionDispatch::TestRequest.create({})
assert_equal({}, req.cookies)
assert_equal nil, req.env["HTTP_COOKIE"]
assert_nil req.env["HTTP_COOKIE"]
req.cookie_jar["user_name"] = "david"
assert_cookies({ "user_name" => "david" }, req.cookie_jar)

@ -96,7 +96,7 @@ def test_score
path = Path::Pattern.from_string "/:controller(/:action(/:id))(.:format)"
generic = Route.build "name", nil, path, constraints, [], {}
knowledge = { id: 20, controller: "pages", action: "show" }
knowledge = { "id" => true, "controller" => true, "action" => true }
routes = [specific, generic]

@ -1,3 +1,17 @@
* Return correct object name in form helper method after `fields_for`.
Fixes #26931.
*Yuji Yaginuma*
* Use `ActionView::Resolver.caching?` (`config.action_view.cache_template_loading`)
to enable template recompilation.
Before it was enabled by `consider_all_requests_local`, which caused
recompilation in tests.
*Max Melentiev*
* Add `form_with` to unify `form_tag` and `form_for` usage.
Used like `form_tag` (where just the open tag is output):

@ -4,4 +4,4 @@ Ensure that you can build the project and run tests.
Run rake ujs:server first, and then run the web tests by
visiting http://localhost:4567 in your browser.
rake test:server
rake ujs:server

@ -49,7 +49,7 @@ end
namespace :ujs do
desc "Starts the test server"
task :server do
system 'bundle exec rackup test/ujs/config.ru -p 4567 -s puma'
system "bundle exec rackup test/ujs/config.ru -p 4567 -s puma"
end
end

@ -35,18 +35,37 @@ module AssetTagHelper
# When the Asset Pipeline is enabled, you can pass the name of your manifest as
# source, and include other JavaScript or CoffeeScript files inside the manifest.
#
# ==== Options
#
# When the last parameter is a hash you can add HTML attributes using that
# parameter. The following options are supported:
#
# * <tt>:extname</tt> - Append a extention to the generated url unless the extension
# already exists. This only applies for relative urls.
# * <tt>:protocol</tt> - Sets the protocol of the generated url, this option only
# applies when a relative url and +host+ options are provided.
# * <tt>:host</tt> - When a relative url is provided the host is added to the
# that path.
# * <tt>:skip_pipeline</tt> - This option is used to bypass the asset pipeline
# when it is set to true.
#
# ==== Examples
#
# javascript_include_tag "xmlhr"
# # => <script src="/assets/xmlhr.js?1284139606"></script>
# # => <script src="/assets/xmlhr.debug-1284139606.js"></script>
#
# javascript_include_tag "xmlhr", host: "localhost", protocol: "https"
# # => <script src="https://localhost/assets/xmlhr.debug-1284139606.js"></script>
#
# javascript_include_tag "template.jst", extname: false
# # => <script src="/assets/template.jst?1284139606"></script>
# # => <script src="/assets/template.debug-1284139606.jst"></script>
#
# javascript_include_tag "xmlhr.js"
# # => <script src="/assets/xmlhr.js?1284139606"></script>
# # => <script src="/assets/xmlhr.debug-1284139606.js"></script>
#
# javascript_include_tag "common.javascript", "/elsewhere/cools"
# # => <script src="/assets/common.javascript?1284139606"></script>
# # <script src="/elsewhere/cools.js?1423139606"></script>
# # => <script src="/assets/common.javascript.debug-1284139606.js"></script>
# # <script src="/elsewhere/cools.debug-1284139606.js"></script>
#
# javascript_include_tag "http://www.example.com/xmlhr"
# # => <script src="http://www.example.com/xmlhr"></script>

@ -215,7 +215,7 @@ def cache_fragment_name(name = {}, skip_digest: nil, virtual_path: nil)
private
def fragment_name_with_digest(name, virtual_path) #:nodoc:
def fragment_name_with_digest(name, virtual_path)
virtual_path ||= @virtual_path
if virtual_path
name = controller.url_for(name).split("://").last if name.is_a?(Hash)
@ -226,7 +226,7 @@ def fragment_name_with_digest(name, virtual_path) #:nodoc:
end
end
def fragment_for(name = {}, options = nil, &block) #:nodoc:
def fragment_for(name = {}, options = nil, &block)
if content = read_fragment_for(name, options)
@cache_hit = true
content
@ -236,11 +236,11 @@ def fragment_for(name = {}, options = nil, &block) #:nodoc:
end
end
def read_fragment_for(name, options) #:nodoc:
def read_fragment_for(name, options)
controller.read_fragment(name, options)
end
def write_fragment_for(name, options) #:nodoc:
def write_fragment_for(name, options)
# VIEW TODO: Make #capture usable outside of ERB
# This dance is needed because Builder can't use capture
pos = output_buffer.length

@ -513,6 +513,17 @@ def apply_form_for_options!(record, object, options) #:nodoc:
# <input type="text" name="post[title]" value="<the title of the post>">
# </form>
#
# # Though the fields don't have to correspond to model attributes:
# <%= form_with model: Cat.new do |form| %>
# <%= form.text_field :cats_dont_have_gills %>
# <%= form.text_field :but_in_forms_they_can %>
# <% end %>
# # =>
# <form action="/cats" method="post" data-remote="true">
# <input type="text" name="cat[cats_dont_have_gills]">
# <input type="text" name="cat[but_in_forms_they_can]">
# </form>
#
# The parameters in the forms are accessible in controllers according to
# their name nesting. So inputs named +title+ and <tt>post[title]</tt> are
# accessible as <tt>params[:title]</tt> and <tt>params[:post][:title]</tt>
@ -521,7 +532,7 @@ def apply_form_for_options!(record, object, options) #:nodoc:
# By default +form_with+ attaches the <tt>data-remote</tt> attribute
# submitting the form via an XMLHTTPRequest in the background if an
# Unobtrusive JavaScript driver, like rails-ujs, is used. See the
# <tt>:remote</tt> option for more.
# <tt>:local</tt> option for more.
#
# For ease of comparison the examples above left out the submit button,
# as well as the auto generated hidden fields that enable UTF-8 support
@ -595,6 +606,16 @@ def apply_form_for_options!(record, object, options) #:nodoc:
#
# Where <tt>@document = Document.find(params[:id])</tt>.
#
# When using labels +form_with+ requires setting the id on the field being
# labelled:
#
# <%= form_with(model: @post) do |form| %>
# <%= form.label :title %>
# <%= form.text_field :title, id: :post_title %>
# <% end %>
#
# See +label+ for more on how the +for+ attribute is derived.
#
# === Mixing with other form helpers
#
# While +form_with+ uses a FormBuilder object it's possible to mix and
@ -690,6 +711,9 @@ def apply_form_for_options!(record, object, options) #:nodoc:
# form_with(**options.merge(builder: LabellingFormBuilder), &block)
# end
def form_with(model: nil, scope: nil, url: nil, format: nil, **options)
options[:allow_method_names_outside_object] = true
options[:skip_default_ids] = true
if model
url ||= polymorphic_path(model, format: format)
@ -964,14 +988,14 @@ def fields_for(record_name, record_object = nil, options = {}, &block)
# <%= fields :comment do |fields| %>
# <%= fields.text_field :body %>
# <% end %>
# # => <input type="text" name="comment[body] id="comment_body">
# # => <input type="text" name="comment[body]>
#
# # Using a model infers the scope and assigns field values:
# <%= fields model: Comment.new(body: "full bodied") do |fields| %<
# <%= fields.text_field :body %>
# <% end %>
# # =>
# <input type="text" name="comment[body] id="comment_body" value="full bodied">
# <input type="text" name="comment[body] value="full bodied">
#
# # Using +fields+ with +form_with+:
# <%= form_with model: @post do |form| %>
@ -986,6 +1010,16 @@ def fields_for(record_name, record_object = nil, options = {}, &block)
# or model is yielded, so any generated field names are prefixed with
# either the passed scope or the scope inferred from the <tt>:model</tt>.
#
# When using labels +fields+ requires setting the id on the field being
# labelled:
#
# <%= fields :comment do |fields| %>
# <%= fields.label :body %>
# <%= fields.text_field :body, id: :comment_body %>
# <% end %>
#
# See +label+ for more on how the +for+ attribute is derived.
#
# === Mixing with other form helpers
#
# While +form_with+ uses a FormBuilder object it's possible to mix and
@ -1003,7 +1037,9 @@ def fields_for(record_name, record_object = nil, options = {}, &block)
# to work with an object as a base, like
# FormOptionHelper#collection_select and DateHelper#datetime_select.
def fields(scope = nil, model: nil, **options, &block)
# TODO: Remove when ids and classes are no longer output by default.
options[:allow_method_names_outside_object] = true
options[:skip_default_ids] = true
if model
scope ||= model_name_from_record_or_class(model).param_key
end
@ -1469,7 +1505,7 @@ def range_field(object_name, method, options = {})
private
def html_options_for_form_with(url_for_options = nil, model = nil, html: {}, local: false,
skip_enforcing_utf8: false, **options)
html_options = options.except(:index, :include_id, :builder).merge(html)
html_options = options.slice(:id, :class, :multipart, :method, :data).merge(html)
html_options[:method] ||= :patch if model.respond_to?(:persisted?) && model.persisted?
html_options[:enforce_utf8] = !skip_enforcing_utf8
@ -1603,7 +1639,7 @@ def to_model
def initialize(object_name, object, template, options)
@nested_child_index = {}
@object_name, @object, @template, @options = object_name, object, template, options
@default_options = @options ? @options.slice(:index, :namespace) : {}
@default_options = @options ? @options.slice(:index, :namespace, :skip_default_ids, :allow_method_names_outside_object) : {}
convert_to_legacy_options(@options)
@ -1888,10 +1924,11 @@ def fields_for(record_name, record_object = nil, fields_options = {}, &block)
record_name = model_name_from_record_or_class(record_object).param_key
end
object_name = @object_name
index = if options.has_key?(:index)
options[:index]
elsif defined?(@auto_index)
self.object_name = @object_name.to_s.sub(/\[\]$/, "")
object_name = object_name.to_s.sub(/\[\]$/, "")
@auto_index
end
@ -1910,6 +1947,9 @@ def fields_for(record_name, record_object = nil, fields_options = {}, &block)
# See the docs for the <tt>ActionView::FormHelper.fields</tt> helper method.
def fields(scope = nil, model: nil, **options, &block)
options[:allow_method_names_outside_object] = true
options[:skip_default_ids] = true
convert_to_legacy_options(options)
fields_for(scope || model, model, **options, &block)
@ -2268,10 +2308,6 @@ def convert_to_legacy_options(options)
if options.key?(:skip_id)
options[:include_id] = !options.delete(:skip_id)
end
if options.key?(:local)
options[:remote] = !options.delete(:local)
end
end
end
end

Some files were not shown because too many files have changed in this diff Show More