thoughtbot / factory_bot_rails

Factory Bot ♥ Rails

Home Page:https://thoughtbot.com/services/ruby-on-rails

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Issues with custom error message translations

elcommie opened this issue · comments

We have a model class in rails with the following validation:

  validates :items, length: {
    minimum: 1, message: I18n.t('items.one_required')
  }

This works fine in version 5.0.1, but in 5.0.2 there's a translation missing: en.items.one_required in the errors collection. Not sure why factory_bot would affect the i18n class but it appears to.

There was a bug in 5.0.1 that was causing the factory_bot_rails reloader to watch the project root in some cases. We fixed that in 5.0.2. This probably has something to do with that fix. This is definitely not expected behavior!

I will try my best to reproduce this. Please share whatever details you can.

Thanks!

It's in the standard config/locales/en.yml file and I see that file near the bottom of the reloaders as you'd expect.

Interestingly, I tried loading factory_bot in console and creating a record there and it worked. But in rspec it fails. Also, I tried just creating a new model that wasn't as complex as mine (my production model inherits from two different other models, uses mixins and a number of other things built up over the years) and that one worked too. Very odd. I'll see if I can narrow down the scenario that triggers this

@composerinteralia I had the same issue come up and I think I narrowed it down to this change, though it might actually be the one mentioned above(#331 ). I'm not sure how to recommend a fix 😅 but maybe some more information:

It appears the new change is causing the suite to load_definitions before the globalization yml files are loaded. Interestingly enough, I was able to get tests successfully passing by putting a binding.pry in a factory (in which I was able to verify that the translations are not being loaded before the factory definitions are loaded), and calling FactoryBot.reload in the console, which in a hacky way loaded the I18n translations, allowing the test to succeed since the translations were then defined.

Hope this helps 😄

Also ran into the same error, any news on when this might be fixed?

Would one of you be able to provide a sample application that reproduces the error? That would make this much easier to debug.

@composerinteralia Interestingly, I replicated the relevant code in a rails new application, but can't seem to reproduce the error. Not sure if that helps at all.

@composerinteralia I'm running into this as well with this application: https://github.com/codeforamerica/ohana-api

Here is an example failing spec: https://github.com/codeforamerica/ohana-api/blob/master/spec/api/patch_organization_spec.rb#L76
Here is the presence validation with custom localized error message: https://github.com/codeforamerica/ohana-api/blob/master/app/models/organization.rb#L17
And here is the custom message defined in config/locales/en.yml:
https://github.com/codeforamerica/ohana-api/blob/master/config/locales/en.yml#L342

Hey, are there any updates on the issue? I am experiencing the same bug in our project.

No updates that I know of. I haven't been able to reproduce the error in the ohana-api application because I haven't been able to get it running. I think I need either a simpler application that reproduces the error, or some help getting ohana-api set up.

@composerinteralia Ok, I've found a way to reproduce it in a new rails app.

https://github.com/zuchmanski/factory-bot-rails-failing-example

To reproduce please clone the repo, bundle install, rake db:schema:load and run rspec --backtrace spec/example_spec.rb.

I've found out that it only happens if you try to read translation during class loading inside the factory:

class Post < ApplicationRecord
  HELLO = I18n.t('hello')
end
FactoryBot.define do
  factory :post do
    title { 'Message' }

    # This loads a Post class, fails since translations are not loaded yet.
    # Comment this line and spec passes.
    Post::HELLO
  end
end

Full diff from empty rails app: https://github.com/zuchmanski/factory-bot-rails-failing-example/commit/2953068207b22eeb08dc00c495addb4c2dcddce0

Hi, I have the same issue with a translation present in a model.

I reproduced it really quickly with this code:

class Model
  REASONS = I18n.t("enumerize.reason")
end

Whereas I had no problem before updating factory_bot_rails from 5.0.1 to 5.0.2, now I have this:

I18n::MissingTranslationData (translation missing: en.enumerize.reason)

@composerinteralia

Is there anything I can do to help you? Have you been able to reproduce the behavior with my repo?

I can try working on it if you could point me the changes, files that you suspect broke the code loading logic.

I am experiencing a similar case
code:

class Model
  validates :foreign_key_id, presence: { message: I18n.t('path.to.locale') }
end

test:

it do
  is_expected.to validate_presence_of(:foreign_key_id).with_message(I18n.t('path.to.locale'))
end

error:

Expected Model to validate that :foreign_key_id cannot be
empty/falsy, producing a custom validation error on failure, but this
could not be proved.
  After setting :foreign_key_id to ‹nil›, the matcher expected the
  Model to be invalid and to produce the validation
  error "Locale translation" on :foreign_key_id. The record was indeed
  invalid, but it produced these validation errors instead:

  * foreign_key_id: ["<span class=\"translation_missing\"
    title=\"translation missing: en.path.to.locale\">Path To Locale</span>"]

I have an idea about how to fix this. I will work on it a bit today and then either make a PR or post here what I have learned so far.

Not quite ready to merge, since I had some trouble with testing, but it would be helpful if somebody that has encountered this problem can confirm that the fix in #343 works for you.

I tried it out on the app @zuchmanski provided and it seems to have done the trick.

@composerinteralia on my setup it returned the following error:

An error occurred while loading rails_helper.
Failure/Error: require File.expand_path('../config/environment', __dir__)

NoMethodError:
  undefined method `reloader' for #<Test::Application:0x00007fdd0202a0f8>
  Did you mean?  reloaders
# ./config/environment.rb:4:in `<top (required)>'
# ./spec/rails_helper.rb:4:in `<top (required)>'

Thanks for trying it out! I am also seeing that error on CI for certain versions. It seems there is more work to be done here. What version of Rails are you on?

That project is on rails 4.2.11.1

Not quite ready to merge, since I had some trouble with testing, but it would be helpful if somebody that has encountered this problem can confirm that the fix in #343 works for you.

@composerinteralia I confirm that the fix works in our projects! Thanks!

@composerinteralia I confirm it fixes the issue in ohana-api. Thanks!

@composerinteralia #347 works for us (did not test #343, though)