| Commit message (Collapse) | Author | Age | Files | Lines |
|\
| |
| | |
When testing cache issues, it is useful to log the actual key, including namespace
|
| |
| |
| |
| | |
full key that actually used by the underline cache implementation
|
| |
| |
| |
| |
| |
| |
| | |
The stated value of `now` would actually give the same result for
`now - 24.hours` and `now - 1.day`. Use an alternative value for
`now` that demonstrates the difference between subtracting
`24.hours` and `1.day`.
|
| | |
|
| |
| |
| |
| | |
This method was already niche, and is now redundant with `.new`
|
|\ \
| | |
| | |
| | |
| | | |
`HashWithIndifferentAccess.new` respects the default value or proc on
objects that respond to `#to_hash`
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
objects that respond to `#to_hash`.
Builds on the work of #12550 where `.new` will convert the object (that respond to `#to_hash`) to a hash and
add that hash's keys and values to itself.
This change will also make `.new` respect the default value or proc of objects that respond to `#to_hash`.
In other words, this `.new` behaves exactly like `.new_from_hash_copying_default`.
`.new_from_hash_copying_default` now simply invokes `.new` and any references to `.new_from_hash_copying_default`
are replaced with `.new`.
Added tests confirm behavior.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Before this commit `Module#redefine_method` always changes
visibility of redefined method to `public`.
This commit changes behavior of Module#redefine_method` to
keep method visibility.
|
| | |
| | |
| | |
| | |
| | | |
In later code examples, it is better to write how `Module#anonymous?`
works.
|
| | | |
|
| | |
| | |
| | |
| | |
| | | |
This is primarily to fix method redefinition warnings in class_attribute
but may be of use in other places where we define singleton methods.
|
|\ \ \
| | | |
| | | | |
FileStore: Long cache keys may result in too long paths due to encoding
|
| | | | |
|
|\ \ \ \
| | | | |
| | | | |
| | | | | |
Handle invalid UTF-8 strings when HTML escaping
|
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | |
| | | | | |
Use `ActiveSupport::Multibyte::Unicode.tidy_bytes` to handle invalid UTF-8
strings in `ERB::Util.unwrapped_html_escape` and `ERB::Util.html_escape_once`.
Prevents user-entered input passed from a querystring into a form field from
causing invalid byte sequence errors.
|
|\ \ \ \ \
| | | | | |
| | | | | | |
Use Module.prepend instead of alias_method and unify behavior of all Numeric extensions
|
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
alias_method
|
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | | |
Given that this pull request affects a mutable value, we need to test
for and document the affects on the receiver in this case.
Additionally, this pull request was missing a CHANGELOG entry.
|
| | | | | | |
|
|\ \ \ \ \ \
| | | | | | |
| | | | | | |
| | | | | | | |
Round some numbers more humanely
|
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | | |
Fix #20869
|
|\ \ \ \ \ \ \
| | | | | | | |
| | | | | | | | |
ActiveSupport: Fixing issue when delegating to methods named "block", "args", or "arg"
|
| | | | | | | | |
|
|\ \ \ \ \ \ \ \
| | | | | | | | |
| | | | | | | | | |
Fix precision on cache_key
|
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | | |
The default timestamp used for AR is `updated_at` in nanoseconds! (:nsec) This causes issues on any machine that runs an OS that supports nanoseconds timestamps, i.e. not-OS X, where the cache_key of the record persisted in the database (milliseconds precision) is out-of-sync with the cache_key in the ruby VM.
This commit adds:
A test that shows the issue, it can be found in the separate file `cache_key_test.rb`, because
- model couldn't be defined inline
- transactional testing needed to be turned off to get it to pass the MySQL tests
This seemed cleaner than putting it in an existing testcase file.
It adds :usec as a dateformat that calculates datetime in microseconds
It sets precision of cache_key to :usec instead of :nsec, as no db supports nsec precision on timestamps
|
|\ \ \ \ \ \ \ \ \
| | | | | | | | | |
| | | | | | | | | | |
nodoc for active support protected method [CI skip]
|
| | | | | | | | | | |
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
The bundled version of TZInfo referred to was removed from Active
Support in version 3.0.
|
| | | | | | | | | | |
|
|\ \ \ \ \ \ \ \ \ \
| |_|/ / / / / / / /
|/| | | | | | | | |
| | | | | | | | | | |
Fix deprecation warning messages on deprecate_methods
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
Add tests for ActiveSupport::Deprecation.deprecate_methods
Modify ActiveSupport::Testing::Deprecation to allow a custom deprecator
Leverage ActiveSupport::Testing::Deprecation assert_deprecated
Update documentation for ActiveSupport::Deprecation.deprecate_methods
Use cases:
Using the default deprecator => "removed from Rails X.Y"
Passing a custom deprecator in the options hash => "removed from MyGem next-release"
Deprecating methods directly from custom deprecator => "removed from MyGem next-release"
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
`each_with_object` allocates an array for each kv pair. Switching to
the slightly more verbose but less allocatey `each_pair` eliminates
array allocations. Eliminating this allocation returns AR objects to
have constant array allocations regardless of the number of columns the
object has.
Here is test code:
```ruby
require 'active_record'
class Topic < ActiveRecord::Base
end
20.times do |i|
Process.waitpid fork {
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
ActiveRecord::Base.connection.instance_eval do
create_table(:topics) do |t|
t.string :title, limit: 250
t.string :author_name
t.string :author_email_address
t.string :parent_title
t.string :type
t.string :group
i.times do |j|
t.string :"aaa#{j}"
end
t.timestamps null: true
end
end
ObjectSpace::AllocationTracer.setup(%i{type})
Topic.create title: "aaron" # heat cache
result = ObjectSpace::AllocationTracer.trace do
10.times do |i|
Topic.create title: "aaron #{i}"
end
end
puts "#{Topic.columns.length},#{(result.find { |k,v| k.first == :T_ARRAY }.last.first / 10)}"
}
end
```
Before this commit:
```
9,166
10,167
11,168
12,169
13,170
14,171
15,172
16,173
17,174
18,175
19,176
20,177
21,178
22,179
23,180
24,181
25,182
26,183
27,184
28,185
```
After:
```
9,157
10,157
11,157
12,157
13,157
14,157
15,157
16,157
17,157
18,157
19,157
20,157
21,157
22,157
23,157
24,157
25,157
26,157
27,157
28,157
```
Left side is the number of columns, right is the number of allocations
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
deep_dup'ing a hash will dup the keys as well as the values. Since
string keys from the source hash will be frozen, and the dup'd objects
are immediately dup'd and frozen on insert in to the hash, the end user
will only ever see two frozen strings. Since the strings are immutable,
this commit just cheats a little and reuses the immutable strings.
Just to reiterate, before this commit, deep duping a hash that looks
like this: `{ "foo" => "bar" }` will generate two new instances of
"foo". One is created when `deep_dup` is called on "foo", and the other
is created when the newly allocated "foo" string is inserted in to the
hash. The user never sees the intermediate "foo", and both copies of
"foo" that the user *can* access will be frozen, so in this case we just
reuse the existing frozen key.
The upshot is that after this change, string allocations on AR
allocations become constant regardless of the number of columns the
model has.
```ruby
require 'active_record'
class Topic < ActiveRecord::Base
end
20.times do |i|
Process.waitpid fork {
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
ActiveRecord::Base.connection.instance_eval do
create_table(:topics) do |t|
t.string :title, limit: 250
t.string :author_name
t.string :author_email_address
t.string :parent_title
t.string :type
t.string :group
i.times do |j|
t.integer :"aaa#{j}"
end
t.timestamps null: true
end
end
ObjectSpace::AllocationTracer.setup(%i{type})
Topic.create title: "aaron" # heat cache
result = ObjectSpace::AllocationTracer.trace do
10.times do |i|
Topic.create title: "aaron #{i}"
end
end
puts "#{Topic.columns.length},#{(result.find { |k,v| k.first == :T_STRING }.last.first / 10)}"
}
end
```
If you run the above script before this commit, the output looks like
this:
```
[aaron@TC rails (master)]$ be ruby -rallocation_tracer test.rb
9,105
10,107
11,109
12,111
13,113
14,115
15,117
16,119
17,121
18,123
19,125
20,127
21,129
22,131
23,133
24,135
25,137
26,139
27,141
28,143
```
The left column is the number of methods, the right column is the number
of string allocations.
Running against this commit, the output is:
```
[aaron@TC rails (master)]$ be ruby -rallocation_tracer test.rb
9,87
10,87
11,87
12,87
13,87
14,87
15,87
16,87
17,87
18,87
19,87
20,87
21,87
22,87
23,87
24,87
25,87
26,87
27,87
28,87
```
As you can see, there is now only a constant number of strings
allocated, regardless of the number of columns the model has.
|
|\ \ \ \ \ \ \ \ \ \
| |/ / / / / / / / /
|/| | | | | | | | | |
Expand support for ActiveSupport::TimeWithZone#utc?
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
Currently, ActiveSupport::TimeWithZone#utc? simply runs a check to see
if the linked ActiveSupport::TimeZone's name is "UTC". This will only
return true for ActiveSupport::TimeZone["UTC"], but not for time zones
such as "Etc/UTC", "Etc/Universal", or other time zones that are aliases
for UTC. Interestingly enough, ActiveSupport::TimeWithZone#utc? is also
aliased as #gmt? but will return false for the "GMT" timezone (along
with other TZInfo aliases for GMT).
Instead of running a simple check on the TimeZone name, we can rely on
the underlying TZInfo::TimezonePeriod and TZInfo::TimezoneOffset which
keep a record of of the offset's abbreviated name. The possibilities
here for UTC time zones are `:UTC`, `:UCT`, and `:GMT`.
Signed-off-by: David <me@davidcel.is>
|
|/ / / / / / / / /
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | | |
I could not find any reason why each method got its own prepended
module here, and all tests appear to pass with my change.
|
|\ \ \ \ \ \ \ \ \
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
Fix cache fetch instrumentation
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
Before this change, you couldn't tell if a read was a hit or not when
you called fetch.
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
With the previous implementation, the block passed to
define_singleton_method, which will live forever as the method body,
captures the parameters (args and block) in its enclosure.
For the current_scope registry, that can include an AR::Relation.
|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | | |
Saw this while doing a review of a patch:
* Normalize case and punctuation across comments.
* ascii -> ASCII
* Since I was on it, some blank lines that visually
add some clarity IMO.
|
|\ \ \ \ \ \ \ \ \ \
| | | | | | | | | | |
| | | | | | | | | | | |
[ci skip] Fix #seconds_since_midnight documentation output it will al…
|
| | | | | | | | | | |
| | | | | | | | | | |
| | | | | | | | | | |
| | | | | | | | | | | |
return floating pointnumber
|
|\ \ \ \ \ \ \ \ \ \ \
| | | | | | | | | | | |
| | | | | | | | | | | | |
Fix Time.now format in documentation [ci skip]
|
| |/ / / / / / / / / / |
|
|\ \ \ \ \ \ \ \ \ \ \
| | | | | | | | | | | |
| | | | | | | | | | | | |
Use #current instead of #now to prevent zone issues and use new ruby …
|
| |/ / / / / / / / / /
| | | | | | | | | | |
| | | | | | | | | | |
| | | | | | | | | | | |
application's time zone
|
|\ \ \ \ \ \ \ \ \ \ \
| |/ / / / / / / / / /
|/| | | | | | | | | | |
|
| | | | | | | | | | | |
|
| | | | | | | | | | | |
|
| | | | | | | | | | |
| | | | | | | | | | |
| | | | | | | | | | |
| | | | | | | | | | | |
[ci skip]
|