Turning off logging output in activerecord sqlite3 adaptor in ruby - ruby

I use the ActiveRecord-gem for accessing a sqlite3-database, all without Rails. I use it like this:
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3", :database => name_file )
ActiveRecord::Schema.define do
if ! table_exists? "db_table"
do_something
end
end
And then I get an output like
-- table_exists?("db_table")
-> 0.0048s
Which I don't want. According to different posts, a simple
ActiveRecord::Base.logger = nil
should do the trick. But this is already nil...

Those look like migration messages. This should help:
ActiveRecord::Migration.verbose = false

Related

Ruby Sequel, "insert ignore" returns undefined method?

Trying to do a multi_insert (or insert, for that matter) with the Sequel gem, using "insert_ignore". I get an undefined method error.
The table
DB = Sequel.connect('sqlite://database.db')
DB.create_table! :users do
primary_key :id
String :name, :default => nil, :unique => true
end
users = [{:name => 'bob'}, {:name => 'bob'}, {:name => 'mary'}]
DB[:users].insert_ignore.multi_insert(users)
this returns
undefined method "insert_ignore" for <#Sequel::SQLite::Dataset: "SELECT * FROM 'users'"> (NoMethodError)
what's wrong? Does SQLite3 not support insert_ignore statements?
confused!
Does SQLite3 not support insert_ignore statements? confused!
The Sequel docs for Sequel::MySQL::DatasetMethods, which are here:
http://sequel.jeremyevans.net/rdoc-adapters/classes/Sequel/MySQL/DatasetMethods.html#method-i-insert_ignore
list the method insert_ignore(), but the Sequel docs for Sequel::SQLite::Dataset, which are here:
http://rdoc.info/github/evanfarrar/opensprints/Sequel/SQLite/Dataset
do not list that method, and the fact that you are getting an undefined method error is pretty good evidence that Sequel does not implement insert_ignore() for sqlite.
However, according to the sqlite docs here:
http://sqlite.org/lang_conflict.html
sqlite does support INSERT OR IGNORE queries. So, if you want to use that functionality, it looks like you'll have to use raw sql with Sequel:
require 'sequel'
require 'sqlite3'
DB = Sequel.sqlite('mydb1.db')
DB.create_table! :users do
primary_key :id
String :name, :default => nil, :unique => true
end
#users = [{:name => 'bob'}, {:name => 'bob'}, {:name => 'mary'}]
my_insert =<<END_OF_QUERY
INSERT OR IGNORE INTO users(name) VALUES
('bob'),
('bob'),
('mary')
END_OF_QUERY
data_set = DB[my_insert]
data_set.insert
Your way worked, but I ended up doing something like:
record = DB[table.to_sym].where(data)
if 1 != record.update(data)
DB[table.to_sym].insert(data)
end
end
this way the record gets updated if it already exists
The sequel gem has now implemented SQLite support for Dataset#insert_ignore, released with version 4.30.0 on Jan 4 2016.
Upgrading to sequel >= 4.30.0 should solve this issue.

Activerecord returning all results as a hash

I have the following connecting to a db called dbblah and table1(names changed)
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "192.168.1.10",
:database => "automation",
:username => "root",
:password => "password"
)
ActiveRecord::Base.pluralize_table_names = false
class Table1 < ActiveRecord::Base
end
db = Table1.find_by(db: 'dbname')
puts db
But when I run it, I am getting the results as a hash it looks like:
[root#localhost server]# ruby blah.rb
#<Table1:0x000000019796a8>
This is just the output of to_s method called on a new object - it is definitively not a hash. By default when calling puts method with a non-string, to_s method is called on that object to display a string. For ActiveRecord models to_s method results in exactely what you got.
Try calling p db to display result of method inspect called on that object, which will give you more insight in its internal structure.

In Ruby/Sinatra, Datamapper's .all works but .get doesn't?

I am trying to take data from a path in Sinatra, and use it to look up a particular record using Datamapper. The Datamapper docs seem to indicate that.
get "/test/:test_path" do
test_get = Intake.get( params[:test_path] )
# Do stuff
erb :blah_blah_blah
end
should find any records associated with the symbol :test_path
This does not work. test_get gets nil.
Meanwhile, what does work is
get "/test/:test_path" do
test_all = Intake.all(:test_path => params[:test_path] )
# Do stuff
erb :blah_blah
end
My two questions are:
What am I doing wrong with the .get() call in Datamapper?
Is the .all(:name => value) method slower than .get(), or does it not matter which I use?
Here's a Sinatra script pared down to demonstrate the behavior.
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra'
require 'dm-core'
require 'dm-timestamps'
DataMapper.setup(:default, {:adapter => 'yaml', :path => 'db'})
class Intake
include DataMapper::Resource
property :id, Serial
property :created_at, DateTime
property :test_path, String
end
get "/test/:test_path" do
test_all = Intake.all(:test_path => params[:test_path] )
puts 'test_all:' test_all.inspect
test_get = Intake.get( params[:test_path] )
puts 'test_get:' test_get.inspect
"Hello World!"
end
#get only does a lookup based on primary key, with is the id. So
Intake.get(params[:test_path])
looks for something with id params[:test_path], which will fail. Use
Intake.first(test_path: params[:test_path])

Tests within Gem need to test migration generator and apply migrations for tests

I'm working on a Gem that contains a migration generator and a bunch of models, classes, etc that utilize the tables created as part of the migration.
Although testing the migration generator itself is easy enough - there's loads of tutorials around for getting that done, what i'm trying to work out is how to actually run the migration on the test DB so I can later test how the gem interacts with the test data?
Since the gem doesn't have a schema.rb, I wasn't sure how to go about doing it.
This is how I run migrations in code;
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
ActiveRecord::Migration.verbose = false
#migration = Class.new(ActiveRecord::Migration) do
def change
create_table :users, :force => true do |t|
t.string :roles_mask
end
create_table :user_without_roles, :force => true do |t|
t.string :roles_mask
end
create_table :user_without_role_masks, :force => true do |t|
end
end
end
#migration.new.migrate(:up)
If you have a string containing your generated migration you could do something like this in your test setup;
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
ActiveRecord::Migration.verbose = false
# Or however you intend to grab the output of the migration generator
migration_string = ERB.new(File.read(<file name here>)).result
migration = Class.new(ActiveRecord::Migration)
migration.class_eval(migration_string)
migration.new.migrate(:up)
That should give you a migrated database using the migration you've generated.
You can do something like this:
I am going to assume you're using ActiveRecord. So in your test helper you should setup a in-memory database:
require 'active_record'
# Connection must be establised before anything else
ActiveRecord::Base.establish_connection(
:adapter => defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3',
:database => ':memory:'
)
Then invoke the rake task within your test. This would look something like:
require 'rake'
requie File.expand_path('../Rakefile', __FILE__) # you'll need to modify this path to actually point to the Rakefile
Rake::Task['db:migrate'].invoke
The rake taks invocation is untested, but that should point you in the right direction.
The other option would be to just run the command:
%x{rake db:migrate}

ActiveRecord and sqlite3 : find does not accept any condition?

I have a problem I can't figure out here. I'm writing a ruby script that deals with an sqllite database.
require 'rubygems'
require 'sqlite3'
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => "sqlite3",
:database => "../database/my.db"
)
class KeyWord < ActiveRecord::Base
set_table_name "keywords"
end
# THIS STATEMENT WORKS (finds the first record, returns "ruby") :
KeyWord.find(1).keyval
# THOSE STATEMENTS RETURN NO RESULT :
KeyWord.find(:all, :conditions => {:keyval => "ruby"})
KeyWord.find_by_sql("SELECT * FROM keywords WHERE keyval='ruby'")
KeyWord.find_by_keyval("ruby")
This is how the table was created :
create_table :keywords do |table|
table.column :keyval, :text
end
Does anyone know where this could come from ?
Thanks,
R.
I see a couple of issues here.
I'm not sure why you're manually setting your table name.
ActiveRecord assumes that your model name is camelCased. So... AR
would, by default, search for a table called key_words. Why not just
go with that?
Pay attention to which version of active record you are
using. Passing in conditions is deprecated. You should be using the
.where syntax. So... you would need to do KeyWord.where(:keyval
=> 'ruby').first or end in .all for a collection of results.
If you are just fooling around, you can use sqlite3 in memory.
ActiveRecord::Base.establish_connection( adapter: 'sqlite3',
database: ":memory:")
Also don't forget to define your schema!
Here is full code w/ more modern syntax.
require 'rubygems'
require 'sqlite3'
require 'active_record'
ActiveRecord::Base.establish_connection( adapter: 'sqlite3', database: ":memory:" )
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define(version: 2) do
create_table :key_words do |t|
t.text :keyval
end
end
class KeyWord < ActiveRecord::Base
end
Keyword.create!(:keyval => 'ruby')
# THESE STATEMENTS WORK:
KeyWord.find(1).keyval
KeyWord.where(:keyval => 'ruby').first
KeyWord.where(:keyval => 'ruby').all
KeyWord.find_by_sql("SELECT * FROM key_words WHERE keyval='ruby'")
KeyWord.find_by_keyval("ruby")

Resources