-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Allow to disable attribute discovery in ActiveRecord #27903
Conversation
r? @sgrif (@rails-bot has picked a reviewer for you, use r? to override) |
# | ||
# Despite on the fact that `projects` table has more columns that `name` and `members_count`, | ||
# ActiveRecord will only use explicitly declared attributes | ||
def attribute_auto_discovery |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't be this moved to included
block and defined via mattr_accessor
or class_attribute
with default value as another options?
@@ -448,6 +471,11 @@ def load_schema | |||
|
|||
def load_schema! | |||
@columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns) | |||
|
|||
unless attribute_auto_discovery | |||
@columns_hash.reject! { |k| !attributes_to_define_after_schema_loads.key?(k) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this filtering necessary? Why can't we just skip the schema load entirely? 😕
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. This should definitely just be return unless attribute_auto_discovery
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This filtering in necessary because otherwise @columns_hash
will include all table columns. It's loaded in the line above.
We already do this filter for ignored columns (.except(*ignored_columns)
)
I'd prefer something like |
Generally if the default is true for a new configuration is true, we invert the name: See #26976 (comment) for more. |
|
|
Note: I want to be conservative to start. We can always change it to have |
Thanks everyone for the feedback! |
@@ -149,6 +176,9 @@ module ModelSchema | |||
class_attribute :ignored_columns, instance_accessor: false | |||
self.ignored_columns = [].freeze | |||
|
|||
class_attribute :skip_defining_attributes_from_schema, instance_accessor: false | |||
self.skip_defining_attributes_from_schema = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we drop the skip_
and have it default to true
?
|
||
if skip_defining_attributes_from_schema | ||
if ignored_columns.any? | ||
raise ArgumentError, "can't use ignored_columns and skip_defining_attributes_from_schema at the same time" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's handle this in the writer method for define_attributes_from_schema
and ignored_columns
. We want to error early, and we shouldn't assume this is the only place the two can interact.
raise ArgumentError, "can't use ignored_columns and skip_defining_attributes_from_schema at the same time" | ||
end | ||
|
||
if primary_key && !attributes_to_define_after_schema_loads.key?(primary_key) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like it should be unnecessary.
Sometimes you want to explicitly declare attributes in the model with Attributes API and ignore the rest of table columns.
I've addressed all concerns 👌
For that, I had to move away from |
🙏 👀 when you have a minute. |
@columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns) | ||
@columns_hash = connection.schema_cache.columns_hash(table_name) | ||
|
||
unless define_attributes_from_schema |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like the wrong place to handle things. We should not be modifying columns_hash
based on this setting (other than perhaps not setting it at all). It seems like we should be skipping the loop down below instead.
@sgrif I'm ready to invest time into finishing this feature and addressing the feedback, but is it something that you'd like to see in ActiveRecord? |
is this something that is being worked on? I would like to use a feature like this. I'm happy to take finishing this PR if @kirs would like me to |
@robotdana yes! I was planning to have someone in my team to work on it but we are happy to also review a PR if it is open. |
Closing in favour of #35309 |
This works as an opposite to
ignore_columns
. Sometimes we want to explicitly declare used columns with Attributes API in the model and use only them, ignoring the rest of columns:@wvanbergen @rafaelfranca @matthewd