有没有办法将Rails模型转换为插入查询?
例如,如果我有一个类似的模型:
m = Model.new
m.url = "url"
m.header = "header"
如果我执行m.save?
,如何获取ActiveRecord会生成的相应SQL查询?我想得到:“INSERT INTO模型(网址,标题)VALUES('url','header')”如果可能的话。
注意:我不想实际保存模型并返回查询(从日志文件等)。如果我选择保存它,我想获得查询。
答案 0 :(得分:7)
在Rails 4.1上,我发现以下代码片段正常工作:
record = Post.new(:title => 'Yay', :body => 'This is some insert SQL')
record.class.arel_table.create_insert
.tap { |im| im.insert(record.send(
:arel_attributes_with_values_for_create,
record.attribute_names)) }
.to_sql
感谢https://coderwall.com/p/obrxhq/how-to-generate-activerecord-insert-sql
答案 1 :(得分:2)
在Rails中测试3.2.13:我想我这次做对了,这次肯定不会持久存在于db中。它也不会触发验证或回调,因此除非您以其他方式调用它们,否则它们更改的任何内容都不会出现在结果中。
将其作为insert_sqlable.rb保存在lib中,然后可以
#in your models or you can send it to ActiveRecord::Base
include InsertSqlable
然后是model.insert_sql来查看它。
#lib/insert_sqlable
module InsertSqlable
def insert_sql
values = arel_attributes_values
primary_key_value = nil
if self.class.primary_key && Hash === values
primary_key_value = values[values.keys.find { |k|
k.name == self.class.primary_key
}]
if !primary_key_value && connection.prefetch_primary_key?(self.class.table_name)
primary_key_value = connection.next_sequence_value(self.class.sequence_name)
values[self.class.arel_table[self.class.primary_key]] = primary_key_value
end
end
im = self.class.arel_table.create_insert
im.into self.class.arel_table
conn = self.class.connection
substitutes = values.sort_by { |arel_attr,_| arel_attr.name }
binds = substitutes.map do |arel_attr, value|
[self.class.columns_hash[arel_attr.name], value]
end
substitutes.each_with_index do |tuple, i|
tuple[1] = conn.substitute_at(binds[i][0], i)
end
if values.empty? # empty insert
im.values = Arel.sql(self.class.connectionconnection.empty_insert_statement_value)
else
im.insert substitutes
end
conn.to_sql(im,binds)
end
end
事实证明,代码在ActiveRecord :: Relation中,而不是ActiveRecord :: Persistence。唯一重要的变化是生成sql而不是执行它的最后一行。
答案 2 :(得分:0)
如果您不想保存模型,则在完成对象后调用m.destroy。
您可以通过调试它来记录sql查询
Rails.logger.debug“INSERT INTO models(url,header)VALUES(#{m.url},#{m.header})。inspect
答案 3 :(得分:0)
经过互联网和论坛搜索后,我想我找到了一个更好的解决方案:只需要两行代码。
我找到了一个很好的宝石,可以完全按照自己的意愿行事,但这个宝石仅适用于Rails 3.2及更早版本。我talked with author,他不想再支持这个宝石了。所以我自己发现了如何支持Rails 4.0,现在我正在维护这个宝石。
<小时/> 有了这个宝石,您可以轻松地执行以下操作。 ( values 中的示例只是一个笑话,在对象中使用它时会得到正确的值)。
对象:
object.to_sql_insert
# INSERT INTO modelName (field1, field2) VALUES ('Wow, amaze gem', 'much doge')
对于objets数组:
array_of_objects.to_sql_insert
# INSERT INTO modelName (field1, field2) VALUES ('Awesome doge', "im fucking cop")
# INSERT INTO modelName (field1, field2) VALUES ('much profit', 'much doge')
# (...)
只需看看Github of this project,您就会发现如何安装和使用这个美妙的宝石。