2

I am having an annoying issue with using Globalize + RSpec + factory_girl. I have a model with an attribute translated, and when creating factories using factory_girl the issue occurs. The code explains it perfectly:

Translation migration:

  def self.up
    CandidateBranch.create_translation_table!({
      name: {type: :string, null: false, limit: 150 }
    }, {
      migrate_data: true
    })
  end

Model:

class CandidateBranch < ActiveRecord::Base
  translates :name
  ####### Validations ---------------------------------------------------------
  validates :name, presence: true, length: { in: 2..150 }

  ####### more code
end

Factory:

FactoryGirl.define do
  factory :candidate_branch do
    sequence(:id) { |id| id }
    sequence(:name) { “trying out" }
  end
end

Test:

require 'rails_helper'
RSpec.describe CandidateBranch, type: :model do
  context "Validate" do
    it "has a valid factory" do
      record = FactoryGirl.attributes_for(:candidate_branch)
      puts "parameters => #{record.inspect}"
      record = CandidateBranch.create record
      puts "parameters => #{record.inspect}"
      expect(record).to be_valid
    end
  end
end

Logs:

▶ RAILS_ENV=test bundle exec rspec spec/models/candidate_branch_spec.rb
"parameters => {:id=>1, :name=>\"trying out\"}"
F

Failures:

  1) CandidateBranch Validate has a valid factory
     Failure/Error: record CandidateBranch.create record
     ActiveRecord::StatementInvalid:
       Mysql2::Error: Field 'name' doesn't have a default value: INSERT INTO `candidate_branches` (`id`, `created_at`, `updated_at`) VALUES (1, '2015-02-18 12:27:57.486623', '2015-02-18 12:27:57.486623’)

Mysql Transaction:

   (0.3ms)  BEGIN
  CandidateBranch::Translation Load (0.5ms)  SELECT `candidate_branch_translations`.* FROM `candidate_branch_translations` WHERE `candidate_branch_translations`.`candidate_branch_id` = 1
   (0.4ms)  SAVEPOINT active_record_1
  SQL (0.6ms)  INSERT INTO `candidate_branches` (`id`, `created_at`, `updated_at`) VALUES (1, '2015-02-18 12:27:57.486623', '2015-02-18 12:27:57.486623')
Mysql2::Error: Field 'name' doesn't have a default value: INSERT INTO `candidate_branches` (`id`, `created_at`, `updated_at`) VALUES (1, '2015-02-18 12:27:57.486623', '2015-02-18 12:27:57.486623')
   (0.2ms)  ROLLBACK TO SAVEPOINT active_record_1
   (0.3ms)  ROLLBACK

As seen in the record, although among the parameters attribute ‘name' is defined when creating the record in the database query, the translation table obviously finds nothing and then try to create the registry without the field translated, which fails.

However, if we comment translation statement in the model…

class CandidateBranch < ActiveRecord::Base
  #translates :name
  ####### Validations ---------------------------------------------------------
  validates :name, presence: true, length: { in: 2..150 }

  ####### more code
end


▶ RAILS_ENV=test bundle exec rspec spec/models/candidate_branch_spec.rb
"parameters => {:id=>1, :name=>\"trying out\"}"
"parameters => #<CandidateBranch id: 1, name: \"trying out\", created_at: \"2015-02-18 12:29:09\", updated_at: \"2015-02-18 12:29:09\”>"

MySQL transaction:

   (0.3ms)  BEGIN
   (0.4ms)  SAVEPOINT active_record_1
  SQL (0.5ms)  INSERT INTO `candidate_branches` (`id`, `name`, `created_at`, `updated_at`) VALUES (1, 'trying out', '2015-02-18 12:29:09.195756', '2015-02-18 12:29:09.195756')
   (0.3ms)  RELEASE SAVEPOINT active_record_1
   (0.4ms)  ROLLBACK

Is it a bug? Am I doing something wrong? Did this happened to anyone else?

Halil Özgür
  • 15,731
  • 6
  • 49
  • 56

2 Answers2

0

I answer myself. Globalize does not fill translated fields in the table base model, what it does is move these fields to their table translations. This means that the validation of the attribute must be applied on the fields translated as the original field is empty.

0

As you found out yourself, globalize moves the translated values to the ..._translations table.
Your error message is caused by a NOT NULL database constraint on the base table, that was obviously set by a former migration with option null: false.

To make your example work, you need to add to your migration:

change_column_null :candidate_branches, :name, true
Martin M
  • 8,430
  • 2
  • 35
  • 53