如何根据查询插入多行?

时间:2010-11-23 14:21:41

标签: mysql ruby-on-rails activerecord ruby-on-rails-3

我正在开发一个包含文件夹,组和权限的系统。权限确定不同组在每个文件夹中可以执行的操作。因此,每当我创建一个新组时,我想在每个文件夹的权限表中添加一条记录,描述新组在该文件夹中可以执行的操作。

目前我只是遍历系统中的所有文件夹并为每个文件夹添加权限记录:

group = Group.create(params)

Folder.all.each do |folder|
  Permission.create! do |permission|
    permission.folder = folder
    permission.group = group
    permission.can_create = true
    permission.can_read = true
    permission.can_update = true
    permission.can_delete = true
  end
end

我不喜欢每次创建新组时都必须遍历所有记录的事实。所以基本上我正在寻找一种使用ActiveRecord执行以下SQL的优雅方法。

INSERT INTO permissions (folder_id, group_id, can_creat, can_read, can_update, can_delete)
SELECT id, #{group.id}, true, true, true, true
FROM folders

我想我可以使用find_by_sql运行上述查询,但这感觉不对,因为我是INSERTing,而不是SELECTing

或者我应该忘记这一点并继续循环我的文件夹记录,如上例所示?

提前致谢。

3 个答案:

答案 0 :(得分:8)

您要找的是ar-extensions


使用

安装gem
sudo gem install ar-extensions

在您的environment.rb中包含gem(或直接在您要插入的模型中)

require 'ar-extensions'

使用

在一个INSERT查询中插入多个记录
fields = [:first_name, :last_name, :email]
data = [["glenn", "gillen", "foo@bar.com"],
       ["john", "jones", "jim@bar.com"],
       ["steve", "smith", "bar@foo.com"]]

User.import fields, data

您也可以使用ActiveRecord对象执行此操作。

data = [ 
         User.new(:first_name => 'glenn', :last_name => 'gillen', :email => 'foo@bar.com'),
         User.new(:first_name => 'john', :last_name => 'jones', :email => 'jim@bar.com'),
         User.new(:first_name => 'steve', :last_name => 'smith', :email => 'bar@foo.com')
       ]

User.import fields, data

只有单个查询就已在用户表中插入了3个新行!

有关它的更多信息hereherehere

答案 1 :(得分:3)

这是我在rails / activerecord中处理自定义sql的方法(包括after_create技巧!)

class Group < ActiveRecord::Base
  after_create :create_default_folder_permissions

  def create_default_folder_permissions
    sql = <<-SQL
     INSERT INTO permissions (folder_id, group_id, can_creat, can_read, can_update, can_delete)
        SELECT id, #{id}, true, true, true, true FROM folders
    SQL
    connection.execute(sql)
  end
end

但是,由于您在权限表中获得number_of_groups * number_of_folders行,因此为每个组和每个文件夹添加权限很快就会成为瓶颈。但是,如果您的查询很简单并且索引正确,则可以轻松扩展到数百万行。

答案 2 :(得分:1)

您正在寻找最“红宝石般优雅”的做事方式,还是最快的?为什么不直接从activerecord调用SQL查询?另一个解决方案是将您的查询放在数据库函数中,并从您的Web应用程序调用该函数。也许有点难以维护,但性能提升令人难以置信,特别是当你开始在你的网络应用程序中有很多文件夹时。