Ruby on Rails has_one Model Not Supplying ID Column - mysql

I have a legacy rails (version 1.2.3) app which runs without issue on a number of servers (not to mention my local environment). Deployed to its newest server, though, and I now get ActiveRecord::StatementInvalid: Mysql::Error: #23000Column 'video_id' cannot be null errors.
Below are the models/relationships, simplified:
class Video < ActiveRecord::Base
has_one(:user, :dependent => :destroy)
end
class User < ActiveRecord::Base
belongs_to(:video)
end
And below is a rails console transcript of the relationships failing:
>> video = Video.create(:title => 'New Video')
=> #<Video:0xb6d5e31c>...
>> video.id
=> 5
>> video.user = User.create(:name => 'Tester')
ActiveRecord::StatementInvalid: Mysql::Error: #23000Column 'video_id' cannot be null: INSERT INTO users (`name`, `video_id`) VALUES('Tester', NULL)
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract_adapter.rb:128:in `log'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/mysql_adapter.rb:243:in `execute'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/mysql_adapter.rb:253:in `insert'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1811:in `create_without_callbacks'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/callbacks.rb:254:in `create_without_timestamps'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/timestamp.rb:39:in `create'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1789:in `create_or_update_without_callbacks'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/callbacks.rb:242:in `create_or_update'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1545:in `save_without_validation'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/validations.rb:752:in `save_without_transactions'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/transactions.rb:129:in `save'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/connection_adapters/abstract/database_statements.rb:59:in `transaction'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/transactions.rb:95:in `transaction'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/transactions.rb:121:in `transaction'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/transactions.rb:129:in `save'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:451:in `create'
from (irb):3
from :0
Has anyone else come across ActiveRecord not sending an ID when it clearly knows it?

The correct syntax is
video.user.create(:name => 'Tester')
as you have it, it is trying to create the User before assigning it to video.user, per ruby order of evaluation.

Well, I've migrated this particular portion of this well-aged app to rails 2.3.5 and the following now does the trick:
video.create_user(:name => 'Tester')
Thanks for the input so far, but if anyone has any idea why the 1.2.3 version of the code works on every server it has met until today (older ActiveRecord disagreeing with a certain version MySQL in some obscure way, maybe?) I'd love to hear it.

Related

Running Stored procedure giving error can't return a result set in the given context

I know this problem has been asked many times. But I tried the solutions and they didn't work for me. I have a web application built on rails 3.2.12 and ruby 1.9.2p180. I have a stored procedure in it which returns me data of a query having 5 inner joins. Multiple rows approximately 600 are returned in present case. On the local the stored procedure runs fine with no issues. But when I tried it on the server it is throwing:
ActiveRecord::StatementInvalid: Mysql2::Error: PROCEDURE test.sp_procedure can't return a result set in the given context: call sp_procedure('2015-02-14 00:00:00 -0500', '2015-03-03 23:59:00 -0500', 5, '13')
I have searched for this issue and found that I need to set CLIENT_MULTI_RESULTS flag when establishing connection to MySQL server. For this I have done monkey patching as said. Here is the file in initializers:
module ActiveRecord
class Base
def self.mysql2_connection(config)
config[:username] = 'deploy' if config[:username].nil?
if Mysql2::Client.const_defined? :FOUND_ROWS
config[:flags] = config[:flags] ? config[:flags] | Mysql2::Client::FOUND_ROWS : Mysql2::Client::FOUND_ROWS
end
client = Mysql2::Client.new(config.symbolize_keys)
options = [config[:host], config[:username], config[:password], config[:database], config[:port], config[:socket], 0]
ConnectionAdapters::Mysql2Adapter.new(client, logger, options, config)
end
def self.select_sp(sql, name = nil)
connection = ActiveRecord::Base.connection
begin
connection.select_all(sql, name)
rescue NoMethodError
ensure
connection.reconnect! unless connection.active?
end
end
end
end
In my database.yml I have added: flags: <%= 65536 | 131072 %> and also tried with flags: 131072. But it didn't work.
However using the following works:
client = Mysql2::Client.new(:host => "localhost", :username => "root", :flags => Mysql2::Client::MULTI_STATEMENTS )
result = client.query( 'CALL sp_procedure('2015-02-14 00:00:00 -0500', '2015-03-03 23:59:00 -0500', 5, '13')')
This worked on the server too. But each time the stored procedure will run it will create a new connection which I don't want.
And also one thing to note while I am doing this on local as soon as I call the stored procedure I have to execute this:
ActiveRecord::Base.connection.reconnect!
If I don't write this it throws an error:
ActiveRecord::StatementInvalid: Mysql2::Error: Commands out of sync; you can't run this command now
So this is also the same thing means it creates a new connection each time. So I am finding for a solution which saves me from doing this.
And if the monkey patching is correct then what am I missing. Please help.

RoR - rake rs:index fails with NameError on Rails 4.0.4(4.1.7), thinking sphinx 3.1.1

I tried to index my mysql database for sphinx search engine and that's what I get. I went through the whole entire stackoverflow, downgraded my rails, updated sphinx and ts like 5 or 6 times. I double checked my code(maybe problem's over there). I depreciated config.threadsafe! and whatever else and it still doesn't work at all. Probably you could help me out. Here are console logs and parts of the original code:
pchudinov:xxx chud$ rake ts:index
/Library/Ruby/Gems/2.0.0/gems/bundler-1.7.4/lib/bundler/runtime.rb:222: warning: Insecure world writable dir /usr/local in PATH, mode 040777
DEPRECATION WARNING: config.threadsafe! is deprecated. Rails applications behave by default as thread safe in production as long as config.cache_classes and config.eager_load are set to true. (called from <class:Application> at /xxx/config/application.rb:29)
searchd is not currently running.
Stopped searchd daemon (pid: ).
Generating configuration to /xxx/config/development.sphinx.conf
rake aborted!
NameError: uninitialized constant RealTeams
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/inflector/methods.rb:226:in `const_get'
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/inflector/methods.rb:226:in `block in constantize'
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/inflector/methods.rb:224:in `each'
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/inflector/methods.rb:224:in `inject'
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/inflector/methods.rb:224:in `constantize'
/Library/Ruby/Gems/2.0.0/gems/activesupport-4.0.2/lib/active_support/core_ext/string/inflections.rb:66:in `constantize'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/core/index.rb:43:in `model'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/index.rb:9:in `append_source'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/interpreter.rb:63:in `__source'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/interpreter.rb:20:in `indexes'
/xxx/app/indices/real_teams_index.rb:2:in `block in <top (required)>'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/core/interpreter.rb:3:in `translate!'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/core/index.rb:39:in `interpret_definition!'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/active_record/index.rb:32:in `sources'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration/consistent_ids.rb:31:in `collect'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration/consistent_ids.rb:31:in `sources'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration/consistent_ids.rb:19:in `attributes'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration/consistent_ids.rb:23:in `sphinx_internal_ids'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration/consistent_ids.rb:7:in `reconcile'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration.rb:87:in `render'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration.rb:96:in `block in render_to_file'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration.rb:96:in `open'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/configuration.rb:96:in `render_to_file'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/rake_interface.rb:13:in `configure'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/rake_interface.rb:24:in `index'
/Library/Ruby/Gems/2.0.0/gems/thinking-sphinx-3.1.1/lib/thinking_sphinx/tasks.rb:9:in `block (2 levels) in <top (required)>'
Tasks: TOP => ts:index
(See full trace by running task with --trace)
Here is the original code for "RealTeam":
controller:
def search
#real_teams = RealTeam.search params[:search]
end
model:
class RealTeam < ActiveRecord::Base
has_many :players
has_many :home_matches, :class_name => 'Match', :foreign_key => 'team_home_id'
has_many :away_matches, :class_name => 'Match', :foreign_key => 'team_away_id'
has_many :performances
end
index:
ThinkingSphinx::Index.define :real_teams, :with => :active_record do
indexes :name
end
P.S. I am not that common with rails yet, but as far as I think code's done properly.
Your index definition should refer to :real_team (singular, like the model name) instead of :real_teams.

Retrieving multiple datasets using the Sequel gem

I'm using the Sequel gem in the most basic manner possible - connecting to a local database and extracting the results.
The one catch is that my code relies on me being able to execute multiple query statements at once (splitting them up is not an option).
I am
using the mysql2 adapter
using the MULTIPLE_STATEMENTS flag to execute multiple statements
Below is my script.
require 'sequel'
conn = Sequel.connect(:adapter => 'mysql2', :database=>'my_test_db', :user => 'some_user', :password => 'xxxx', :host => 'localhost', :flags => ::Mysql2::Client::MULTI_STATEMENTS)
# res will be a Sequel::Mysql2::Dataset object
res = conn["select * from table_1; select * from table_2;"]
I can easily enough get the results of the first query (selecting from table_1) by simply doing
res.all OR res.each{ |r| puts r }
My problem is, how do I get the next set of results (selecting from table_2) ? Is there some way to store/cache the existing result and move on to the next dataset?
Attempting to do run res.all again results in an error
Sequel::DatabaseDisconnectError: Mysql2::Error: Commands out of sync; you can't run this command now
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/adapters/mysql2.rb:77:in `query'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/adapters/mysql2.rb:77:in `block in _execute'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/database/logging.rb:33:in `log_yield'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/adapters/mysql2.rb:77:in `_execute'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/adapters/shared/mysql_prepared_statements.rb:34:in `block in execute'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/database/connecting.rb:229:in `block in synchronize'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/connection_pool/threaded.rb:104:in `hold'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/database/connecting.rb:229:in `synchronize'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/adapters/shared/mysql_prepared_statements.rb:34:in `execute'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/dataset/actions.rb:795:in `execute'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/adapters/mysql2.rb:181:in `execute'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/adapters/mysql2.rb:152:in `fetch_rows'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/dataset/actions.rb:143:in `each'
from /Users/lefthandpisces/.rvm/gems/ruby-1.9.3-p448/gems/sequel-4.6.0/lib/sequel/dataset/actions.rb:46:in `all'
from (irb):14
from /Users/lefthandpisces/.rvm/rubies/ruby-1.9.3-p448/bin/irb:12:in `<main>'
Thanks!
You can't do this with the mysql2 adapter. I believe the mysql adapter supports it, but even then it's a bad idea. Use separate datasets or a single dataset with a UNION.

Rails 3.1 broke sorting for MySql::Time

I just upgrading from Rails 3 to 3.1, and am getting this error:
NoMethodError (undefined method `<=>' for #<Mysql::Time:2011-01-12 00:00:00>):
on this line:
payments = Payment.all( :select => 'date(created_at) as day, amount', :order => 'created_at',
:conditions => ["status = ?"], 1)
payments.group_by(&:day).sort
Any ideas how to fix?
You could try to explicitly cast the rows to ruby Time objects:
payments.group_by(&:day).sort{ |x,y| Time.parse(x) <=> Time.parse(y) }
Fixed it. I switched to the mysql2 gem (https://github.com/brianmario/mysql2), and that resolved the issue while keeping performance.

JRuby 1.6.3 and Rails 3.1rc5 and activerecord-3.1.0.rc5 and destroy_all

I am able to create able to run my migrations from JRuby 1.6.3 and Rails 3.1rc5 and in a console session create a simple Role object like this:
jruby-1.6.3 :001 > role = Role.new(:name => "Admin")
(1.0ms) SELECT name
FROM sqlite_master
WHERE type = 'table' AND NOT name = 'sqlite_sequence'
=> #<Role id: nil, name: "Admin", created_at: nil, updated_at: nil>
All is good but when I run
Role.destroy_all
I get the following stack trace:
jruby-1.6.3 :003 > Role.destroy_all
ArgumentError: wrong number of arguments (3 for 2)
from /Users/paulcowan/.rvm/gems/jruby-1.6.3/gems/activerecord-3.1.0.rc5/lib/active_record/base.rb:470:in `find_by_sql'
from /Users/paulcowan/.rvm/gems/jruby-1.6.3/gems/activerecord-3.1.0.rc5/lib/active_record/relation.rb:111:in `to_a'
from /Users/paulcowan/.rvm/gems/jruby-1.6.3/gems/activerecord-3.1.0.rc5/lib/active_record/relation.rb:289:in `destroy_all'
from org/jruby/RubyBasicObject.java:1684:in `__send__'
from /Users/paulcowan/.rvm/gems/jruby-1.6.3/gems/activerecord-3.1.0.rc5/lib/active_record/base.rb:438:in `destroy_all'
from (irb):3:in `evaluate'
from org/jruby/RubyKernel.java:1093:in `eval'
from org/jruby/RubyKernel.java:1419:in `loop'
from org/jruby/RubyKernel.java:1205:in `catch'
from org/jruby/RubyKernel.java:1205:in `catch'
from /Users/paulcowan/.rvm/gems/jruby-1.6.3/gems/railties-3.1.0.rc5/lib/rails/commands/console.rb:45:in `start'
from /Users/paulcowan/.rvm/gems/jruby-1.6.3/gems/railties-3.1.0.rc5/lib/rails/commands/console.rb:8:in `start'
from /Users/paulcowan/.rvm/gems/jruby-1.6.3/gems/railties-3.1.0.rc5/lib/rails/commands.rb:40:in `(root)'
from org/jruby/RubyKernel.java:1047:in `require'
from script/rails:6:in `(root)'
It would seem all is not right between activerecord-3.1.0.rc5 and jruby.
Anybody any help on this?
There has been some progress on the activerecord-jdbc-adapter front and you can now get your setup working now by using the master branch of activerecord-jdbc-adapter. Just add the following to your Gemfile:
gem 'activerecord-jdbc-adapter', :git => 'https://github.com/nicksieger/activerecord-jdbc-adapter.git
I'd only recommend doing this if you cannot wait for the final activerecord-jdbc-adapter gem and certainly not in production.
You are correct. All is not right yet with activerecord-jdbc-adapter and Rails 3.1. I'm working on it and hope to have it ready by the time Rails 3.1 goes final.
Don't you have to specify conditions for it destroy_all?
e.g.
http://apidock.com/rails/ActiveRecord/Base/destroy_all/class