Exemplo SQL raw Rails

Como posso converter este código em SQL bruto e usá-lo em carris? Porque quando eu uso este código em heroku, há um erro de tempo-limite de pedido.Acho que será mais rápido se eu usar SQL raw.

@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)
Author: Dorian, 2013-02-12

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.

 313
Author: Huy, 2013-02-12 19:48:23
Eu sei que isto é velho... Mas eu estava tendo o mesmo problema hoje e encontrar uma solução:
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:

  1. ActiveRecord-Findinig by SQL .
  2. Ruby on Rails-Active Record Resultado .
 127
Author: João Paulo Motta, 2017-06-17 20:14:58

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.

 24
Author: Gary S. Weaver, 2017-05-23 12:34:40

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)
 16
Author: Deepak Mahakale, 2016-09-20 14:13:47

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)
 1
Author: tsauerwein, 2018-07-02 09:30:46