sql-serverjdbcjrubyruby-on-rails-4.2jrubyonrails

Getting NoMethodError when using jdbc sqlserver adapter with jRuby on Rails


I have a jRuby on Rails application hosted on IIS 8 on Windows Server 2012 R2 (I know, I must be insane). After about 2 weeks of painful programming I have a working application but I'm trying to configure it to use SQL Server 2012 Express via the Microsoft JDBC SQL Server driver instead of the default sqlite3 database. So far, this is not going well.

After configuring my database.yml file I tried to run:
bundle exec rake db:migrate RAILS_ENV=production --trace
I am met with the error
rake aborted! NoMethodError: undefined method 'type' for "nvarchar(255)":String

A full trace of my error can be seen below:

rake db:migrate

C:\inetpub\wwwroot\rails>bundle exec rake db:migrate RAILS_ENV=production --trac
e
io/console not supported; tty will not be manipulated
io/console not supported; tty will not be manipulated
NOTE: ActiveRecord 4.2 is not (yet) fully supported by AR-JDBC, please help us f
inish 4.2 support - check http://bit.ly/jruby-42 for starters
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Invoke db:load_config (first_time)
** Execute db:load_config
** Execute db:migrate
rake aborted!
NoMethodError: undefined method `type' for "nvarchar(255)":String
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttribute_methods/time_zone_conversion.rb:64:in `create_time_zone_conversion_attr
ibute?'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttribute_methods/time_zone_conversion.rb:53:in `inherited'
org/jruby/RubyProc.java:271:in `call'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttribute_decorators.rb:61:in `matching'
org/jruby/RubyArray.java:2470:in `select'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttribute_decorators.rb:60:in `matching'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttribute_decorators.rb:56:in `decorators_for'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttribute_decorators.rb:47:in `apply'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttribute_decorators.rb:29:in `add_user_provided_columns'
org/jruby/RubyArray.java:2414:in `map'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttribute_decorators.rb:28:in `add_user_provided_columns'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttributes.rb:93:in `columns'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/a
ttributes.rb:98:in `columns_hash'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/q
uerying.rb:41:in `find_by_sql'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/r
elation.rb:638:in `exec_queries'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/r
elation.rb:514:in `load'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/r
elation.rb:243:in `to_a'
C:0:in `map'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/m
igration.rb:844:in `get_all_versions'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/m
igration.rb:985:in `migrated'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/m
igration.rb:990:in `ran?'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/m
igration.rb:967:in `runnable'
org/jruby/RubyArray.java:2640:in `reject!'
org/jruby/RubyArray.java:2611:in `reject'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/m
igration.rb:967:in `runnable'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/m
igration.rb:952:in `migrate'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/m
igration.rb:820:in `up'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/m
igration.rb:798:in `migrate'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/t
asks/database_tasks.rb:137:in `migrate'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/activerecord-4.2.2/lib/active_record/r
ailties/databases.rake:44:in `(root)'
org/jruby/RubyProc.java:271:in `call'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/task.rb:240:in `e
xecute'
org/jruby/RubyArray.java:1613:in `each'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/task.rb:235:in `e
xecute'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/task.rb:179:in `i
nvoke_with_call_chain'
C:/jruby-1.7.22/lib/ruby/1.9/monitor.rb:211:in `mon_synchronize'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/task.rb:172:in `i
nvoke_with_call_chain'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/task.rb:165:in `i
nvoke'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/application.rb:15
0:in `invoke_task'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/application.rb:10
6:in `top_level'
org/jruby/RubyArray.java:1613:in `each'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/application.rb:10
6:in `top_level'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/application.rb:11
5:in `run_with_threads'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/application.rb:10
0:in `top_level'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/application.rb:78
:in `run'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/application.rb:17
6:in `standard_exception_handling'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/lib/rake/application.rb:75
:in `run'
C:/jruby-1.7.22/lib/ruby/gems/shared/gems/rake-10.4.2/bin/rake:33:in `(root)'
org/jruby/RubyKernel.java:1059:in `load'
C:\jruby-1.7.22\bin\rake:23:in `(root)'

Tasks: TOP => db:migrate

database.yml

# SQLite version 3.x
#   gem install sqlite3
#
#   Ensure the SQLite 3 gem is defined in your Gemfile
#   gem 'sqlite3'
#
default: &default
  adapter: sqlite3
  pool: 5
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: db/test.sqlite3

production:
  adapter: sqlserver
  database: smdb
  url: jdbc:sqlserver://localhost;instanceName=SQLEXPRESS;databaseName=smdb;user=sa;password=password123;

Gemfile

source 'https://rubygems.org'

ruby '1.9.3', :engine => 'jruby', :engine_version => '1.7.22'

gem 'rails',                                '4.2.2'
gem 'bootstrap-sass',                       '3.2.0.0'
gem 'sass-rails',                           '5.0.2'
gem 'uglifier',                             '2.5.3'
gem 'coffee-rails',                         '4.1.0'
gem 'coffee-script-source',                 '1.8.0'
gem 'jquery-rails',                         '4.0.3'
gem 'turbolinks',                           '2.3.0'
gem 'jbuilder',                             '2.2.3'
gem 'faker',                                '1.4.2'
gem 'tzinfo-data',                          '1.2015.6'
gem 'sdoc',                                 '0.4.0', group: :doc

group :development, :test do
  gem 'activerecord-jdbcsqlite3-adapter',   '1.3.17'
  gem 'spring',                             '1.1.3'
end

group :test do
  gem 'minitest-reporters',                 '1.0.5'
  gem 'mini_backtrace',                     '0.1.3'
  gem 'guard-minitest',                     '2.3.1'
end

group :production do
  gem 'trinidad',                           '1.4.6'
  gem 'deprecated',                         '3.0.1'
  gem 'activerecord-jdbcmssql-adapter',     '1.3.17'
end 

And finally my two Database Migration files:

20150805101650_create_servers.rb

class CreateServers < ActiveRecord::Migration
  def change
    create_table :servers do |t|
      t.string :server_name
      t.string :application
      t.string :server_role
      t.string :team_contact
      t.string :individual_contact
      t.string :business_owner
      t.string :vendor
      t.string :vendor_contact
      t.string :main_doc
      t.string :main_win

      t.timestamps null: false
    end
  end
end

20150805105953_add_index_to_server_name.rb

class AddIndexToServerName < ActiveRecord::Migration
  def change
    add_index :servers, :server_name, unique: true
  end
end

I know that the instance is being hit as I was previously met with an authentication error which has gone since I added the username and password to the jdbc connection string

Solution

Downgraded to Rails 4.1.0 which seems to be more compatible with JDBC Adapter. Ran a rake db:migrate RAILS_ENV=production which resulted in another error. The error was resolved by removing config.active_record.raised_in_transactional_callbacks = true from application.rb


Solution

  • AR-JDBC does not handle Rails 4.2 esp. with databases such as MS-SQL, there's the warning :

    NOTE: ActiveRecord 4.2 is not (yet) fully supported by AR-JDBC, please help us finish 4.2 support - check http://bit.ly/jruby-42 for starters

    ... SQLServer support needs your help/support!