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

fixes #9981 - making sure lookup_keys with errors get displayed if they're broken #2693

Closed
wants to merge 1 commit into from

Conversation

unorthodoxgeek
Copy link
Member

apparently, ActiveRecord has a bug...
foo.update_attributes(params) creates a new bar, but it fails validations so isn't saved in DB.

foo.bars will have unsaved bars, but foo.bars.includes(:baz) will discard the unsaved bars.

I ❤️ Rails, don't you?

@unorthodoxgeek
Copy link
Member Author

thanks @waldenraines for helping out in investigating this issue 👍

@orrabin
Copy link
Member

orrabin commented Sep 9, 2015

@unorthodoxgeek works for me! 👍

@waldenraines
Copy link

👍

@domcleal
Copy link
Contributor

This removes the optimisation for existing smart variables and triggers a Bullet warning. Can the includes be used on existing records only?

@unorthodoxgeek
Copy link
Member Author

unorthodoxgeek commented Sep 10, 2015 via email

@domcleal
Copy link
Contributor

Do you know in what version we can revert it?

OK, I see now that you're not going to be able to use new_record, since it's retrieving all lookup keys. Could you whitelist it in Bullet then, probably via a skip_bullet type helper?

@unorthodoxgeek
Copy link
Member Author

updated. there doesn't seem to be a N+1 issue anymore, but bullet doesn't see that, probably because it listens to includes and not to the preloader service...

@domcleal
Copy link
Contributor

What Bullet warning do you still get precisely? Can you paste the logs? I'm not seeing one here.

I wonder if we shouldn't just call .includes back when we're retrieving the initial Puppetclass, since then we'll be including the right objects before we call .update_attributes in the #update action, and won't be reloading them when intending to retrieve.

@unorthodoxgeek
Copy link
Member Author

ok, now it's working correctly, and doesn't break MVC - I moved the preloader to a before filter, it works like a charm, no bullet warning, no extra queries.

@@ -85,4 +86,8 @@ def action_permission
super
end
end

def fetch_associations
ActiveRecord::Associations::Preloader.new(@puppetclass.lookup_keys, [:lookup_values]).run
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use .includes with find_resource instead? This class doesn't appear to be part of the intended public API (rails/rails#11719 (comment)).

Copy link
Member Author

Choose a reason for hiding this comment

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

no, that's the point of this PR, this doesn't work when using includes.

Copy link
Contributor

Choose a reason for hiding this comment

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

The original code called .includes on the association, not on the original resource, causing the objects in the association to get reloaded. Calling includes on the top level resource (Puppetclass), before setting attributes on it ought to work?

Copy link
Member Author

Choose a reason for hiding this comment

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

sometimes I wonder why I even bother disagreeing with you. you're right, as you usually are 😄

Copy link
Contributor

Choose a reason for hiding this comment

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

Nah, that'd make for a very dull life, and we'd learn nothing.

@@ -85,4 +86,8 @@ def action_permission
super
end
end

def fetch_associations
@puppetclass.lookup_keys.includes(:lookup_values)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this needs to happen before the .find, probably by overriding resource_scope?

def resource_scope
  super.includes(:lookup_keys => [:lookup_values])
end

At the moment it's preloading it here, but it's not having an effect later when the view calls @puppetclass.lookup_keys[0].lookup_values or something, so causes a second query (and Bullet warning).

You can replicate this in the console, if you compare:

pc = Puppetclass.includes(:lookup_keys => [:lookup_values]).find('example')
pc.lookup_keys.first.lookup_values

to

pc = Puppetclass.find('example')
pc.lookup_keys.includes(:lookup_values)
pc.lookup_keys.first.lookup_values

The latter will generate extra queries.

@domcleal
Copy link
Contributor

Merged as de65857, thanks @unorthodoxgeek.

@domcleal domcleal closed this Oct 26, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants