Commit Graph

17450 Commits

Author SHA1 Message Date
Yasuo Honda
d0d9e8e576
Merge pull request #47552 from lsylvester/where-include-index
Allow both include and where on PostgreSQL add_index
2023-03-06 18:33:01 +09:00
Rafael Mendonça França
9f60cd8dc7
Merge PR #45463 2023-03-03 22:58:01 +00:00
Rafael Mendonça França
35d574dbfd
Merge pull request #47569 from p8/activemodel/add-model-name-to-missing-attribute-error
Add class name to ActiveModel::MissingAttributeError error message
2023-03-03 17:50:26 -05:00
Eileen M. Uchitelle
3771f6865c
Merge pull request #47566 from Shopify/do-not-use-query-constraints-if-association-doesnt-explicitly-specifies-it
Do not use `query_constraints` if association doesn't explicitly specifies it
2023-03-03 09:14:50 -05:00
Eileen M. Uchitelle
8200a3d678
Merge pull request #47565 from Shopify/fix-nullifying-association-with-composite-query-constraints
Fix nullifying association with composite query constraints
2023-03-03 09:13:44 -05:00
Eileen M. Uchitelle
d90d3894cd
Merge pull request #45642 from kbrock/quoted_columns
[ActiveRecord] ToSql#HomogeneousIn uses visitor pattern to produce Attribute sql
2023-03-03 09:09:27 -05:00
Petrik
661c995f3b Add class name to ActiveModel::MissingAttributeError error message.
When an attribute is missing the current message is unclear about which
class is missing the attribute, especially when there are multiple
classes that could miss the attribute.

By adding the classs name to the error message it is easier to debug:

```ruby
user = User.first
user.pets.select(:id).first.user_id
=> ActiveModel::MissingAttributeError: missing attribute 'user_id' for Pet
```

This also makes the error message more inline with the
UnknownAttributeError message:

```ruby
=> ActiveModel::UnknownAttributeError: unknown attribute 'name' for Person
```

Co-authored-by: Yasuo Honda <yasuo.honda@gmail.com
2023-03-03 14:31:22 +01:00
Rafael Mendonça França
049dfd4ccf
Remove deprecated Tasks::DatabaseTasks.schema_file_type 2023-03-03 00:38:27 +00:00
Rafael Mendonça França
3ec629784c
Remove deprecated override of Enumerable#sum 2023-03-03 00:38:26 +00:00
Rafael Mendonça França
96b9fd6f14
Remove deprecated config.active_record.partial_writes 2023-03-03 00:38:25 +00:00
Rafael Mendonça França
96c9db1b48
Remove deprecated ActiveRecord::Base config accessors 2023-03-03 00:38:24 +00:00
Nikita Vasilevsky
f45663a30b Do not use query_constraints if association doesn't explicitly specifies it 2023-03-03 00:19:39 +00:00
Nikita Vasilevsky
2faba7433c Fix nullifying association with composite query constraints
Given a models setup like:
```ruby
class BlogPost < ApplicationRecord
  query_constraints :blog_id, :id

  has_many :comments, query_constraints: [:blog_id, :blog_post_id]
end

class Comment < ApplicationRecord
  query_constraints :blog_id, :blog_post_id

  belongs_to :blog_post, query_constraints: [:blog_id, :blog_post_id]
end
```

It should be possible to nullify both `blog_post.comments = []` and
`comment.blog_post = nil` association which should result in
nullification of all parts of the composite query constraints,
meaning `blog_id` and `blog_post_id` being nil on the affected comments.

Co-authored-by: Paarth Madan <paarth.madan@shopify.com>
2023-03-02 23:01:50 +00:00
Lachlan Sylvester
fd1a3b46b5 support using both include and where at the same time on a PostgreSQL index 2023-03-02 17:03:52 +11:00
Nikita Vasilevsky
2801ea64c3 Fix has_many through association assginments with custom scope and custom joining association name
`where_values_hash` method signature accepts `table_name` which is not
always the same as the association name.
So passing `through_association.reflection.name.to_s` as `table_name`
in `through_scope_attributes` wasn't accurate for every case.
This commit fixes the issue by passing the `table_name` taken from
`through_association.reflection.klass.table_name` instead.
2023-03-01 17:56:03 +00:00
Eileen M. Uchitelle
5cbf61502c
Merge pull request #47541 from Shopify/has-many-through-assign-with-query-constraints
Support assignments for composite key has_many through associations
2023-03-01 12:51:53 -05:00
Eileen M. Uchitelle
7d7ed37cfc
Merge pull request #47534 from Shopify/fix-polymorphic-has-many-through-assignments
Fix assigning through records when using polymorphic has many through association
2023-03-01 12:50:50 -05:00
Nikita Vasilevsky
bd93237d78 Support assignments for composite key has_many through associations
Given a has_many through association with a composite foreign key, like:
```ruby
class BlogPost < ApplicationRecord
  query_constraints :blog_id, :id

  has_many :blog_post_tags, query_constraints: [:blog_id, :blog_post_id]
  has_many :tags, through: :blog_post_tags
end

class BlogPostTag < ApplicationRecord
  belongs_to :blog_post, query_constraints: [:blog_id, :blog_post_id]
  belongs_to :tag, query_constraints: [:blog_id, :tag_id]
end

class Tag < ApplicationRecord
  query_constraints :blog_id, :id

  has_many :blog_post_tags, query_constraints: [:blog_id, :tag_id]
  has_many :blog_posts, through: :blog_post_tags
end
```

It should be possible to assign tags to a blog post:
```ruby
blog_post = BlogPost.create!(title: "Hello world")
blog_post.tags << Tag.new(name: "ruby")
```
2023-02-28 23:10:57 +00:00
Matt McMurray
e39b859b87
Replace call to BINARY with CAST(_ AS BINARY) (#47523)
* Replace call to BINARY with CAST(_ AS BINARY)

* Remove space b/w function and quote

Co-authored-by: Rafael Mendonça França <rafael@franca.dev>

* Update unit test to assert for new CAST syntax

---------

Co-authored-by: Rafael Mendonça França <rafael@franca.dev>
2023-02-28 16:15:44 -05:00
Nikita Vasilevsky
c12a77da40 Fix assigning through records when using polymorphic has many through association 2023-02-28 17:56:56 +00:00
eileencodes
232aed8504
Allow configs_for to accept a custom hash key
Now that we support a way to register custom configurations we need to
allow applications to find those configurations. This change adds a
`config_key` option to `configs_for` to find db configs where the
configuration_hash contains a particular key.

I have also removed the deprecation for `include_replicas` while I was
in here to make the method signature cleaner. I've updated the upgrade
guide with the removal.
2023-02-28 12:12:08 -05:00
eileencodes
3d004435b4
Allow applications to register custom database configurations
Previously, applications could only have two types of database
configuration objects, `HashConfig` and `UrlConfig`. This meant that if
you wanted your config to implement custom methods you had to monkey
patch `DatabaseConfigurations` to take a custom class into account. This
PR allows applications to register a custom db_config handler so that
custom configs can respond to needed methods. This is especially useful
for tools like Vitess where we may want to indicate it's sharded, but
not give Rails direct access to that knowledge.

Using the following database.yml as an example:

```yaml
development:
  primary:
    database: my_db
  animals:
    database: my_animals_db
    vitess:
      sharded: 1
```

We can register a custom handler that will generate `VitessConfig`
objects instead of a `HashConfig` object in an initializer:

```ruby
ActiveRecord::DatabaseConfigurations.register_db_config_handler do |env_name, name, url, config|
  next unless config.key?(:vitess)

  VitessConfig.new(env_name, name, config)
end
```

and create the `VitessConfig` class:

```ruby
class VitessConfig < ActiveRecord::DatabaseConfigurations::UrlConfig
  def sharded?
    vitess_config.fetch("sharded", false)
  end

  private
    def vitess_config
      configuration_hash.fetch(:vitess_config)
    end
end
```

Now when the application is booted, the config with the `vitess` key
will generate a `VitessConfig` object where all others will generate a
`HashConfig`.

Things to keep in mind:

1) It is recommended but not required that these custom configs inherit
from Rails so you don't need to reimplement all the existing methods.
2) Applications must implement the configuration in which their config
should be used, otherwise first config wins (so all their configs
will be the custom one.)
3) The procs must support 4 arguments to accommodate `UrlConfig`. I am
thinking of deprecating this and forcing the URL parsing to happen in
the `UrlConfig` directly.
4) There is one tiny behavior change where when we have a nil url key in
the config hash we no longer merge it back into the configuration hash.
We also end up with a `HashConfig` instead of a `UrlConfig`. I think
this is fine because a `nil` URL is...useless.

Co-authored-by: John Crepezzi <john.crepezzi@gmail.com>
2023-02-28 10:12:28 -05:00
Matthew Draper
31f5cb18fa
Merge pull request #47495 from olefriis/use-same-binding-grammar-for-arel-as-for-active-record
Use same rules for bindings in BoundSqlLiteral as in ActiveRecord
2023-03-01 00:38:13 +10:30
Matthew Draper
e0f1fc0c28
Merge pull request #47481 from olefriis/support-arel-nodes-as-bindings-in-bounds-sql-literal
Support Arel nodes as bindings in BoundSqlLiteral
2023-03-01 00:37:38 +10:30
Ole Friis Østergaard
4dabfd7f5e Respect permitted_classes for default yaml column serializer 2023-02-28 11:49:31 +01:00
Ole Friis Østergaard
009461f320 Revert to previous heuristic for determining type/coder 2023-02-28 11:48:39 +01:00
Keenan Brock
07d2407bee
Use visitor pattern in ToSql#HomogeneousIn to produce Attribute sql
In `ToSql`, operators that generate the sql for an `Attribute` use `visit(o.left, collector)`
This can be seen in `Equality` (and friends), `Case`, `SelectStatement`, and `In`.

`HomogeneousIn` manually produces the sql for an `Attribute`, introduced in 72fd0bae
This change makes `HomogeneousIn` follow the pattern.
2023-02-27 17:11:14 -05:00
Jean Boussier
c15093c856
Merge pull request #47518 from adrianna-chang-shopify/ac-fix-pg-sql-warnings
Avoid setting notice receiver on PG connection when ignoring SQL warnings
2023-02-27 17:32:43 +01:00
Eileen M. Uchitelle
08d75b4140
Merge pull request #47425 from adrianna-chang-shopify/ac-fix-no-autoincrement-sqlite
Ensure `AUTOINCREMENT` declaration is preserved when altering SQLite tables
2023-02-27 11:11:07 -05:00
Adrianna Chang
099711c037
Avoid setting notice receiver on PG connection when ignoring SQL warnings 2023-02-27 10:23:10 -05:00
Eileen M. Uchitelle
65ae7d1755
Merge pull request #47476 from sj26/disable-joins-uuids
Disable Joins UUID support
2023-02-27 09:18:41 -05:00
Jorge Manrubia
5d7b6d823f
Add option to configure digest algorithm used by Active Record Encryption (#44873)
Before, it was using the configured by Rails. Having a mechanism to configure it
for Active Record encryption makes sense to prevent problems with encrypted content
when the default in Rails changes.

Additionally, there was a bug making AR encryption use the older SHA1 before
`ActiveSupport.hash_digest_class` got initialized to SHA256. This bug was exposed
by https://github.com/rails/rails/pull/44540. We will now set SHA256 as the standard
for 7.1+, and SHA1 for previous versions.
2023-02-27 10:16:41 +01:00
Samuel Cochran
18ecbe987e
Avoid casting to an integer
Not all ids are integers. Existing tests still pass without the cast,
and removing the cast causes uuid joins to work.
2023-02-27 10:49:09 +11:00
Yasuo Honda
357b1cfb1f Use squiggly heredoc to remove extra spaces after DEPRECATION WARNING:
- Without this commit

```ruby
DEPRECATION WARNING:                 Passing the coder as positional argument is deprecated and will be remove in Rails 7.2.

                Please pass the coder as a keyword argument:

                  serialize :foo, coder: JSON
 (called from <class:User> at rep.rb:20)
DEPRECATION WARNING:                 Passing the class as positional argument is deprecated and will be remove in Rails 7.2.

                Please pass the class as a keyword argument:

                  serialize :bar, type: Hash
 (called from <class:User> at rep.rb:21)

```

- With this commit

```ruby
DEPRECATION WARNING: Passing the coder as positional argument is deprecated and will be remove in Rails 7.2.

Please pass the coder as a keyword argument:

  serialize :foo, coder: JSON
 (called from <class:User> at rep.rb:20)
DEPRECATION WARNING: Passing the class as positional argument is deprecated and will be remove in Rails 7.2.

Please pass the class as a keyword argument:

  serialize :bar, type: Hash
 (called from <class:User> at rep.rb:21)
```
2023-02-26 23:42:32 +09:00
Jon Dufresne
da82e587f2 Improve typography of user facing validation messages
With the universal adoption of UTF-8 in browsers, user facing text can
use more optimal Unicode typography. In digital and print design, using
RIGHT SINGLE QUOTATION MARK (U+2019) is normally preferred over
APOSTROPHE (U+0027) in contractions.

For details, see the Unicode Standard Section 6.2:
https://www.unicode.org/versions/Unicode13.0.0/ch06.pdf

> Punctuation Apostrophe. U+2019 right single quotation mark is
> preferred where the character is to represent a punctuation mark, as
> for contractions: “We’ve been here before.” In this latter case,
> U+2019 is also referred to as a punctuation apostrophe.
2023-02-25 08:21:19 -08:00
fatkodima
2a6adc9efe Speedup activerecord tests 2023-02-25 02:04:10 +02:00
Ole Friis Østergaard
03f2a2c331 Use same rules for bindings in BoundSqlLiteral as in ActiveRecord 2023-02-24 13:28:00 +00:00
Ole Friis Østergaard
584ad87572 Support Arel nodes as bindings in BoundSqlLiteral 2023-02-24 08:49:37 +00:00
Jean Boussier
cee15555c9 Stop serializing columns as YAML by default
YAML is great for configuration and such, but for serializing arbitrary
data it has many problem, both in term of performance and efficiency
but also in term of security.

As such, we shouldn't let it be the default.

The open question is wether we should provide another default, or
just let users chose what they want based on their own tradeoffs.

Many people would probably suggest JSON as the new default, unfortunately
I don't think it's a good fit either because the parsers available in
Ruby have some wonky behaviors:

```ruby
>> ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(Object.new))
=> {}
>> JSON.load(JSON.dump(Object.new))
=> "#<Object:0x000000012b61a068>"
```

If we were to select another default, I beleive it would need several
properties:

  - It should only serialized a safe list of primitive types.
  - It should explictly raise if attempting to serialize complex types.
2023-02-24 08:55:04 +01:00
Jean Boussier
b0dd7c7ae2
Merge pull request #47482 from Shopify/serialization-default
Serialized attribute should be able to be defined in abstract classes
2023-02-23 17:45:23 +01:00
Jean Boussier
c4c0b799e4 Serialized attribute should be able to be defined in abstract classes
Ref: https://github.com/rails/rails/pull/47191

This feature recently regressed when https://github.com/rails/rails/pull/47191
was merged to handle defaults.

The `attribute` definition callback is set on the parent class and
is triggered when the child class schema is loaded.

I don't know if this is fixeable.
2023-02-23 17:08:02 +01:00
Lorin Thwaits
093cc00ded Avoid "comparison of Gem::Version..." error in Ruby < 3.1 2023-02-23 11:25:45 +00:00
zzak
d2af670dba
Remove Copyright years (#47467)
* Remove Copyright years

* Basecamp is now 37signals... again

Co-authored-by: David Heinemeier Hansson <dhh@hey.com>

---------

Co-authored-by: David Heinemeier Hansson <dhh@hey.com>
2023-02-23 11:38:16 +01:00
Carlos Antonio da Silva
701311e9cd Improve wording on eager_load and preload AR docs [ci skip] 2023-02-22 20:44:13 -03:00
Carlos Antonio da Silva
c4b050984a Fix a couple typos and revise sentence on new column serializer docs
[ci skip]
2023-02-22 20:05:05 -03:00
Jean Boussier
185f2d718d Allow to define the default column serializer
YAML has quite a bit of footguns, as such it's desirable
to be able to substitute it for something else or even
simply to force users to define a serializer explictly for
every serialized columns.
2023-02-22 19:32:28 +01:00
Eileen M. Uchitelle
3886edc676
Merge pull request #47452 from Shopify/has-many-through-with-query-constraints
Support has_many through associations with composite query_constraints
2023-02-22 09:36:50 -05:00
Jean Boussier
2c97993201
Merge pull request #47191 from serg-kovalev/fix/issue-46351-serialize-default
Respect Column default in Type::Serialized
2023-02-22 10:30:04 +01:00
Siarhei Kavaliou
695db7b7a5
Respect Column default in Type::Serialized #46351 2023-02-22 10:03:53 +03:00
Nikita Vasilevsky
5e915f3879 Support has_many through associations with composite query_constraints
Given an association like:
```ruby
BlogPost.has_many :blog_post_tags,
  query_constraints: [:blog_id, :blog_post_id]
BlogPost.has_many :tags, through: :blog_post_tags
```

The `tags` association records can be queried
and the resulting JOIN query will include both `blog_id` and
`blog_post_id` in the ON clause.
2023-02-22 00:01:22 +00:00