Skip to content
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

Rails 4.2 Can't save data ActiveRecord::StatementInvalid: Mysql2::Error: Field 'name' doesn't have a default value #429

Closed
Nike0 opened this issue Mar 16, 2015 · 22 comments

Comments

@Nike0
Copy link

Nike0 commented Mar 16, 2015

Hi,

I have a trouble when upgrading my app from Rails 3.2.21 to 4.2.0. I can't save data in models with translates option. Here is the model example:

class Benefit < ActiveRecord::Base
  translates :name, fallbacks_for_empty_translations: true, versioning: :paper_trail
  validates_presence_of :name

  # other code
end

And Gemfile (necessary gems only):

gem 'rails', '~> 4.2.0'
gem 'paperclip', '~> 4.1.0'
gem 'globalize', '~> 5.0.0'
gem 'globalize-versioning', '~> 0.1.0'
gem 'paperclip-globalize3', '~> 2.2.0' 
gem 'paper_trail', '~> 3.0.0'

Then I've tried to create a record:

benefit = Benefit.new
benefit.name = 'test_name'
benefit.display_order = 1
benefit.save!

I saw next SQL query in the log:

INSERT INTO `benefits` (`display_order`) VALUES (1)

Then I created a new empty Rails 4.2 project. Here is all code:

class TestModel < ActiveRecord::Base
  translates :name, fallbacks_for_empty_translations: true, versioning: :paper_trail

  validates_presence_of :name
end

Migrations:

class CreateTestModels < ActiveRecord::Migration
  def change
    create_table :test_models do |t|
      t.string :name, limit: 60, null: false
      t.integer :display_order, null: true
      t.timestamps null: false
    end
  end
end

class CreateTestModelTranslation < ActiveRecord::Migration
  def up
    TestModel.create_translation_table!
  end

  def down
    TestModel.drop_translation_table!
  end
end

Gemfile:

source 'https://rubygems.org'

gem 'rails', '4.2.0'
gem 'mysql2'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.1.0'

gem 'globalize', '~> 5.0.0'
gem 'globalize-versioning', '~> 0.1.0'
gem 'paperclip', '~> 4.1.0'
gem 'paperclip-globalize3', '~> 2.2.0'
gem 'paper_trail'

gem 'jquery-rails'
gem 'turbolinks'
gem 'jbuilder', '~> 2.0'
gem 'sdoc', '~> 0.4.0', group: :doc

group :development, :test do
  gem 'byebug'
  gem 'web-console', '~> 2.0'
  gem 'spring'
end

Attempt to create a record with backtrace:

nike0@nike0-work:~/Work/rails_42_test$ rails console
Loading development environment (Rails 4.2.0)
2.1.2 :001 > record = TestModel.new
 => #<TestModel id: nil, name: nil, display_order: nil, created_at: nil, updated_at: nil> 
2.1.2 :002 > record.name = 'test_name'
 => "test_name" 
2.1.2 :003 > record.display_order = 1
 => 1 
2.1.2 :004 > record.save!
   (0.2ms)  BEGIN
  SQL (1.5ms)  INSERT INTO `test_models` (`display_order`, `created_at`, `updated_at`) VALUES (1, '2015-03-16 13:58:24.727233', '2015-03-16 13:58:24.727233')
Mysql2::Error: Field 'name' doesn't have a default value: INSERT INTO `test_models` (`display_order`, `created_at`, `updated_at`) VALUES (1, '2015-03-16 13:58:24.727233', '2015-03-16 13:58:24.727233')
   (0.1ms)  ROLLBACK
ActiveRecord::StatementInvalid: Mysql2::Error: Field 'name' doesn't have a default value: INSERT INTO `test_models` (`display_order`, `created_at`, `updated_at`) VALUES (1, '2015-03-16 13:58:24.727233', '2015-03-16 13:58:24.727233')
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:299:in `query'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:299:in `block in execute'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:466:in `block in log'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:460:in `log'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract_mysql_adapter.rb:299:in `execute'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/mysql2_adapter.rb:231:in `execute'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/mysql2_adapter.rb:248:in `exec_insert'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/database_statements.rb:108:in `insert'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/connection_adapters/abstract/query_cache.rb:14:in `insert'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/relation.rb:64:in `insert'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/globalize-5.0.1/lib/patches/active_record/persistence.rb:19:in `_create_record'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/counter_cache.rb:139:in `_create_record'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/attribute_methods/dirty.rb:127:in `_create_record'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activerecord-4.2.0/lib/active_record/callbacks.rb:306:in `block in _create_record'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/callbacks.rb:117:in `call'
... 31 levels...
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/railties-4.2.0/lib/rails/commands/console.rb:9:in `start'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:68:in `console'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/railties-4.2.0/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/railties-4.2.0/lib/rails/commands.rb:17:in `<top (required)>'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `block in require'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274:in `require'
        from /home/nike0/Work/rails_42_test/bin/rails:8:in `<top (required)>'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:240:in `load_dependency'
        from /home/nike0/.rvm/gems/ruby-2.1.2/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
        from /home/nike0/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from /home/nike0/.rvm/rubies/ruby-2.1.2/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
        from -e:1:in `<main>'

Also I tried to use 4.x version of globalize and saw error like here.

Thank you.

@coorasse
Copy link

This error doesn't allow me to upgrade to Rails 4.2. Tried with globalize 5.0.0 and 4.0.3 same problem

@Nike0
Copy link
Author

Nike0 commented Apr 20, 2015

I don't know why, but in lib/patches/active_record/persistence.rb:16 selected non-translation fields only. This operation causes an error as above.

@Nike0
Copy link
Author

Nike0 commented Apr 21, 2015

I apologize for the mistake. Even without this rejection record is not saved and the value is lost in the depths of activerecord and activesupport gems.

@xsrgx
Copy link

xsrgx commented May 11, 2015

Is anybody live there?

@simi
Copy link
Member

simi commented May 11, 2015

sure @xsrgx
Is there any chance to provide minimal repro script based on https://github.com/globalize/globalize/blob/issue-template/issue_template.rb for example?

@Nike0
Copy link
Author

Nike0 commented May 12, 2015

Yes, ofc.
I'm just waited creators for answer. I couldn't resolve problem by myself.

@nagi
Copy link

nagi commented Jun 24, 2015

@simi Here is a minimal repro script which passes with gem 'activerecord', '4.1.8' and gem 'globalize', '4.0.3' ; the only addition is on line 19: https://gist.github.com/nagi/7ee7aa1c9e0030ee7fa6

scarfacedeb pushed a commit to scarfacedeb/rails_admin_globalize_field that referenced this issue Jun 28, 2015
Due to globalize/globalize#429

Dependencies will be locked until that issue is resolved.
@trentclowater
Copy link

I just ran into this issue today. Found that if a translated column has null: false with no default, it exhibits the problem. If the column has null: true (or nothing, which defaults to null: true), or the column has null: false, default: "" then it works fine. So for example:

This works:

t.string :name

And this works:

t.string :name, null: false, default: ""

But this gives the error:

t.string :name, null: false 

To work around this for now I just added the default: "" and also added a validate :name, presence: true to the model, but having a default of an empty string goes against the point of having null: false in the first place (and may cause problems if the database is accessed outside this particular rails application, which this one could be in the future).

@parndt
Copy link
Member

parndt commented Aug 5, 2015

Official advice is to remove the column from your source table completely as it no longer makes sense to have it there.

@nethsix
Copy link

nethsix commented Sep 20, 2015

@parndt I am having exactly the same issue that @Nike0 has after upgrading from (rails 4.1.7, activerecord 4.1.7, globalize 4.0.3) to (rails 4.2.4, activerecord 4.2.4, globalize-5.0.1). I did some tracing with byebug and the code in line 17-19 of globalize/lib/patches/active_record/persistence.rb (https://github.com/globalize/globalize/blob/master/lib/patches/active_record/persistence.rb):

attributes_values = arel_attributes_with_values_for_create(attribute_names_without_translated)

new_id = self.class.unscoped.insert attributes_values

seems to filter out attributes that are 'translated' (i.e., the :name field in @Nike0 and my cases) before passing them into the insert statement, thus it results in the error 'Field 'name' doesn't have a default value'.

I am willing to spend more time to debug/trace this, please help guide me. Thank you.

Also when you mention that the official advice is to remove the column, are you referring to :name column? If so please kindly help me understand why; the :name column in this case belongs to the table, e.g., Product#name, or is :name a reserved keyword for globalize?

Thanks!

@nethsix
Copy link

nethsix commented Sep 21, 2015

After byebug-ing around, and re-reading the docs, I understand what @parndt meant when he said 'the official advice is to remove the column'. In globalize ~> 5.0.0, the original table must NOT have columns, e.g., in my case, the Property table has a :name column, which are to be translated since those columns should exist only in the translated table. Previously in globalize ~> 4.0.0, the columns to be translated exists in both the original table and the translated table.

@shioyama
Copy link
Contributor

shioyama commented Oct 1, 2016

Closing this, as noted Globalize does not support having the same column on both the model table and its translation table. We may look into handling this more gracefully, but it is not the expected situation and is thus not supported in general.

@shioyama shioyama closed this as completed Oct 1, 2016
@kapilsdv
Copy link

Hi,
I'm encountering the same issue and can't follow the official advice to delete the source column because I have Foreign Key constraints to the translates column.
Please help/suggest a way other than deleting the column
Thanks

@shioyama
Copy link
Contributor

@kapilsdv Sorry, really nothing we can do. We're not going to chase after AR changes which conflict with this configuration since it's inherently problematic. If you upgrade to Rails/AR 5 you should be okay since we use ignored_columns which allows us to cleanly ignore the column on the model table, but this is not available in Rails 4.

@kapilsdv
Copy link

Thanks for quick reply.
Actually I'm using Rails 5 (should have told before) so where should i use this ignored_columns.

@shioyama
Copy link
Contributor

Globalize will use ignored_columns automatically if it detects configuration with a translated column on the model table. Are you using the latest commit on master? If so you should see a deprecation warning, but no actual issues.

@sachin87
Copy link

@shioyama i have set self.ignored_columns = [] in my model but still i am getting the same issue, please help.

@shioyama
Copy link
Contributor

@sachin87 you don't need to set ignored_columns anywhere, it is set by default. Are you using the latest release on master?

@shioyama
Copy link
Contributor

@sachin87 Also, do not set ignored_columns = [] because this will undo what we are trying to fix.

@sachin87
Copy link

@shioyama what should i do then, i have set null: false option to a column at database end which is a sort of primary key, i can't set it to null in any way, what should be the value of ignored_columns so that its value should be set always.

@shioyama
Copy link
Contributor

@sachin87 Do you see the deprecation error? Are you using Rails 5?

If you are using Rails 5 and see the deprecation error, but you need something in the column on every record to satisfy a null: false constraint, well then I don't really know but at that point it's not a Globalize issue. Maybe you could just rename the column on your model table?

@sachin87
Copy link

@shioyama I have added a foreign key constraint on that column, and i already have a lot of data, i can't remove this column.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests