2014-08-29 122 views
0

我正在使用rails標記的博客系統上工作。現在它使用連接表,但我對性能有一些疑問。Rails activeRecord補丁和提交

現在,每次創建博客及其關聯標籤時,它都會向數據庫提交每一條語句。我認爲更好的做法應該是修補所有這些語句,並且只向數據庫提交一次。在軌道中可能嗎?

創建日誌轉儲:

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