Why is my simple Ruby SQLite3 example failing? - ruby

In my attempt to learn Ruby, I've been reading Mr. Neighborly's Humble Little Ruby Book.
Most examples have been very easy to follow giving me a good introduction to Ruby, however I can't run DB related examples easily.
I'm trying to run this code: (slightly modified from the example given in the book)
#!/usr/bin/ruby
require 'rubygems'
require 'dbi'
DBI.connect('DBI:SQLite3:testdb', 'ruby', 'ruby') do | dbh |
dbh.do('CREATE TABLE slugs(name varchar(20), age int);') rescue puts "TABLE slugs already exists."
sql = "INSERT INTO slugs (name, age) VALUES (?, ?)"
dbh.prepare(sql) do |st|
1.upto(20) do |i|
st.execute("slug #{i}", "#{i}")
end
end
end
When run, it inserts one row in the database, then it gives me the following error:
/var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:41:in `bind_param': library routine called out of sequence (SQLite3::MisuseException)
from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:41:in `bind_params'
from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:37:in `each'
from /var/lib/gems/1.8/gems/sqlite3-ruby-1.3.2/lib/sqlite3/statement.rb:37:in `bind_params'
from /var/lib/gems/1.8/gems/dbd-sqlite3-1.2.5/lib/dbd/sqlite3/statement.rb:71:in `bind_params'
from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/statement.rb:115:in `execute'
from /media/dev/ruby-prax/moi.rb:12
from /media/dev/ruby-prax/moi.rb:11:in `upto'
from /media/dev/ruby-prax/moi.rb:11
from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/database.rb:61:in `prepare'
from /media/dev/ruby-prax/moi.rb:10
from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi/handles/driver.rb:41:in `connect'
from /var/lib/gems/1.8/gems/dbi-0.4.5/lib/dbi.rb:148:in `connect'
from /media/dev/ruby-prax/moi.rb:5
TABLE slugs already exists.
I am on Ubuntu 10.04 at the moment.
Version info:
tlee#tim-ubuntu:/media/dev/ruby-prax$ ruby -v
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
tlee#tim-ubuntu:/media/dev/ruby-prax$ gem list
*** LOCAL GEMS ***
abstract (1.0.0)
daemons (1.1.0)
dbd-mysql (0.4.4)
dbd-odbc (0.2.5)
dbd-sqlite3 (1.2.5)
dbi (0.4.5)
deprecated (3.0.0, 2.0.1)
erubis (2.6.6)
eventmachine (0.12.10)
extlib (0.9.15)
json_pure (1.4.6)
mysql (2.8.1)
rack (1.2.1)
sqlite3-ruby (1.3.2)
thin (1.2.7)
thor (0.14.1)
tlee#tim-ubuntu:/media/dev/ruby-prax$ sqlite3 --version
3.6.22
tlee#tim-ubuntu:/media/dev/ruby-prax$
What am I doing wrong?

I experienced the same problem. There is an issue on github about the SQLite driver for DBD failing when you use a prepared INSERT statement more than once. Personally, I've taken the recommendation in the answer there of moving to RDBI, since Ruby/DBI is apparently no longer being maintained. Moving to RDBI required very minimal code changes.

Your table definition is:
slugs(name varchar(20), age int);
but you are trying to insert:
st.execute("slug #{i}", "#{i}")
Note that "#{i}" is not an integer, it's a string. Change it to i, as in this example:
st.execute("slug #{i}", i)
Then see what happens.

I somehow think that several of sqlite3 libraries on Ruby are missing reset and clear methods for the statement class.
When same SQL statement is executed repeatedly, a statement is prepared once and executed with a fresh set of values. But after the statement is executed and before it is re-bound, it needs to be reset (and often cleared). The point is that it is faster to reset a used statement than "compiling and optimizing" the same SQL over and over again. Most of you probably know all this... but here's the link to the SQLite documentation of the relevant part:
https://www.sqlite.org/c3ref/stmt.html
I don't see reset and clear methods in SQLite3::Statement class, so these might be somehow missed from this implementation, or there is some other mechanism to reset/clear automatically when reused, but that mechanism is somehow not triggered. However, it is not even mentioned in the documentation... at least I couldn't find it.
I think clear_bindings and reset methods are missing from SQLite3::Statement class.
https://github.com/sparklemotion/sqlite3-ruby/issues/158

Related

Shotgun doesn't start after updating to Ruby 3.0.1

I'm trying to start Shotgun for a Sinatra app after having upgraded to Ruby 3.0.1, and get this:
$ shotgun
== Shotgun/Thin on http://127.0.0.1:9393/
/Users/me/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/rack-2.2.3/lib/rack/handler/thin.rb:11:in `run': wrong number of arguments (given 2, expected 1) (ArgumentError)
from /Users/me/.rbenv/versions/3.0.1/lib/ruby/gems/3.0.0/gems/shotgun-0.9.2/bin/shotgun:156:in `<top (required)>'
from /Users/me/.rbenv/versions/3.0.1/bin/shotgun:23:in `load'
from /Users/me/.rbenv/versions/3.0.1/bin/shotgun:23:in `<main>'
Running gem list, I get:
shotgun (0.9.2)
What's going on? Thanks!
Ruby v3.0 introduces a breaking change, relating to keyword vs positional arguments.
The shotgun gem hasn't been updated for a long time; the latest version (0.9.2) was released in September 2016.
Looking at the gem in github, I see there's an open issue about this exact problem you've raised, and someone has already - helpfully - forked the project with a fix.
Unless the original author merges this fix and releases a new version of the gem, you'll need to use a forked version such as the above. For example, update your Gemfile to say:
gem 'shotgun', git: 'https://github.com/delonnewman/shotgun.git'
And then run bundle install.
There's also this open PR with the exact same fix, so you could equally use that fork instead.
... Or alternatively, stick to ruby 2.7 for now.

Padrino Project Generator Fails - Undefined Method `add_builtin_type'

I'm new to both Ruby and Sinatra/Padrino so I apologize if I'm missing something really simple.
I have Sinatra working fine, as I can build a very simple "hello" app and see it work.
I wanted to move on and generate a new Padrino project, but when I do this:
$ padrino g project foobar
I get this:
/Users/dave/.rvm/gems/ruby-2.1.5/gems/activesupport-4.2.0/lib/active_support/ordered_hash.rb:3:in `<top (required)>': undefined method `add_builtin_type' for Psych:Module (NoMethodError)
from /Users/dave/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:121:in `require'
from /Users/dave/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:121:in `require'
from /Users/dave/.rvm/gems/ruby-2.1.5/gems/padrino-gen-0.12.4/lib/padrino-gen.rb:3:in `<top (required)>'
from /Users/dave/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /Users/dave/.rvm/rubies/ruby-2.1.5/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
from /Users/dave/.rvm/gems/ruby-2.1.5/gems/padrino-gen-0.12.4/bin/padrino-gen:12:in `<main>'
I have tried installing the Psych gem but this didn't change anything. I have no idea what to try next, or how to really interpret the error message. Any nudges in the right direction you can give me?
Bug reports show this may be an RVM issue.
I suggest changing from RVM to "ruby-install" and "chruby" because IMHO these are simpler, easier, and better at installing dependencies including psych and its libraries.
As joelparkerhenderson noted, the error message shows problems with gem files in the .rvm directory, suggesting some issue or conflict with rvm. Switching to system ruby solved the problem for me. I don't really need to use a specific version of ruby on this project, so that's a fine workaround for me.
I had this problem while using Ruby 2.1.5. After reading comments on here I realized it's not a RVM problem, but a ruby problem. I switched to 2.0.0-p576 and everything works. Psych must not be compatible with the new ruby versions.
However I don't understand how a different ruby version would cause this method to go missing. If anyone could explain that I would be grateful!
I ran into this using rbenv and padrino 0.13.0. Tried many versions of Ruby, including the system Ruby on OS X El Capitan, but found that that made no difference, so I'm now running the latest stable one (2.2.4).
Eventually I tried each version of the psych gem and found I could only get padrino g to work with an older version of the gem. Psych version 2.0.8 worked, while every newer version (up to the current 2.0.16) failed.
So: gem install psych -v=2.0.8 && gem uninstall psych -v '>= 2.0.9'
With me, after a lot of googling and reading various thread on S.O., it was only my rvm that was the problem. I was getting the rvm 'WARNING!' that rvm wasn't first in $PATH. You can check this with echo $PATH. Check out your ~/.bashrc see if there is anything like heroku toolbelt or linuxbrew, or whatever, loading themselves into your PATH at the FRONT i.e. PRE-PENDING your path, rather than APPENDING. This is indicated by something like export PATH="/usr/local/heroku/bin:$PATH". That sets heroku at the beginning of your PATH. Simply change it to export PATH="$PATH:/usr/local/heroku/bin".
I was trying to start a padrino project with activesupport, and this was causing problems. Changing to an earlier version of Ruby, as suggested in another thread, didn't cut it, because activesupport requires 2.2.0 or up.
Fixing my PATH, ensuring that rvm was initialized at the very beginning of the PATH, fixed my Padrino problem, and was able to initialize a project with the following command:
padrino g project sample_blog -t shoulda -e haml -c sass -s jquery -d activerecord -b
I know that's all a little off-tangent, but I think it's bound to help one or two people out there!
PS I'm using ruby 2.2.2p95 in this project folder.

JRuby and SQLite3

I'm trying to make work JRuby and SQLite3 with the following gems:
bouncy-castle-java (1.5.0146.1)
bundler (1.3.2)
dbd-jdbc (0.1.6 java)
dbi (0.4.5)
deprecated (2.0.1)
jdbc-sqlite3 (3.7.2.1)
jruby-launcher (1.0.15 java)
jruby-openssl (0.8.2)
json (1.7.7 java)
rack (1.5.2)
rack-protection (1.4.0)
rake (10.0.3)
rubygems-bundler (1.1.1)
rvm (1.11.3.6)
sinatra (1.3.5)
sqlite3 (1.3.7)
tilt (1.3.5)
and this code:
require 'java'
require 'dbi'
require 'dbd/Jdbc'
require 'jdbc/sqlite3'
dbh = DBI.connect(
"DBI:jdbc:sqlite:db.sqlite", # connection string
'', # no username for sqlite3
'', # no password for sqlite3
'driver' => 'org.sqlite.JDBC') # need to set the driver
But I have this error:
DBI::InterfaceError: Unable to load driver 'jdbc' (underlying error: wrong constant name jdbc)
load_driver at /home/gl/.rvm/gems/jruby-1.7.3/gems/dbi-0.4.5/lib/dbi.rb:300
mon_synchronize at /home/gl/.rvm/rubies/jruby-1.7.3/lib/ruby/1.9/monitor.rb:211
load_driver at /home/gl/.rvm/gems/jruby-1.7.3/gems/dbi-0.4.5/lib/dbi.rb:242
_get_full_driver at /home/gl/.rvm/gems/jruby-1.7.3/gems/dbi-0.4.5/lib/dbi.rb:160
connect at /home/gl/.rvm/gems/jruby-1.7.3/gems/dbi-0.4.5/lib/dbi.rb:145
(root) at srv.rb:6
Have you got an idea?
I've just been trying to work this out myself, and eventually succeeded - the problem is that the driver name is now 'Jdbc', rather than 'jdbc' - capitalization is important, both in the connection string, and the require statement. If you change your connection string to "DBI:Jdbc:sqlite:db.sqlite" it should work fine.
I suggest you use ActiveRecord rather than DBI.
You can execute bare SQL thus:
ActiveRecord::Base.connection.execute("SELECT * FROM some_table")
The accepted answer does not work (for me at least). I searched SO and the Web for hours (there's a lot of good and bad information out there) and finally came upon a solution that works (for me at least). A large part of the problem is solved by adding the line 'Jdbc::SQLite3.load_driver'.
require 'java'
require 'jdbc/sqlite3'
module JavaSql
include_package 'java.sql'
end
Jdbc::SQLite3.load_driver
Java::org.sqlite.JDBC
conn_str = 'jdbc:sqlite:../Data/AflBettingHistory.db3'
conn = JavaSql::DriverManager.getConnection(conn_str)
stm = conn.createStatement
rs = stm.executeQuery("select Name from Team")
while (rs.next) do
puts rs.getString("Name")
end
rs.close
stm.close
conn.close

Problem with Firewatir requiring different version of activesupport

I have a script that uses Watir to retrieve information from Web pages. It works fine as a standalone script. Now I would like to create a Padrino Rake task based on it, and attempt to run the script results in an error:
can't activate activesupport (= 2.3.9) for "firewatir-1.6.7", already activated activesupport-3.0.3 for "padrino-core-0.9.19"
I understand the reason for the problem: Firwatir demands an older version of activesupport. But can this demand be overruled?
have you tried padrino-core-0.9.15? it uses activesupport 2.3.8
gem install padrino-core -v 0.9.15
that would be the first thing I'd try.
Dave

NoMethodError (set_result) in SQLite3 when running Geocommons Geocoder using irb on Mac OS X 10.5.8

Has anyone here ever encountered the following error after installing and attempting to run the Geocommons geocoder on Mac OS X 10.5.8? This is my exact output from the Terminal window from the point at which I started irb:
$ irb
>> require 'geocoder/us'
=> true
>> db = Geocoder::US::Database.new("/opt/tiger/orangeca.db")
=> #<Geocoder::US::Database:0x57ac10 #threadsafe=false, #db=#<SQLite3::Database:0x57ab98>, #debug=false, #st={}>
>> p db.geocode("Disneyland Anaheim, CA 92802")
NoMethodError: undefined method `set_result' for #<SQLite3::Database::FunctionProxy:0x576778>
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:64:in `tune'
from /Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.3.0/lib/sqlite3/database.rb:316:in `call'
from /Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.3.0/lib/sqlite3/database.rb:316:in `create_function'
from /Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.3.0/lib/sqlite3/resultset.rb:66:in `call'
from /Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.3.0/lib/sqlite3/resultset.rb:66:in `step'
from /Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.3.0/lib/sqlite3/resultset.rb:66:in `next'
from /Library/Ruby/Gems/1.8/gems/sqlite3-ruby-1.3.0/lib/sqlite3/resultset.rb:97:in `each'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:138:in `execute_statement'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:46:in `synchronize'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:46:in `synchronize'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:135:in `execute_statement'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:122:in `execute'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:151:in `places_by_zip'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:339:in `find_candidates'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:654:in `geocode_address'
from /Library/Ruby/Gems/1.8/gems/Geocoder-US-2.0.0/lib/geocoder/us/database.rb:724:in `geocode'
from (irb):3>>
Incidentally, "orangeca.db" is the TIGER/Line data for Orange County, CA - I downloaded only it from the main Census database rather than the entire US dataset because I'm merely testing Geocoder's usefulness for a piece of software I want to write and I didn't want to spend 10 hours downloading several GB of data which I might not end up using in the final product anyway.
My best guesses at explaining this behavior, based on information I found on the SQLite3::Database::FunctionProxy class, are as follows:
My SQLite3 is installed correctly but something is incorrectly configured such that my Geocoder is not finding set_result as desired.
My SQLite3 is incorrectly installed, but I am not sure where I went wrong in setting it up.
If anyone could offer any help with this, I would greatly appreciate it. Thank you in advance for your help!
Try using this version of the Sqlite Ruby Gem: http://github.com/schuyler/sqlite3-ruby
You need to use the 1.2.5 version of the sqlite3-ruby gem.
gem install sqlite3-ruby --version=1.2.5
You can either make sure there is no other gems providing sqlite3 (such as sqllite3 or a newer version of sqllite3-ruby) or explicitly require this version of this gem.

Resources