106

I need to write a standalone ruby script that is supposed to deal with database. I used code given below in rails 3

@connection = ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:database => "siteconfig_development",
:username => "root",
:password => "root123"
)

results = @connection.execute("select * from users")
results.each do |row|
puts row[0]
end

but getting error:-

`<main>': undefined method `execute' for #<ActiveRecord::ConnectionAdapters::ConnectionPool:0x00000002867548> (NoMethodError)

what i am missing here?

SOLUTION

After getting solution from denis-bu i used it following way and that worked too.

@connection = ActiveRecord::Base.establish_connection(
            :adapter => "mysql2",
            :host => "localhost",
            :database => "siteconfig_development",
            :username => "root",
            :password => "root123"
)

sql = "SELECT * from users"
@result = @connection.connection.execute(sql);
@result.each(:as => :hash) do |row| 
   puts row["email"] 
end

5 Answers 5

168

Maybe try this:

ActiveRecord::Base.establish_connection(...)
ActiveRecord::Base.connection.execute(...)
Sign up to request clarification or add additional context in comments.

3 Comments

FWIW, Using empty params is not idiomatic ruby. So do connection.execute rather than connection().execute
Works on Rails 4 also.
github.com/igorkasyanchuk/execute_sql less code is needed plus you can do it in directly rails console
99
connection = ActiveRecord::Base.connection
connection.execute("SQL query") 

3 Comments

In this case, connection = ActiveRecord::Base.connection; connection.execute("SQL query") would work. Less typing!
Or just ActiveRecord::Base.connection.execute("SQL query")
This connection may have to be returned to the connection pool afterwards to avoid threading issues: ActiveRecord::Base.connection_pool.checkin(connection) apidock.com/rails/ActiveRecord/ConnectionAdapters/…
40

I'd recommend using ActiveRecord::Base.connection.exec_query instead of ActiveRecord::Base.connection.execute which returns a ActiveRecord::Result (available in rails 3.1+) which is a bit easier to work with.

Then you can access it in various the result in various ways like .rows, .each, or .to_hash

From the docs:

result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts')
result # => #<ActiveRecord::Result:0xdeadbeef>


# Get the column names of the result:
result.columns
# => ["id", "title", "body"]

# Get the record values of the result:
result.rows
# => [[1, "title_1", "body_1"],
      [2, "title_2", "body_2"],
      ...
     ]

# Get an array of hashes representing the result (column => value):
result.to_hash
# => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
      {"id" => 2, "title" => "title_2", "body" => "body_2"},
      ...
     ]

# ActiveRecord::Result also includes Enumerable.
result.each do |row|
  puts row['title'] + " " + row['body']
end

note: copied my answer from here

2 Comments

As stated, exec_query returns the actual results - what I want, while execute just returns status information.
As of Rails-7.0 and Ruby-3.1, .to_hash is undefined (Ver.7.0.4 doc). Instead, .to_a returns an Array of Hash. Make sure the column names are unique in using .to_a, e.g., specify "SELECT 3 a,4 b,5 c;" as opposed to "SELECT 3,4,5;".
25

You could also use find_by_sql

# A simple SQL query spanning multiple tables
Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
> [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "first_name"=>"Quentin"}>, ...]

3 Comments

my script is outside rails application so i don't think find_by_sql would work.
you're right, i read your question too quickly. This answer might help others who come to this page based on your question title.
how to get not an array but relation?
4

How about this :

@client = TinyTds::Client.new(
      :adapter => 'mysql2',
      :host => 'host',
      :database => 'siteconfig_development',
      :username => 'username',
      :password => 'password'

sql = "SELECT * FROM users"

result = @client.execute(sql)

results.each do |row|
puts row[0]
end

You need to have TinyTds gem installed, since you didn't specify it in your question I didn't use Active Record

4 Comments

Sure, TinyTds is whole other gem.. It is not ActiveRecord. To use it you should install it separately.
I don't want to use any additional GEM as long as mysql2 and active-record is available
Good, you should mention that in your question (tag/title)
TinyTDS works with MSSQL and Sybase, it doesn't work with MySQL. ant: You should mention that in your answer, and not assume that the OP is using the same niche DBMS as you are.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.