【问题标题】:Rails activeRecord patch and commitRails activeRecord 补丁和提交
【发布时间】:2014-08-29 20:26:04
【问题描述】:

我正在使用 Rails 开发一个标记的博客系统。现在它可以使用连接表,但我对性能有些怀疑。

现在,每次我创建博客及其关联标签时,它都会将每条语句提交到数据库。我认为更好的做法应该是修补所有这些语句并只提交一次数据库。在rails中可以吗?

创建日志转储:

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

【问题讨论】:

    标签: ruby-on-rails database activerecord


    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2012-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多