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

Antworten:



100
connection = ActiveRecord::Base.connection
connection.execute("SQL query") 

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


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"}>, ...]

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


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.