Activerecord returning all results as a hash - ruby

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.

Related

Construct nested OpenStruct object

I have to mimic a Google API response and create a 2-level deep data structure that is traversable by . like this:
=> user.names.first_name
Bob
Is there any smarter/better way than this:
user = OpenStruct.new(names: OpenStruct.new(first_name: 'Bob'))
This method is rude method but works,
require 'ostruct'
require 'json'
# Data in hash
data = {"names" => {"first_name" => "Bob"}}
result = JSON.parse(data.to_json, object_class: OpenStruct)
And another method is adding method to Hash class itself,
class Hash
def to_openstruct
JSON.parse to_json, object_class: OpenStruct
end
end
Using above method you can convert your hash to openstruct
data = {"names" => {"first_name" => "Bob"}}
data.to_openstruct

active record with ruby (not rails)

I am using active record with ruby (but not rails). I am using sqlite3 which has a test.db on file (not just in-memory). When I run the following code snippet using user.create, it complains about argument error (and when I use use.save, it throws an active record exception. Any idea what I might be doing wrong? Thanks
require 'rubygems'
gem 'activerecord'
require 'sqlite3'
require 'active_record'
ActiveRecord::Base.logger = Logger.new(STDERR)
#ActiveRecord::Base.colorize_logging = false
ActiveRecord::Base.establish_connection(
:adapter => 'sqlite3',
:host => "localhost",
:database => 'test.db'
)
class User < ActiveRecord::Base
#attr_accessible :email, :full_name
attr_accessor :email
attr_accessor :full_name
validates :email, presence: true, uniqueness: true
def initialize(email, full_name)
#email = email
#full_name = full_name
end
end
puts "full_name for user:"
full_name = gets.chomp
puts "email address:"
email = gets.chomp
user = User.new(email, full_name)
#user.save
user = User.create!(email: '', full_name: '')
Exception in first case (with User.create!):
main.rb:42:in `initialize': wrong number of arguments (1 for 2) (ArgumentError)
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/inheritance.rb:61:in `new'
from /var/lib/gems/1.9.1/gems/activerecord-4.2.4/lib/active_record/persistence.rb:50:in `create!'
from main.rb:55:in `<main>'
It is complaining about the new method. According to the documentation: (http://api.rubyonrails.org/classes/ActiveRecord/Base.html), you don't need the initialize, because when you inherit from ActiveRecord::Base, you need to initialize your objects with a hash.
user = User.new({email: email, full_name: full_name})
# or
user = User.new(email: email, full_name: full_name)
# then
user.save
You need to drop the initialize and the attr_accessor from your code.
Try to comment User#initialize method and create new user like this:
User.create! email: 'halk#mail.com', full_name: 'Halk'
Explanation
When you declare AR model by heritage from ActiveRecord::Base class you don't need to define your own #initialize method. But you do. When you call User::create! method, you pass only one argument - Hash with two pairs (with email and full_name keys). But User#initialize define two parameters - email and full_name separately. So Ruby exception raise and talk about it:
wrong number of arguments (1 for 2) (ArgumentError)

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.

ruby active_record connection within a class

My problem is that I want to put my connection and SQL statements in site methods in my class, but when I put it in separate methods and call the methods from elsewhere it won't connect to my MySQL database. My code:
require 'active_record'
class Databaseoperation < ActiveRecord::Base
def initialize
$mysqlinfo = Hash[*File.read('/home/me/properties/mysql.property').split(/=|\n/)]
end
def mysqlConnect
self.establish_connection(:adapter => 'jdbcmysql', :database => 'mydb' , :host => 'localhost', :username => 'root', :password => 'root' )
end
def getSqlServer
$record = MysqlConnection.connection.select_all('SELECT * from Installation')
end
end
dbp = Databaseoperation.new
dbp.mysqlConnect
Error message:
ActiveRecord::ConnectionNotEstablished: ActiveRecord::ConnectionNotEstablished
retrieve_connection at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/connection_adapters/abstract/connection_pool.rb:546
retrieve_connection at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/connection_handling.rb:79
connection at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/connection_handling.rb:53
columns at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/model_schema.rb:208
column_names at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/model_schema.rb:247
define_attribute_methods at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/attribute_methods.rb:29
synchronize at org/jruby/ext/thread/Mutex.java:149
define_attribute_methods at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/attribute_methods.rb:26
method_missing at /home/me/.rvm/gems/jruby-1.7.4/gems/activerecord-4.0.0/lib/active_record/attribute_methods.rb:123
mysqlConnect at ./databaseoperation.rb:12
(root) at ./databaseoperation.rb:23
If I don't put my statements inside methods in my class it connects to the database. But I really would like to be able to have connections and sql statements separated in methods for my class. How can I do this? Note that I'm using jruby-1.7.4.

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