代码之家  ›  专栏  ›  技术社区  ›  Mischa

如何根据查询插入多行?

  •  1
  • Mischa  · 技术社区  · 14 年前

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

    目前,我只是循环浏览系统中的所有文件夹,并为每个文件夹添加权限记录:

    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 回复  |  直到 14 年前
        1
  •  3
  •   johno    14 年前

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

    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
  •  8
  •   Chirantan    14 年前

    你要找的是 ar-extensions


    使用安装gem

    sudo gem install ar-extensions
    

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

    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
    

    在users表中插入了3行新行,其中只有 单一查询!

    更多信息 here , here here .

        3
  •  1
  •   plang    14 年前

    你是在寻找最“红宝石般优雅”的做事方式,还是最快的?为什么不直接从activerecord调用SQL查询呢?另一个解决方案是将查询放在数据库函数中,并从web应用程序调用该函数。也许维护起来有点困难,但性能得到了惊人的提升,尤其是当你的web应用中开始有很多文件夹时。