-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Add missing unique indices #343
Conversation
Thanks, I will take a look. Do you have EXPLAIN output at hand that shows the improvement? We will also need an upgrade migration for everyone who already has the gem. |
Per #294 (comment), I'll name the index |
Sorry for the delay, I kept forgetting what I needed to do, add an upgrade migration. Will do over the weekend. |
soon.. |
Why not to add just |
Ok, in terms of how engines and migrations work, right now we're copying over the migration.rb file. In order to allow an upgrade migration, I believe we'd need for me to make these changes in a second migration and update the engine to run install/copy/run multiple migrations in a sorted order. We could just specify our migrations and inject them directly but that would change the current behavior. Do you have any particular insights into that? @makaroni4 in terms of uniqueness constraint, context needs to be included because that is the 'tag group'. i.e. you could tag the genre of music with alternative and also tag the radio station style of the music as alternative (bad example) where the tag would be alternative in both cases but the context would be different, and that's okay. As for tagger_id and tagger_type, perhaps you're correct that they shouldn't be included in the uniqueness constraint, but that is how the constraint is currently specified in the rails code |
@bf4 for current constraint your index is good, you are right. |
Looks like I'll have to change the engine code to run multiple migrations |
Should be done now... could probably improve the documentation, but otherwise, I modified the commit to
|
bump |
1 similar comment
bump |
I've seen your bumps but the pull request doesn't merge cleanly and I'm swamped at the moment. |
Ok, will update the PR to merge cleanly |
@tilsammans Rebased the commit on top and force pushed |
As this is a plugin for Rails (I see the dependency in the gemspec), why not just hook into the |
@parndt Code example? Will that handle migration ordering, even while preserving the name of the already-existing migration? I find the documentation for this stuff pretty spotty, and mostly involves code-diving, which is why, when I get around to it, I'm going to help out with the documentation at https://github.com/bf4/docrails/tree/rails-engines/guides (as suggested by steve klabnik) |
For ordering you just have to name them sortably, for example Then, ensure your files are in # lib/plugin_name.rb which gets autoloaded by gem naming conventions.
require 'plugin_name/engine'
module PluginName
end # lib/plugin_name/engine.rb
require 'rails'
module PluginName
class Engine < Rails::Engine
end
end Or am I misunderstanding the requirements? |
I think so, @parndt there is already a migration prior to this PR named "migration.rb". So, a way to make that sortable didn't immediately occur to me, unless it were something like new-1_migration, new-2_migration, but that breaks the rails convention and we'd still have to implement next_migration_number anayways |
Why not just rename that to |
# if the orm supports migrations | ||
# @return [Array] an empty array if the orm does not support migrations | ||
# @example [ ['migration.rb', 'db/migrate/acts_as_taggable_on_migration'] ] | ||
# @note For historical reasons, all migrations are ordered by the format |
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.
@parndt Did you look at the diff?
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.
I looked but I did not understand why this was required.
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.
Because too much of rails engine knowledge requires source diving and I missed how easy it is to rename and move the files to db/migrate 😁
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.
😉
I, wrongly, thought that would break existing applications that used the gem by adding a duplicate migration. Now that you write that, I see that 1_migration.rb will resolve to the existing migration.rb Yay |
Yep, and Rails should install it as something like |
Updated to use the simpler Rails::Engine integration. Added some other commits I'm happy to remove and put in a different PR, if you want. |
If you're reviewing, I found a bug that it's appending '_engine' to the copied migration name. Looking at how to set the basename |
@parndt How annoying, not exactly as we thought current generated migration name pre-PR
new migration name(s) per simple rename of files as suggested above
Relevant code
Solution: rename 1_migration.rb to 1_acts_as_taggable_on_migration.rb since the migration.name is derived from the filename. Similarly, I had to rename migration to 2_add_missing_unique_indices.rb to match the class name in the file Command: |
Hi ❓ |
@bf4 did you figure out the |
@parndt Yeah. See comments above "rename 1_migration.rb to 1_acts_as_taggable_on_migration.rb since the migration.name is derived from the filename. Similarly, I had to rename migration to 2_add_missing_unique_indices.rb to match the class name in the file" |
Hello old friend, I've come to bump you once again @tilsammans @mbleigh |
Need help maintaining this? |
Alrighty then |
As far as I can tell there is no code in this gem to handle exceptions triggered by simultaneous writes of tag names to the newly introduced unique index. Am I correct, and is this by design? Do I need to handle exceptions when calling save_tags? |
Correct, you have to handle the exception in your application. Unless you have a very active application with multiple instances, the exception handling won't be required. |
I have to admit that that sounds like wishful thinking to me and I'm sort of surprised avoiding this issue is not a goal in this project. I don't have a particularly active application but I definitely found a duplicate tag exception in my logs (of course, it might just have been someone double-submitting a form). Is this problem so difficult to solve that a solution is not appropriate for this gem? Should I open a new issue and submit a pull request if I can solve the problem? At minimum, a mention that tags may not save correctly during normal operation seems to me like it's worth a mention in the project documentation. Thanks for sharing this gem and and for your guidance on this issue, Andrew |
A PR is welcome if it include tests. The reason i think why gems don't handle exception is that it depend on the adapter you are using. Also there is a multitude of exceptions that need to be handled :
|
Thanks for those points. I tend to think of those other issues as things that would happen during "normal" operating conditions. However, I see your point that you don't know what exception to expect when a duplicate tag is saved. It might be sufficient just to handle all exceptions and reattempt saving tags some configured number of times to avoid most failures. |
I do know the exception that is raised. But it raised by the adapter (pg in my case) not ActiveRecord. I think it ActiveRecord that need to be fixed to handle this type exceptions. |
This should be a new issue re: catching db-level exceptions. The db index |
[mbleigh#294] Add missing unique indices
Referenced in #294
Note that because indexed fields are added in order, the attached commit includes the index on :tag_id and the compound index on taggable_id, taggable_type, context
I was running consistency_fail on my project and it pointed out that since the app enforces uniqueness on these fields, the database should as well. (It's more reliable race-condition-wise, too)
This commit is not ruby 1.8 compatible. Based on the README, that seems appropriate