Rails 3 führt eine benutzerdefinierte SQL-Abfrage ohne Modell aus

105

Ich muss ein eigenständiges Ruby-Skript schreiben, das sich mit der Datenbank befassen soll. Ich habe den unten in Schiene 3 angegebenen Code verwendet

@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

aber Fehler bekommen: -

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

Was fehlt mir hier?

LÖSUNG

Nachdem ich die Lösung von denis-bu bekommen hatte, benutzte ich sie wie folgt und das funktionierte auch.

@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
neeraj
quelle

Antworten:

168

Vielleicht versuchen Sie Folgendes:

ActiveRecord::Base.establish_connection(...)
ActiveRecord::Base.connection.execute(...)
denis-bu
quelle
14
FWIW, die Verwendung leerer Parameter ist kein idiomatischer Rubin. Also connection.executelieber alsconnection().execute
Radixhound
Funktioniert auch auf Rails 4.
Leigh McCulloch
github.com/igorkasyanchuk/execute_sql Es wird weniger Code benötigt und Sie können dies in der Konsole mit direkter Schiene tun
Igor Kasyanchuk
100
connection = ActiveRecord::Base.connection
connection.execute("SQL query") 
Sachin R.
quelle
8
In diesem Fall ist connection = ActiveRecord :: Base.connection; connection.execute ("SQL-Abfrage") würde funktionieren. Weniger tippen!
Watusimoto
16
Oder einfachActiveRecord::Base.connection.execute("SQL query")
Kasper Grubbe
3
Diese Verbindung muss möglicherweise anschließend wieder in den Verbindungspool aufgenommen werden, um Threading-Probleme zu vermeiden: ActiveRecord::Base.connection_pool.checkin(connection) apidock.com/rails/ActiveRecord/ConnectionAdapters/…
Lee
35

Ich würde empfehlen, ActiveRecord::Base.connection.exec_queryanstelle von ActiveRecord::Base.connection.executea ActiveRecord::Result(verfügbar in Rails 3.1+) zu verwenden, was etwas einfacher zu handhaben ist.

Dann können Sie es in verschiedenen Zugriff auf das Ergebnis auf verschiedene Weise wie .rows, .eachoder.to_hash

Aus den Dokumenten :

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

Hinweis: Ich habe meine Antwort von hier kopiert

hajpoj
quelle
1
Wie bereits erwähnt, gibt exec_query die tatsächlichen Ergebnisse zurück - was ich möchte, während execute nur Statusinformationen zurückgibt.
Paul Chernoch
24

Sie können auch find_by_sql verwenden

# 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"}>, ...]
montrealmike
quelle
Mein Skript befindet sich außerhalb der Rails-Anwendung, daher glaube ich nicht, dass find_by_sql funktionieren würde.
Neeraj
4
Du hast recht, ich habe deine Frage zu schnell gelesen. Diese Antwort kann anderen helfen, die aufgrund Ihres Fragentitels auf diese Seite gelangen.
Montreal Real
Wie bekomme ich kein Array, sondern eine Beziehung?
Малъ Скрылевъ
4

Wie wäre es damit :

@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

Sie müssen TinyTds gem installiert haben, da Sie es in Ihrer Frage nicht angegeben haben. Ich habe Active Record nicht verwendet

Ameise
quelle
1
Sicher, TinyTds ist ein ganz anderes Juwel. Es ist kein ActiveRecord. Um es zu verwenden, sollten Sie es separat installieren.
Denis-Bu
1
Ich möchte kein zusätzliches GEM verwenden, solange mysql2 und active-record verfügbar sind
neeraj
Gut, Sie sollten das in Ihrer Frage (Tag / Titel) erwähnen
Ameise
2
TinyTDS funktioniert mit MSSQL und Sybase, nicht mit MySQL. ant: Sie sollten dies in Ihrer Antwort erwähnen und nicht davon ausgehen, dass das OP dasselbe Nischen-DBMS verwendet wie Sie.
Cliffordheath