Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hi,
Firstly, apologies: this is a bit of an epic, but it's taken me a while to get my head round it, so I've tried to explain thoroughly.
I noticed some odd behaviour recently when trying to force slug regeneration, which I traced down to
Model#should_generate_new_friendly_id?
. This returns inconsistent values depending on the order of certain operations. An example to recreate:This divergence of behaviour leads to oddities like this test, in which a record needs to be saved twice after its slug is cleared before being restored.
It turns out this was being caused by the mis-ordered setting of
@current_friendly_id
, which occurs in abefore_save
lifecycle callback. However#set_slug
, which calls#should_generate_new_friendly_id
to check whether a new slug is needed, is called in abefore_validation
callback, which happens prior tobefore_save
.This means that as far as
#should_generate_new_friendly_id
is concerned,@current_friendly_id
doesn't represent the current friendly_id at all, but rather the friendly_id at the time this particular instance of the record was last saved (if at all).This could be fixed by setting
@current_friendly_id
in a prependedbefore_validation
callback. However this would be pointless, as then it would always be identical to the current value of the slug column, which#should_generate_new_friendly_id
also fetches.The attached commits provide updated tests for the regeneration behaviour, and address the issue by only checking the current value of the slug column in
#should_generate_new_friendly_id?
, removingcurrent_friendly_id
completely.Unfortunately, however, this breaks a test in
SimpleI18n
:The reason this worked before was another bug in
#should_generate_new_friendly_id?
, whereby ifcurrent_friendly_id
was set, only that would be compared against the slug base - the current slug column value was not checked at all. So in the above test, the following happened:Journalist
is created in:es
locale,slug_es
and@current_friendly_id
set to "juan-fulano":en
locale with supplied base text "John Doe",slug_en
set to "john-doe"#set_slug
invoked again during final#save!
call#should_generate_new_friendly_id
compares normalized name ("juan-fulano") withcurrent_friendly_id
- they match, so returns false.slug_en
Now, however, the last two steps go:
#should_generate_new_friendly_id
compares normalized name ("juan-fulano") with current locale slug value, "john-doe". They don't match, so it returns true.#set_slug
overwrites theslug_en
column with a newly-generated slug based on the record name, setting it back to "juan-fulano"I'm not really sure how to fix this, or if it even can be fixed. Because the
SimpleI18n
module doesn't do translation, and has no way of keeping track of base texts for different locales over multiple model loads, even if we fix this particular test failure so thatslug_en
isn't overwritten, the next time the model is loaded and saved in the:en
locale, it'll get splatted for sure.So. A pull request with some fixes, but also a breakage and a conundrum. Sorry about this - I'd be glad to hear your thoughts...
Cheers,
Simon