Как вставить несколько строк на основе запроса? - PullRequest
1 голос
/ 23 ноября 2010

Я занимаюсь разработкой системы, в которой есть папки, группы и разрешения. Разрешения определяют, что разные группы могут делать в каждой папке. Поэтому всякий раз, когда я создаю новую группу, я хочу добавить в таблицу разрешений для каждой папки запись, описывающую, что новая группа может делать в этой папке.

В настоящее время я просто перебираю все папки в системе и добавляю запись разрешений для каждой папки:

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

Мне не нравится тот факт, что мне приходится просматривать все записи каждый раз, когда я создаю новую группу. Поэтому в основном я ищу элегантный способ выполнить следующий SQL с помощью ActiveRecord.

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 ]

8 голосов
/ 02 декабря 2010

То, что вы ищете, это ar-extensions


Установите драгоценный камень, используя

sudo gem install ar-extensions

Включите драгоценный камень в ваш 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

3 новых строки были добавлены в таблицу пользователей, с помощью одного одиночного запроса!

Подробнее об этом здесь , здесь и здесь .

3 голосов
/ 01 декабря 2010

Вот как я работаю с пользовательским sql в rails / activerecord (трюк 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строки в таблице разрешений.Но если ваши запросы просты и индексы правильны, вы можете легко масштабировать до миллионов строк.

1 голос
/ 26 ноября 2010

Вы ищете самый "элегантный" стиль работы или самый быстрый? Почему бы вам напрямую не вызвать свой SQL-запрос из activerecord? Другое решение - поместить ваш запрос в функцию базы данных и вызвать эту функцию из вашего веб-приложения. Может быть, немного сложнее в обслуживании, но невероятный прирост производительности, особенно когда вы начинаете иметь много папок в своем веб-приложении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...