actionpack 8.1.3.1 → 8.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b0ff49056ea3c453a5170155101b42a63b72fc925700963edd6e35b389be3be
4
- data.tar.gz: bd670c091cfafca4e009546d4c033ddf888d514ac7d8c4943260f0dd271a966e
3
+ metadata.gz: 188361aae9342d1758609c8aae8e654ed45555478396061ad363d516afaa9447
4
+ data.tar.gz: a327bf62a9c720d6507c3ab0523e10c27042bac1c94bdbb738bb6dcfcf9b2255
5
5
  SHA512:
6
- metadata.gz: bbfafbfe0e65589d3059d85a4a6ff62f3cf87f60c7b908b79db86a584268f04db86305addf572b6366aea58d4cb86cc5cbd762f867a1d8e6a80599d3df4657b3
7
- data.tar.gz: 30e91ed3ba2adaa8fd9cb451794c20964090382028f24ed933f821fa05b2d408af8df466b25b16c6bbdfd367e38d8400ef0547311c8da8e3ec535928b76205f7
6
+ metadata.gz: aff62143454ada2ba6226b429126b4ec52aa8e55afd690e3e35db8f1add1a63e661ec837ced36660ed02f2bd2b094a516401238f8a959cf792a7e2afc57928c7
7
+ data.tar.gz: 32ff126c37ddfa3c381b374122cf4b636e6589d3cf16ca1cf4f231d0931d4ae0c0ef80ca13d5d2296988833a842b3b09d8ac89f22a72074230763b145758c3a2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,120 @@
1
+ ## Rails 8.1.4 (September 24, 2026) ##
2
+
3
+ * Fix the debug error page to not attempt to read source fragments from
4
+ directory paths.
5
+
6
+ *Marco Roth*
7
+
8
+ * Apply source value mappings to dynamic Permissions Policy sources.
9
+
10
+ Dynamic Permissions Policy sources (procs) now have source mappings applied
11
+ to their resolved values, the same as static sources.
12
+
13
+ *Kenta Ishizaki*
14
+
15
+ * Allow `ActionDispatch::Http::URL.path_for` with `trailing_slash: true` and a
16
+ blank path to accept query params and an anchor.
17
+
18
+ Previously the blank path used a frozen `"/"`, which raised a `FrozenError`
19
+ when appending the query string.
20
+
21
+ *Kenta Ishizaki*
22
+
23
+ * Avoid mutating the `params` hash passed to `ActionDispatch::Http::URL.url_for`.
24
+
25
+ *Kenta Ishizaki*
26
+
27
+ * Honor falsy values (e.g. `format: false`, `anchor: false`) passed in the
28
+ deprecated positional-hash form of routing DSL methods.
29
+
30
+ Previously, `false` values were silently dropped without emitting a
31
+ deprecation warning, causing the deprecated hash form to produce different
32
+ routes than the keyword form.
33
+
34
+ *Kenta Ishizaki*
35
+
36
+ * Honor the deprecated `namespace` hash `:path`, `:shallow_path`, and
37
+ `:shallow_prefix` options when passed as `false`.
38
+
39
+ *Kenta Ishizaki*
40
+
41
+ * Fix the deprecated `scope` hash `:except` option to apply to `except`
42
+ instead of `only`.
43
+
44
+ *Kenta Ishizaki*
45
+
46
+ * Reject malformed hosts with extra ports in `ActionDispatch::HostAuthorization`.
47
+
48
+ When an allowed host is configured with an explicit port, a `Host` header
49
+ with an additional port (e.g. `www.example.com:80:80`) is no longer accepted.
50
+
51
+ *Andrii Furmanets*
52
+
53
+ * Fix `url_for` to leave out an optional part of a route when its value is a
54
+ blank string, the same way it already does for `nil`.
55
+
56
+ Before, the blank string ended up in the path, producing a URL the route
57
+ itself cannot match:
58
+
59
+ ```ruby
60
+ get "(/locale/:locale)/products(/:id)", to: "products#show"
61
+
62
+ url_for(controller: "products", action: "show", locale: "", id: 123)
63
+ # Before: "/locale//products/123"
64
+ # After: "/products/123"
65
+ ```
66
+
67
+ Blank strings for required parameters behave as before.
68
+
69
+ *Carl Dawson*
70
+
71
+ * Fix path normalization to handle mixed-case percent-encoding.
72
+
73
+ *Andrii Furmanets*
74
+
75
+ * Avoid loading `ActionController::Live` early in initializer, and introduce
76
+ `action_controller_live` load hook.
77
+
78
+ *Adrianna Chang*
79
+
80
+ * Set the browser binary when preloading the Selenium driver for system tests.
81
+
82
+ Selenium 4.45 stopped setting it as a side effect of getting the driver path,
83
+ causing tests to fail with "cannot find Chrome binary".
84
+
85
+ *Titus Fortner*
86
+
87
+ * Fix `Session::CacheStore` to not generate a new session after dropping the current one.
88
+
89
+ *Kenta Ishizaki*
90
+
91
+ * Parse all three HTTP-date formats in the `If-Modified-Since` request header.
92
+
93
+ `If-Modified-Since` carries an HTTP-date, which RFC 9110 allows in any of
94
+ three formats (IMF-fixdate, RFC 850, or asctime), and requires recipients to
95
+ accept all three. The header was parsed with `Time.rfc2822`, which only
96
+ accepts the IMF-fixdate format, and the parse failure was swallowed — so a
97
+ conditional `GET` using an RFC 850 or asctime date silently failed to produce
98
+ a `304 Not Modified` and re-sent the full response. It is now parsed with
99
+ `Time.httpdate`, consistent with how `Last-Modified` and `Date` are read.
100
+
101
+ *Kenta Ishizaki*
102
+
103
+ * Fix response steam buffers compatibility with `IO.copy_stream`.
104
+
105
+ `IO.copy_stream(src, response.stream)` raised `TypeError: no implicit
106
+ conversion of Array into Integer` because `Buffer#write` returned the
107
+ buffer array instead of an Integer (bytes written). Additionally, the
108
+ written data could be silently corrupted because `IO.copy_stream`
109
+ reuses its internal string buffer after `write` returns — storing a
110
+ reference without `dup` meant the buffered content was later mutated.
111
+
112
+ Both `ActionDispatch::Response::Buffer#write` and
113
+ `ActionController::Live::Buffer#write` are affected.
114
+
115
+ *Gabriel Quaresma*
116
+
117
+
1
118
  ## Rails 8.1.3.1 (July 29, 2026) ##
2
119
 
3
120
  * No changes.
@@ -514,7 +514,7 @@ module ActionController
514
514
  end
515
515
 
516
516
  # This method takes an authorization body and splits up the key-value pairs by
517
- # the standardized `:`, `;`, or `\t` delimiters defined in
517
+ # the standardized `,`, `;`, or `\t` delimiters defined in
518
518
  # `AUTHN_PAIR_DELIMITERS`.
519
519
  def raw_params(auth)
520
520
  _raw_params = auth.sub(TOKEN_REGEX, "").split(AUTHN_PAIR_DELIMITERS).map(&:strip)
@@ -27,7 +27,7 @@ module ActionController
27
27
  # end
28
28
  #
29
29
  # There are a few caveats with this module. You **cannot** write headers after
30
- # the response has been committed (Response#committed? will return truthy).
30
+ # the response has been committed (`Response#committed?` will return truthy).
31
31
  # Calling `write` or `close` on the response stream will cause the response
32
32
  # object to be committed. Make sure all headers are set before calling write or
33
33
  # close on your stream.
@@ -50,7 +50,8 @@ module ActionController
50
50
  #
51
51
  # def stream
52
52
  # response.headers["Content-Type"] = "text/event-stream"
53
- # response.headers["Last-Modified"] = Time.now.httpdate # Add this line if your Rack version is 2.2.x
53
+ # # Add this line if your Rack version is 2.2.x
54
+ # response.headers["Last-Modified"] = Time.now.httpdate
54
55
  # ...
55
56
  # end
56
57
  #
@@ -62,26 +63,27 @@ module ActionController
62
63
  # You can configure which execution state keys should be excluded from being shared
63
64
  # using the `config.action_controller.live_streaming_excluded_keys` configuration:
64
65
  #
65
- # # config/application.rb
66
- # config.action_controller.live_streaming_excluded_keys = [:active_record_connected_to_stack]
66
+ # # config/application.rb
67
+ # config.action_controller.live_streaming_excluded_keys =
68
+ # [:active_record_connected_to_stack]
67
69
  #
68
70
  # This is useful when using ActionController::Live inside a `connected_to` block. For example,
69
71
  # if the parent request is reading from a replica using `connected_to(role: :reading)`, you may
70
72
  # want the streaming thread to use its own connection context instead of inheriting the read-only
71
73
  # context:
72
74
  #
73
- # # Without configuration, streaming thread inherits read-only connection
74
- # ActiveRecord::Base.connected_to(role: :reading) do
75
- # @posts = Post.all
76
- # render stream: true # Streaming thread cannot write to database
77
- # end
75
+ # # Without configuration, streaming thread inherits read-only connection
76
+ # ActiveRecord::Base.connected_to(role: :reading) do
77
+ # @posts = Post.all
78
+ # render stream: true # Streaming thread cannot write to database
79
+ # end
78
80
  #
79
- # # With configuration, streaming thread gets fresh connection context
80
- # # config.action_controller.live_streaming_excluded_keys = [:active_record_connected_to_stack]
81
- # ActiveRecord::Base.connected_to(role: :reading) do
82
- # @posts = Post.all
83
- # render stream: true # Streaming thread can write to database if needed
84
- # end
81
+ # # With configuration, streaming thread gets fresh connection context
82
+ # # config.action_controller.live_streaming_excluded_keys = [:active_record_connected_to_stack]
83
+ # ActiveRecord::Base.connected_to(role: :reading) do
84
+ # @posts = Post.all
85
+ # render stream: true # Streaming thread can write to database if needed
86
+ # end
85
87
  #
86
88
  # Common keys you might want to exclude:
87
89
  # - `:active_record_connected_to_stack` - Database connection routing and roles
@@ -230,6 +232,8 @@ module ActionController
230
232
  raise ClientDisconnected, "client disconnected"
231
233
  end
232
234
  end
235
+
236
+ string.bytesize
233
237
  end
234
238
 
235
239
  # Same as `write` but automatically include a newline at the end of the string.
@@ -429,5 +433,7 @@ module ActionController
429
433
  "#{message}\n\n"
430
434
  end
431
435
  end
436
+
437
+ ActiveSupport.run_load_hooks(:action_controller_live, self)
432
438
  end
433
439
  end
@@ -241,7 +241,8 @@ module ActionController
241
241
  # url_from("http://example.com/profile") # => "http://example.com/profile"
242
242
  # url_from("http://evil.com/profile") # => nil
243
243
  #
244
- # Subdomains are considered part of the host:
244
+ # Subdomains are included when comparing hosts. The hostname must match exactly
245
+ # for a redirect to be considered internal.
245
246
  #
246
247
  # # If request.host is on https://example.com or https://app.example.com, you'd get:
247
248
  # url_from("https://dev.example.com/profile") # => nil
@@ -145,7 +145,7 @@ module ActionController
145
145
  #
146
146
  # params = ActionController::Parameters.new(a: "123", b: "456")
147
147
  # params.permit(:c)
148
- # # => ActionController::UnpermittedParameters: found unpermitted keys: a, b
148
+ # # => ActionController::UnpermittedParameters: found unpermitted parameters: :a, :b
149
149
  #
150
150
  # Please note that these options *are not thread-safe*. In a multi-threaded
151
151
  # environment they should only be set once at boot-time and never mutated at
@@ -34,7 +34,9 @@ module ActionController
34
34
  end
35
35
 
36
36
  initializer "action_controller.live_streaming_excluded_keys" do |app|
37
- ActionController::Live.live_streaming_excluded_keys = app.config.action_controller.live_streaming_excluded_keys
37
+ ActiveSupport.on_load(:action_controller_live) do
38
+ ActionController::Live.live_streaming_excluded_keys = app.config.action_controller.live_streaming_excluded_keys
39
+ end
38
40
  end
39
41
 
40
42
  initializer "action_controller.parameters_config" do |app|
@@ -13,7 +13,11 @@ module ActionDispatch
13
13
 
14
14
  def if_modified_since
15
15
  if since = get_header(HTTP_IF_MODIFIED_SINCE)
16
- Time.rfc2822(since) rescue nil
16
+ # `If-Modified-Since` carries an HTTP-date, which per RFC 9110 may be in
17
+ # any of the three legal formats (IMF-fixdate, RFC 850, or asctime).
18
+ # `Time.httpdate` accepts all three; it also matches how the response side
19
+ # parses `Last-Modified`/`Date`. `Time.rfc2822` only accepted IMF-fixdate.
20
+ Time.httpdate(since) rescue nil
17
21
  end
18
22
  end
19
23
 
@@ -179,7 +179,8 @@ module ActionDispatch # :nodoc:
179
179
  if context.nil?
180
180
  raise RuntimeError, "Missing context for the dynamic permissions policy source: #{source.inspect}"
181
181
  else
182
- context.instance_exec(&source)
182
+ resolved = context.instance_exec(&source)
183
+ apply_mappings(Array.wrap(resolved))
183
184
  end
184
185
  else
185
186
  raise RuntimeError, "Unexpected permissions policy source: #{source.inspect}"
@@ -150,7 +150,8 @@ module ActionDispatch # :nodoc:
150
150
 
151
151
  @str_body = nil
152
152
  @response.commit!
153
- @buf.push string
153
+ @buf.push string.frozen? ? string : string.dup
154
+ string.bytesize
154
155
  end
155
156
  alias_method :<<, :write
156
157
 
@@ -170,7 +170,7 @@ module ActionDispatch
170
170
  path = options[:script_name].to_s.chomp("/")
171
171
  path << options[:path] if options.key?(:path)
172
172
 
173
- path = "/" if options[:trailing_slash] && path.blank?
173
+ path = +"/" if options[:trailing_slash] && path.blank?
174
174
 
175
175
  add_params(path, options[:params]) if options.key?(:params)
176
176
  add_anchor(path, options[:anchor]) if options.key?(:anchor)
@@ -181,7 +181,7 @@ module ActionDispatch
181
181
  private
182
182
  def add_params(path, params)
183
183
  params = { params: params } unless params.is_a?(Hash)
184
- params.reject! { |_, v| v.to_param.nil? }
184
+ params = params.reject { |_, v| v.to_param.nil? }
185
185
  query = params.to_query
186
186
  path << "?#{query}" unless query.empty?
187
187
  end
@@ -90,6 +90,11 @@ module ActionDispatch
90
90
  defaults = route.defaults
91
91
  required_parts = route.required_parts
92
92
 
93
+ # After query param extraction, so empty values are consumed as path parts.
94
+ parameterized_parts.delete_if do |key, value|
95
+ value.to_s.blank? && !required_parts.include?(key)
96
+ end
97
+
93
98
  route.parts.reverse_each do |key|
94
99
  break if defaults[key].nil? && parameterized_parts[key].present?
95
100
  next if parameterized_parts[key].to_s != defaults[key].to_s
@@ -31,7 +31,7 @@ module ActionDispatch
31
31
 
32
32
  unless path == "/"
33
33
  path.delete_suffix!("/")
34
- path.gsub!(/(%[a-f0-9]{2})/) { $1.upcase }
34
+ path.gsub!(/(%[a-f0-9]{2})/i) { $1.upcase }
35
35
  end
36
36
 
37
37
  path.force_encoding(encoding)
@@ -336,7 +336,7 @@ module ActionDispatch
336
336
  def source_fragment(path, line)
337
337
  return unless Rails.respond_to?(:root) && Rails.root
338
338
  full_path = Rails.root.join(path)
339
- if File.exist?(full_path)
339
+ if File.file?(full_path)
340
340
  File.open(full_path, "r") do |file|
341
341
  extract_source_fragment_lines(file.each_line, line)
342
342
  end
@@ -73,10 +73,11 @@ module ActionDispatch
73
73
  end
74
74
 
75
75
  def sanitize_string(host)
76
+ port = "#{PORT_REGEX}?" unless host.match?(/:\d+\z/)
76
77
  if host.start_with?(".")
77
- /\A#{SUBDOMAIN_REGEX}?#{Regexp.escape(host[1..-1])}#{PORT_REGEX}?\z/i
78
+ /\A#{SUBDOMAIN_REGEX}?#{Regexp.escape(host[1..-1])}#{port}\z/i
78
79
  else
79
- /\A#{Regexp.escape host}#{PORT_REGEX}?\z/i
80
+ /\A#{Regexp.escape host}#{port}\z/i
80
81
  end
81
82
  end
82
83
 
@@ -54,7 +54,7 @@ module ActionDispatch
54
54
  def delete_session(env, sid, options)
55
55
  @cache.delete(cache_key(sid.private_id))
56
56
  @cache.delete(cache_key(sid.public_id))
57
- generate_sid
57
+ generate_sid unless options[:drop]
58
58
  end
59
59
 
60
60
  private
@@ -315,7 +315,7 @@
315
315
  return toggle('env_dump');
316
316
  }
317
317
  var copyAsText = function() {
318
- const text = document.getElementById("exception-message-for-copy").textContent;
318
+ const text = document.getElementById("exception-message-for-copy").value;
319
319
 
320
320
  navigator.clipboard.writeText(text).then(() => {
321
321
  const beforeText = this.innerText;
@@ -328,7 +328,7 @@
328
328
  <body>
329
329
 
330
330
  <%= yield %>
331
- <script type="text/plain" id="exception-message-for-copy"><%= @exception_message_for_copy %></script>
331
+ <textarea hidden id="exception-message-for-copy"><%= @exception_message_for_copy %></textarea>
332
332
 
333
333
  </body>
334
334
  </html>
@@ -5,14 +5,12 @@
5
5
  <main role="main" id="container">
6
6
  <h2><%= h @exception_wrapper.message %></h2>
7
7
  <% unless @exception_wrapper.failures.empty? %>
8
- <p>
9
- <h2>Failure reasons:</h2>
10
- <ol>
11
- <% @exception_wrapper.failures.each do |route, reason| %>
12
- <li><code><%= route.inspect.delete('\\') %></code> failed because <%= reason.downcase %></li>
13
- <% end %>
14
- </ol>
15
- </p>
8
+ <h2>Failure reasons:</h2>
9
+ <ol>
10
+ <% @exception_wrapper.failures.each do |route, reason| %>
11
+ <li><code><%= route.inspect.delete('\\') %></code> failed because <%= reason.downcase %></li>
12
+ <% end %>
13
+ </ol>
16
14
  <% end %>
17
15
 
18
16
  <%= render "rescues/trace", traces: @traces, trace_to_show: @trace_to_show %>
@@ -4,7 +4,7 @@ Routing Error
4
4
  <% unless @exception.failures.empty? %>
5
5
  Failure reasons:
6
6
  <% @exception.failures.each do |route, reason| %>
7
- - <%= route.inspect.delete('\\') %></code> failed because <%= reason.downcase %>
7
+ - <%= route.inspect.delete('\\') %> failed because <%= reason.downcase %>
8
8
  <% end %>
9
9
  <% end %>
10
10
 
@@ -665,11 +665,11 @@ module ActionDispatch
665
665
 
666
666
  private
667
667
  def assign_deprecated_option(deprecated_options, key, method_name)
668
- if (deprecated_value = deprecated_options.delete(key))
668
+ if deprecated_options.key?(key)
669
669
  ActionDispatch.deprecator.warn(<<~MSG.squish)
670
670
  #{method_name} received a hash argument #{key}. Please use a keyword instead. Support to hash argument will be removed in Rails 8.2.
671
671
  MSG
672
- deprecated_value
672
+ deprecated_options.delete(key)
673
673
  end
674
674
  end
675
675
 
@@ -989,7 +989,7 @@ module ActionDispatch
989
989
  def scope(*args, only: nil, except: nil, **options)
990
990
  if args.grep(Hash).any? && (deprecated_options = args.extract_options!)
991
991
  only ||= assign_deprecated_option(deprecated_options, :only, :scope)
992
- only ||= assign_deprecated_option(deprecated_options, :except, :scope)
992
+ except ||= assign_deprecated_option(deprecated_options, :except, :scope)
993
993
  assign_deprecated_options(deprecated_options, options, :scope)
994
994
  end
995
995
 
@@ -1097,9 +1097,9 @@ module ActionDispatch
1097
1097
  def namespace(name, deprecated_options = nil, as: DEFAULT, path: DEFAULT, shallow_path: DEFAULT, shallow_prefix: DEFAULT, **options, &block)
1098
1098
  if deprecated_options.is_a?(Hash)
1099
1099
  as = assign_deprecated_option(deprecated_options, :as, :namespace) if deprecated_options.key?(:as)
1100
- path ||= assign_deprecated_option(deprecated_options, :path, :namespace) if deprecated_options.key?(:path)
1101
- shallow_path ||= assign_deprecated_option(deprecated_options, :shallow_path, :namespace) if deprecated_options.key?(:shallow_path)
1102
- shallow_prefix ||= assign_deprecated_option(deprecated_options, :shallow_prefix, :namespace) if deprecated_options.key?(:shallow_prefix)
1100
+ path = assign_deprecated_option(deprecated_options, :path, :namespace) if deprecated_options.key?(:path)
1101
+ shallow_path = assign_deprecated_option(deprecated_options, :shallow_path, :namespace) if deprecated_options.key?(:shallow_path)
1102
+ shallow_prefix = assign_deprecated_option(deprecated_options, :shallow_prefix, :namespace) if deprecated_options.key?(:shallow_prefix)
1103
1103
  assign_deprecated_options(deprecated_options, options, :namespace)
1104
1104
  end
1105
1105
 
@@ -65,7 +65,9 @@ module ActionDispatch
65
65
  def resolve_driver_path(namespace)
66
66
  # The path method has been deprecated in 4.20.0
67
67
  if Gem::Version.new(::Selenium::WebDriver::VERSION) >= Gem::Version.new("4.20.0")
68
- namespace::Service.driver_path = ::Selenium::WebDriver::DriverFinder.new(options, namespace::Service.new).driver_path
68
+ driver_finder = ::Selenium::WebDriver::DriverFinder.new(options, namespace::Service.new)
69
+ namespace::Service.driver_path = driver_finder.driver_path
70
+ options.binary = driver_finder.browser_path if driver_finder.browser_path?
69
71
  else
70
72
  namespace::Service.driver_path = ::Selenium::WebDriver::DriverFinder.path(options, namespace::Service)
71
73
  end
@@ -8,7 +8,7 @@ module ActionDispatch
8
8
  # Saves the content of response body to a file and tries to open it in your browser.
9
9
  # Launchy must be present in your Gemfile for the page to open automatically.
10
10
  def save_and_open_page(path = html_dump_default_path)
11
- save_page(path).tap { |s_path| open_file(s_path) }
11
+ save_page(path).tap { |s_path| open_file(s_path) } # rubocop:disable Lint/Debugger
12
12
  end
13
13
 
14
14
  private
@@ -11,8 +11,8 @@ module ActionPack
11
11
  module VERSION
12
12
  MAJOR = 8
13
13
  MINOR = 1
14
- TINY = 3
15
- PRE = "1"
14
+ TINY = 4
15
+ PRE = nil
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
18
18
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.3.1
4
+ version: 8.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 8.1.3.1
18
+ version: 8.1.4
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 8.1.3.1
25
+ version: 8.1.4
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: nokogiri
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -127,28 +127,28 @@ dependencies:
127
127
  requirements:
128
128
  - - '='
129
129
  - !ruby/object:Gem::Version
130
- version: 8.1.3.1
130
+ version: 8.1.4
131
131
  type: :runtime
132
132
  prerelease: false
133
133
  version_requirements: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - '='
136
136
  - !ruby/object:Gem::Version
137
- version: 8.1.3.1
137
+ version: 8.1.4
138
138
  - !ruby/object:Gem::Dependency
139
139
  name: activemodel
140
140
  requirement: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - '='
143
143
  - !ruby/object:Gem::Version
144
- version: 8.1.3.1
144
+ version: 8.1.4
145
145
  type: :development
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - '='
150
150
  - !ruby/object:Gem::Version
151
- version: 8.1.3.1
151
+ version: 8.1.4
152
152
  description: Web apps on Rails. Simple, battle-tested conventions for building and
153
153
  testing MVC web applications. Works with any Rack-compatible server.
154
154
  email: david@loudthinking.com
@@ -352,10 +352,10 @@ licenses:
352
352
  - MIT
353
353
  metadata:
354
354
  bug_tracker_uri: https://github.com/rails/rails/issues
355
- changelog_uri: https://github.com/rails/rails/blob/v8.1.3.1/actionpack/CHANGELOG.md
356
- documentation_uri: https://api.rubyonrails.org/v8.1.3.1/
355
+ changelog_uri: https://github.com/rails/rails/blob/v8.1.4/actionpack/CHANGELOG.md
356
+ documentation_uri: https://api.rubyonrails.org/v8.1.4/
357
357
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
358
- source_code_uri: https://github.com/rails/rails/tree/v8.1.3.1/actionpack
358
+ source_code_uri: https://github.com/rails/rails/tree/v8.1.4/actionpack
359
359
  rubygems_mfa_required: 'true'
360
360
  rdoc_options: []
361
361
  require_paths:
@@ -372,7 +372,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
372
372
  version: '0'
373
373
  requirements:
374
374
  - none
375
- rubygems_version: 4.0.16
375
+ rubygems_version: 4.0.20
376
376
  specification_version: 4
377
377
  summary: Web-flow and rendering framework putting the VC in MVC (part of Rails).
378
378
  test_files: []