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

Global configuration for :ignore_log_data option #111

Merged
merged 3 commits into from
May 15, 2019

Conversation

DmitryTsepelev
Copy link
Collaborator

This is the implementation of #109. The idea is that we store a list of models that allow overriding the global setting (i.e. where :ignore_log_data is not specified) and when global setting is changed - we start or stop ignoring the log_data column.

Copy link
Owner

@palkan palkan left a comment

Choose a reason for hiding this comment

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

The current approach (model tracking and overriding) has one problem – it's not thread-safe.
And I don't think it's possible to make it thread-safe, unfortunately.

Looks like it's gonna be too complicated to patch this behaviour this way (via schema cache).

I have another idea: what if can add a default_scope which is only activated when the corresponding Logidze parameter (thread-safe) is true?

Smth like:

default_scope do
  with_log_data if Logidze.force_load_ignore_log_data
end

?

This way we cover the scenario: "ignore log data by default" + "load within a block".
And I don't think we need the opposite (at least for now): "enable by default" + "ignore within a block". Doesn't make a lot of sense to me.

CHANGELOG.md Outdated
Now it's possible to avoid loading `log_data` from the DB by default with

```ruby
Rails.application.config.logidze.select_ignore_log_data = true
Copy link
Owner

Choose a reason for hiding this comment

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

Can't see where we add logidze config to Rails.

Let's just use Logidze.ignore_log_data_by_default = true (yeah, and rename the option).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

✔️

@DmitryTsepelev
Copy link
Collaborator Author

DmitryTsepelev commented Jan 29, 2019

The approach itself works fine (not all the tests are green now!), but the problem is that reload uses just self.class.find(self.id, options), so most of the specs fail without something like this. Moreover, when the column is ignored - Rails does not even define an attribute for it.

Since we're using default_scope I'm thinking about the opposite approach: no ignored_columns, default_scope excludes log_data from select by default and there is no need to hack reload

@palkan
Copy link
Owner

palkan commented Jan 29, 2019

I'm thinking about the opposite approach: no ignored_columns, default_scope excludes log_data

I don't like the idea of replacing ignored_columns with the default scope: the first one is low-level, I'm afraid the latter one could have a lot of edge cases.

self.class.reset_column_information

This is not good for performance.

that reload uses just self.class.find(self.id, options),

Looks like it uses some scope-less version of .find, 'cause find itself uses default scopes.

So, the problem is only with reload; thus we can add reload_log_data call after reload if ignore_log_data is disabled (global parameter).

@DmitryTsepelev DmitryTsepelev force-pushed the global-ignore-config branch 5 times, most recently from 40e86ee to 26ea844 Compare January 31, 2019 14:47
@DmitryTsepelev
Copy link
Collaborator Author

@palkan Done! I've patched unscoped instead of reload to make it a bit more readable, I've also had to redefine column_names, because Rails >=4 caches them based on ignored_columns and does not even save not listed attributes while updating the record

@palkan
Copy link
Owner

palkan commented Jan 31, 2019

@DmitryTsepelev Looks good! Thanks!

@aderyabin Check please; any questions/suggestions?

@DmitryTsepelev DmitryTsepelev force-pushed the global-ignore-config branch 4 times, most recently from e7c524d to 04320b3 Compare March 15, 2019 08:13
@palkan
Copy link
Owner

palkan commented Mar 15, 2019

@DmitryTsepelev Looks like Rails 4.2 can not do size / count with explicitly selected columns and we should use count(:all) (as I remember):

1) Logidze::Model Versioned associations when feature is enabled has_many returns not versioned association #size, due to AR implementaion
     Failure/Error: expect(very_old_article.comments.size).to eql(2)
     
     ActiveRecord::StatementInvalid:
       PG::UndefinedFunction: ERROR:  function count(integer, text, jsonb, integer, timestamp without time zone, timestamp without time zone, jsonb) does not exist
       LINE 1: SELECT COUNT(id, content, log_data, article_id, created_at, ...
                      ^
       HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
       : SELECT COUNT(id, content, log_data, article_id, created_at, updated_at, log_data) FROM "comments" WHERE "comments"."article_id" = $1

Let's replace it with very_old_article.comments.to_a.size.

@DmitryTsepelev
Copy link
Collaborator Author

I bet our Rails 4 users still want to have working #size method :) I've patched with_log_data scope to call select("*") instead of select(column_names + ["log_data"]) when ignored_columns contains only "log_data" (which is the same thing as if Rails::VERSION::MAJOR == 4 because real ignored_columns were added in Rails 5). What do you think?

@palkan palkan merged commit 3b58a00 into palkan:master May 15, 2019
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