Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract MySQL into adapter so we can run against other databases #4

Closed
wants to merge 2 commits into from

Conversation

shioyama
Copy link
Member

@shioyama shioyama commented Jan 30, 2025

What the title says: extract the stuff in ActiveRecord::DatabaseValidations::MySQL into ActiveRecord::DatabaseValidations::Adapters::MySQL so we can add other databases. I implemented a minimal registry with proc values that require/return the adapter class.

@shioyama shioyama marked this pull request as ready for review January 30, 2025 06:32
@shioyama shioyama force-pushed the shioyama/database_adapters branch from 844c4d0 to ec33d77 Compare January 30, 2025 07:28
Copy link

@nvasilevski nvasilevski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like in all places we have access to the model class which makes me wonder if that's what we need to use to choose the adapter. Model's connection is what defines the adapter and all columns should belong to the same adapter for a given model. So I'd like to suggest we change the DatabaseValidations::Adapters.for implementation to accept an AR model class/connection class or database name to base the selection on with potential memoization to avoid executing the same code for every column

@@ -77,6 +77,10 @@ def validate_each(record, attribute, _value)
validator.validate(record)
end
end

def adapter_for(column)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should design it in a way to allow choosing the adapter per connection or database configuration. For majority of the applications adapter will not change regardless of the model used. Some application in rare cases may use different databases for different models and we need to account for that. But it's unfortunate to keep executing the same code for every column even though we know columns of the same model will belong to the same adapter

@registry = {}

def self.for(column)
name = column.class.name.delete_prefix("ActiveRecord::ConnectionAdapters::")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is what makes me the most concerned. It feels like we are relying too much on the internal structure of Rails which may change. I'd much rather rely on adapter names like mysql2, sqlite3 and postgresql which are unlikely to be changed

@@ -7,8 +7,9 @@ def truncate_value_to_field_limit(field, value)
return if value.nil?

column = self.class.columns_hash[field.to_s]
maximum, type, encoding = ActiveRecord::DatabaseValidations::MySQL.column_size_limit(column)
value = ActiveRecord::DatabaseValidations::MySQL.value_for_column(value, encoding)
adapter = DatabaseValidations::Adapters.for(column)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked around the docs and my suggestion is build the registry around adapter names and not column instances

Suggested change
adapter = DatabaseValidations::Adapters.for(column)
adapter = DatabaseValidations::Adapters.for(self.class.connection_db_config.adapter)

@shioyama shioyama force-pushed the shioyama/database_adapters branch from ec33d77 to de65d1a Compare January 31, 2025 05:37
@shioyama
Copy link
Member Author

shioyama commented Jan 31, 2025

I'm really not confident this is the right approach (even with the suggestions here, thanks!). It feels like we shouldn't need this gem at all, if ActiveRecord provided enough of the column type configuration.

@nvasilevski
Copy link

It feels like we shouldn't need this gem at all, if ActiveRecord provided enough of the column type configuration.

I would really love to see Rails implementing the features we need instead!

@shioyama
Copy link
Member Author

shioyama commented Feb 3, 2025

Replaced by #6

@shioyama shioyama closed this Feb 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants