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.