2

I have a en.yml which contains the following

en:
  article:
    title:
      format: "Requires at least one alphanumeric character"
    title_format: "Title Requires at least one alphanumeric character"

The article.title.format is used in my article model and article.title_format is used in article_test test. Is there any way to make this DRY?

vvbdtt
  • 72
  • 5
  • Why do you have a dedicated model for tests? Are those strings error messages? – spickermann Oct 23 '22 at 15:36
  • Sorry. There is no dedicated model for test, will update in the question. Yes, those are the error messages. – vvbdtt Oct 23 '22 at 15:56
  • This might not be worth the trouble. Unless your translator knows YAML really well they're bound to foul it up, plus the phrasing might differ based on context not present in English. – tadman Oct 23 '22 at 17:32

1 Answers1

1

YAML is limited for things like this, but you do have anchors, aliases and merge_keys. This SO answer is VERY exhaustive on this issue.

So, you can repeat the exact same message, but not modify that message without some other library or code injection:

&standard_answer: "Requires at least one alphanumeric character" 
en:
  article:
    title:
      format: *standard_answer
    title_format: *standard_answer

in Ruby, is equivalent to:

en:
  article:
    title:
      format: "Requires at least one alphanumeric character" 
    title_format: "Requires at least one alphanumeric character" 

To answer the question you aren't asking...

If you are trying to test model validations, I think you're doing too much anyway:

  • These will break if Rails decides to tweak the language used
  • Your tests now rely on your i18n file just to find a hard-coded string
  • It's less readable because the test constraints are now in 2 separate files (but it is more compact, so you could argue that)

What you want to know is: "Can I save this record without any alphanumeric characters in the title?"

I would only test whether the validation succeeds or fails.

If you're using RSpec, I like this pattern.

Or, another option, RSpec Expectations ships with Predicate matchers:

# prove the record is valid
expect(record).to be_valid

# make the record invalid in only 1 way
record.title = 'does not have a number'
expect(record).to be_invalid # also works: expect(record).not_to be_valid

Note that I'm making sure the record is valid first, then changing one thing, then checking for validity again. This helps ensure you are testing the right validation.

Chiperific
  • 4,428
  • 3
  • 21
  • 41
  • This is not working when I run rails unit test. It interprets ``"{{standard_answer}}"`` as a string. – vvbdtt Oct 23 '22 at 16:33
  • 1
    Sorry, it's language specific! See this for YAML in Ruby: https://yaml.org/YAML_for_ruby.html#aliases_and_anchors – Chiperific Oct 23 '22 at 16:47