Exemplo SQL raw Rails
@payments = PaymentDetail.joins(:project).order('payment_details.created_at desc')
@payment_errors = PaymentError.joins(:project).order('payment_errors.created_at desc')
@all_payments = (@payments + @payment_errors)
5 answers
Podes fazer isto:
sql = "Select * from ... your sql query here"
records_array = ActiveRecord::Base.connection.execute(sql)
records_array
seria então o resultado de sua consulta sql em um array que você pode iterar através.
Model.find_by_sql
Se quiser instanciar os resultados:
Client.find_by_sql("
SELECT * FROM clients
INNER JOIN orders ON clients.id = orders.client_id
ORDER BY clients.created_at desc
")
# => [<Client id: 1, first_name: "Lucas" >, <Client id: 2, first_name: "Jan">...]
Model.connection.select_all('sql').to_hash
Se quiser apenas hash de valores:
Client.connection.select_all("SELECT first_name, created_at FROM clients
WHERE id = '1'").to_hash
# => [
{"first_name"=>"Rafael", "created_at"=>"2012-11-10 23:23:45.281189"},
{"first_name"=>"Eileen", "created_at"=>"2013-12-09 11:22:35.221282"}
]
Objecto do resultado:
select_all
devolve um objecto result
. Podes fazer coisas mágicas com ele.
result = Post.connection.select_all('SELECT id, title, body FROM posts')
# 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
Fontes:
- ActiveRecord-Findinig by SQL .
- Ruby on Rails-Active Record Resultado .
Você pode fazer SQL direto para ter uma única consulta para ambas as tabelas. Eu vou fornecer um exemplo de consulta Higienizada para evitar que as pessoas coloquem variáveis diretamente no texto em si( perigo de injeção SQL), mesmo que este exemplo não especificasse a necessidade dele:
@results = []
ActiveRecord::Base.connection.select_all(
ActiveRecord::Base.send(:sanitize_sql_array,
["... your SQL query goes here and ?, ?, ? are replaced...;", a, b, c])
).each do |record|
# instead of an array of hashes, you could put in a custom object with attributes
@results << {col_a_name: record["col_a_name"], col_b_name: record["col_b_name"], ...}
end
Edit : Como Huy disse, uma maneira simples é ActiveRecord::Base.connection.execute("...")
. Outra maneira é ActiveRecord::Base.connection.exec_query('...').rows
E você pode usar declarações preparadas nativas, por exemplo, se usando postgres, declaração preparada pode ser feito com raw_connection, preparar, e execut_ preparado como descrito em https://stackoverflow.com/a/13806512/178651
Você também pode colocar fragmentos de SQL em pesquisas relacionais ActiveRecord: http://guides.rubyonrails.org/active_record_querying.html e em associações, âmbitos, etc. Você provavelmente poderia construir o mesmo SQL com consultas relacionais de acordes e pode fazer coisas legais com a ARel como Ernie menciona em http://erniemiller.org/2010/03/28/advanced-activerecord-3-queries-with-arel/. E, claro, há outros ORMs, pedras preciosas, etc.
Se isto vai ser usado muito e a adição de índices não vai causar outros problemas de desempenho/recursos, considere adicionar um índice no DB para payment_details.criado_ AT e para erros de pagamento.created_ at.
Se muitos registos e nem todos os registos tiverem de aparecer de uma só vez, considera usar paginação:
Se precisar de paginar, pense em criar uma vista no DB chamada payment_records que combina as tabelas payment_details e payment_ errones, em seguida, ter um modelo para a vista (que será apenas para leitura). Alguns DBS suportam vistas materializadas, o que pode ser uma boa idéia para o desempenho.
Também considere especificações de hardware ou VM sobre o servidor Rails e o servidor DB, configuração, espaço em disco, velocidade da rede/latência/etc., proximidade, etc. E considere colocar DB em um servidor/VM diferente do aplicativo Rails se você não tiver, etc.
Você pode executar a pesquisa raw usando ActiveRecord
. E eu vou sugerir ir com o bloco SQL
query = <<-SQL
SELECT *
FROM payment_details
INNER JOIN projects
ON projects.id = payment_details.project_id
ORDER BY payment_details.created_at DESC
SQL
result = ActiveRecord::Base.connection.execute(query)
Também pode misturar SQL raw com condições de ActiveRecord, por exemplo se quiser chamar uma função numa condição:
my_instances = MyModel.where.not(attribute_a: nil) \
.where('crc32(attribute_b) = ?', slot) \
.select(:id)