2014-08-29 2 views
0

Я работаю над системой с тегами с использованием рельсов. Теперь он работает с использованием таблицы join, но у меня есть некоторые сомнения в производительности.Rails activeRecord patch and commit

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

Создание дампа журнала:

Started POST "/articles" for 127.0.0.1 at 2014-08-29 15:30:48 -0400 
Processing by ArticlesController#create as HTML 
    Parameters: {"utf8"=>"✓", "authenticity_token"=>"K4rWQEh0810X2jMe/Z9pC/PN2WeOcO0F0TkjKUZTPec=", "title"=>"test27", "text"=>"ddddd", "tag"=>"a,k,g", "commit"=>"Submit"} 
Unpermitted parameters: utf8, authenticity_token, tag, commit 
    (0.9ms) BEGIN 
    SQL (0.3ms) INSERT INTO `articles` (`created_at`, `text`, `title`, `updated_at`) VALUES ('2014-08-29 19:30:48', 'ddddd', 'test27', '2014-08-29 19:30:48') 
    (0.2ms) COMMIT 
    Tag Load (0.3ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`name` = 'a' LIMIT 1 
    (0.2ms) BEGIN 
    SQL (0.3ms) INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES (28, 1) 
    (0.2ms) COMMIT 
    Tag Load (0.2ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`name` = 'k' LIMIT 1 
    (0.1ms) BEGIN 
    SQL (0.2ms) INSERT INTO `tags` (`name`) VALUES ('k') 
    (0.1ms) COMMIT 
    (0.1ms) BEGIN 
    SQL (0.3ms) INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES (28, 17) 
    (8.3ms) COMMIT 
    Tag Load (0.3ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`name` = 'g' LIMIT 1 
    (0.1ms) BEGIN 
    SQL (0.2ms) INSERT INTO `tags` (`name`) VALUES ('g') 
    (0.1ms) COMMIT 
    (0.1ms) BEGIN 
    SQL (0.4ms) INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES (28, 18) 
    (0.2ms) COMMIT 

дизайн Модель:

class Article < ActiveRecord::Base 
    has_and_belongs_to_many :tag 
end 

class Tag < ActiveRecord::Base 
    has_and_belongs_to_many :article, :uniq => true 
end 

Блог создать код:

def create 
     @article = Article.new(article_params) 
     tag_arr = params[:tag].split(',') 

     if @article.save 
      tag_arr.each do |name| 
       tag = Tag.find_or_create_by(name: name) # create a new tag only if tag.name not exist 
       @article.tag << tag 
      end 
      redirect_to @article 
     else 
      render 'new' 
     end 
    end 

ответ

1

Чтобы сохранить статью и теги в одной транзакции, завернуть операции в блоке transaction.

def create 
    @article = Article.new(article_params) 
    tag_arr = params[:tag].split(',') 

    Article.transaction do 
    if @article.save 
     tag_arr.each do |name| 
     article.tags.find_or_create_by(name: name) 
     end 
    end 
    end 

    if @article.new_record? 
    render 'new' 
    else 
    redirect_to @article 
    end 
end 

Это приведет к SQL запросов что-то вроде:

(0.9ms) BEGIN 
SQL (0.3ms) INSERT INTO `articles` (`created_at`, `text`, `title`, `updated_at`) VALUES ('2014-08-29 19:30:48', 'ddddd', 'test27', '2014-08-29 19:30:48') 
Tag Load (0.3ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`name` = 'a' LIMIT 1 
SQL (0.3ms) INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES (28, 1) 
Tag Load (0.2ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`name` = 'k' LIMIT 1 
SQL (0.2ms) INSERT INTO `tags` (`name`) VALUES ('k') 
SQL (0.3ms) INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES (28, 17) 
Tag Load (0.3ms) SELECT `tags`.* FROM `tags` WHERE `tags`.`name` = 'g' LIMIT 1 
SQL (0.2ms) INSERT INTO `tags` (`name`) VALUES ('g') 
SQL (0.4ms) INSERT INTO `articles_tags` (`article_id`, `tag_id`) VALUES (28, 18) 
(0.2ms) COMMIT