Previously, if you were using a pre-7.1 migration and you were adding an index using `create_table`, the index would be named using the new index naming functionality introduced in #47753.
If you're using MySQL 8.0.16+ and your database contains a table with
a check constraint, the first and last characters of the constraint
will be stripped when dumping the schema; this makes it impossible
to use check constraints in a MySQL 8.0 database with the `:ruby`
schema format; once dumped, they cannot be re-imported.
This is because, up until MySQL 8.0.16, all check constraints were
surrounded by an extra set of parentheses; this behaviour differed
from that presented by MariaDB, which handled them correctly thanks
to an engine check within the AbstractMySqlAdapter.
With this change, we only strip the parentheses if they are present,
which prevents the corruption of the constraint.
It is also possible that the exported check constraint will contain
invalid and unexpected whitespace characters; we handle that here too,
stripping out sequences of `\\` and `\n`, as well as any other
whitespace.
When the relation being handled has no selected values, it fallsback to selecting the model's primary key. In composite key cases, this can lead to attempting to compare a single attribute to a list of attributes, which leads to malformed syntax at the SQL level. This check prevents any code from attempting to do so, by raising in CPK cases when defaulting to primary key. For now, users can build these queries themselves.
MySQL adapters take an auto_increment option but when using a primary
key type that option is silently ignored and doesn't change behavior.
This fixes the issue by only applying `options[:auto_increment] = true`
if it wasn't set to false already.
I didn't make changes to the other adapters because they don't accept
`auto_increment` as an option. If we want this for postgres we'll need
to implement the option first.
* Infer `foerign_key` when `inverse_of` is present
Automatically infer `foreign_key` on `has_one` and `has_many` associations when `inverse_of` is present.
When inverse of is present, rails has all the info it needs to figure out what the foreign_key on the associated model should be. I can't imagine this breaking anything
* Update test models to remove redundant foreign_keys
* add changelog entry
* fix changelog grammar
Co-authored-by: Rafael Mendonça França <rafael@franca.dev>
Ref: https://github.com/rails/rails/pull/47314
Ref: https://bugs.ruby-lang.org/issues/19436
`Object#extend` is really bad for performance as it generate an
infinite amount of unique classes from the point of view of the Ruby
virtual machine, so it keeps invalidating call caches.
Additionally, these call caches keep a reference on the last instance
they saw, which may lead to what is essentially a memory leak.
I discovered this while working on https://github.com/rails/rails/pull/47800
The bug is quite subtle.
If you call `Model.all.delete(id)`, `all` is an `ActiveRecord::Relation`
which does not respond to `delete`, so it delegates to `Model.delete`
and generate that method in the `GeneratedRelationMethods` module.
The problem however, is that `CollectionProxy` does define `delete`,
so after that initial call, the `Model::ActiveRecord_CollectionProxy`
subclass now has its `delete` method overridden, and now delegate
to the model.
Here I chose to keep that method generation caching, but I'm honestly
not convinced it's really needed. I question how much of a hotspot
these methods are, and we're busting method caches and generating
a lot of code to save on a minor `method_missing` call.
I think we should just remove that caching.
Typically, a fixture's label is hashed into a single unique identifier
that sufficiently represent the respective fixture. In composite key
models, there's still only one label, but a requirement to populate
values for an arbitrary number of columns. Until now, these columns
would all take on the same value, but these may appear odd to an end
user and lead to confusion. This commit uses the index of the column in
the composite key to shift the hash in a deterministic way. In this
case, we bit shift the hashed value index-times and modulo it with the
max. This differentiates components of the key enough that there doesn't
appear to be a correlation.
This updates the index name generation to always create a valid index name if one is not passed by the user.
Set the limit to 62 bytes to ensure it works for the default configurations of Sqlite, mysql & postgres.
MySQL: 64
Postgres: 63
Sqlite: 62
When over the limit, we fallback to a "short format" that includes a hash to guarantee uniqueness in the generated index name.
Fix: https://github.com/rails/rails/issues/47704
Superseed: https://github.com/rails/rails/pull/47722
While the instance variable ordering bug will be fixed in Ruby 3.2.2,
it's not great that we're depending on such brittle implementation detail.
Additionally, Marshalling Active Record instances is currently very inefficient,
the payload include lots of redundant data that shouldn't make it into the cache.
In this new format the serialized payload only contains basic Ruby core or stdlib objects,
reducing the risk of changes in the internal representation of Rails classes.
Given a model with a composite primary key like:
`TravelRoute.primary_key = [:from, :to]`
Calling `TravelRoute.ids` would return an array of identifiers which is
represented by an array of arrays:
```ruby
TravelRoute.all.ids # => [["Ottawa", "New York"], ["London", "Paris"]]
```
With the introduction of composite primary keys, a common usecase is querying for records with tuples representing the composite key. This change introduces new syntax to the where clause that allows specifying an array of columns mapped to a list of corresponding tuples. It converts this to an OR-joined list of separate queries, similar to previous implementations that rely on grouping queries.
Given a model with a composite primary key, for example:
`TravelRoute.primary_key = [:from, :to]`
and two objects of the given model, objects `a` and `b`, should be
equal to each other and have the same `hash` value if they have the same
values for the composite primary key, like:
```ruby
a = TravelRoute.new(from: "NYC", to: "LAX")
b = TravelRoute.new(from: "NYC", to: "LAX")
a == b # => true
a.hash == b.hash # => true
```
At the same time, two objects of the given model should not be equal to
each other and should have different `hash` values if they have
different primary key values or no primary key being set, like:
```ruby
a = TravelRoute.new(from: "NYC", to: "LAX")
b = TravelRoute.new(from: "NYC", to: "SFO")
a == b # => false
a.hash == b.hash # => false
TravelRoute.new == TravelRoute.new # => false
TravelRoute.new.hash == TravelRoute.new.hash # => false
```
Currently when opening the main framework pages there is no introduction
to the framework. Instead we only see a whole lot of modules and the
`gem_version` and `version` methods.
By including the READMEs using the `:include:` directive each frameworks
has a nice introduction.
For markdown READMEs we need to add the :markup: directive.
[ci-skip]
Co-authored-by: zzak <zzakscott@gmail.com>
Given a `has_many :through` association with `query_constraints`:
```ruby
BlogPost.has_many :posts_tags
BlogPost.has_many :tags,
through: :posts_tags,
query_constraints: [:blog_id, :post_id]
``
It is possible to nullify the association like `blog_post.tags = []`
which results in deletion of records from the `posts_tags` joining table.
In https://github.com/rails/rails/pull/46690 the `db_warnings_action` and `db_warnings_ignore` configs where added. The
`db_warnings_ignore` can take a list of warning messages to match against.
At GitHub we have a subscriber that that does something like this but also filters out error codes. There might also be
other applications that filter via error codes and this could be something they can use instead of just the explicit
messages.
This also refactors the adapter tests in order for mysql2 and postgresql adapters to share the same helper when setting
the db_warnings_action and db_warnings_ignore configs
Given an association defined with composite query constraints like:
```ruby
BlogPost.has_many :comments, query_constraints: [:blog_id, :blog_post_id]
```
it is possible to query blog posts by whole `comments` objects like:
```ruby
comments = Comment.first(2)
BlogPost.where(comments: comments).to_a
```