Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在一个事务中分配或创建关联模型_Ruby On Rails_Ruby On Rails 3_Activerecord - Fatal编程技术网

Ruby on rails 在一个事务中分配或创建关联模型

Ruby on rails 在一个事务中分配或创建关联模型,ruby-on-rails,ruby-on-rails-3,activerecord,Ruby On Rails,Ruby On Rails 3,Activerecord,我有文章,每篇文章都有许多类别 当用户创建或更新文章时,他或她可以填写类别名称,如果此类类别尚不存在,则需要创建一个新类别 型号 class Article < ActiveRecord::Base attr_accessible :category_id, :content, :title, :category_name belongs_to :category def category_name category.try(:name) end def

我有
文章
,每篇文章都有许多
类别

当用户创建或更新文章时,他或她可以填写类别名称,如果此类类别尚不存在,则需要创建一个新类别

型号

class Article < ActiveRecord::Base
  attr_accessible :category_id, :content, :title, :category_name

  belongs_to :category

  def category_name
    category.try(:name)
  end

  def category_name=(name)
    self.category = Category.find_or_create_by_name(name) if name.present?
  end
end

class Category < ActiveRecord::Base
  attr_accessible :name

  has_many :articles
end
我想得到一些建议/解决方案,如何优雅地解决这个问题

我可能会在我的控制器里写东西

ActiveRecord::Base.transaction do
  @article = Article.create(params[:article])
  respond_with(@article)
end
但这意味着我必须用两种方法编写相同的代码:
create
update
。因为这违反了干燥原则,我宁愿另找一种方法

  • 我不关心一行代码是否枯燥
  • 你可以做如下的事情
  • 请注意,我不喜欢这个,但它是可行的

    def update
      article = Article.find(params[:id])
      article.attributes = params[:article]
      respond_with persist(article)
    end
    
    def create
      article = Article.new(params[:article])
      respond_with persist(article)
    end
    
    private
    
    def persist(article)
      ActiveRecord::Base.transaction do
        return article.save
      end
    end
    

    老问题,但万一有人正在寻找类似问题的解决方案:

    我认为您应该能够在不干扰事务的情况下处理它,并使用嵌套属性,如下所示:

    class Article < ActiveRecord::Base
      # ...
    
      belongs_to :category
    
      accepts_nested_attributes_for :category
    
      def category_name=(name)
        category = Category.find_by(name: name)
        if category
          self.category_id = category.id
        else
          self.category_attributes = {name: name}
        end
      end
    end
    
    类文章
    因此,如果存在具有该名称的类别,它将只分配类别id。否则,它将通过嵌套属性分配一个新类别,该属性将确保在没有其他验证错误的情况下保持该类别,而在有其他验证错误的情况下不保持该类别。

    查看Railscast on。这需要一些额外的步骤,但Ryan在解释过程中做得很好。
    def update
      article = Article.find(params[:id])
      article.attributes = params[:article]
      respond_with persist(article)
    end
    
    def create
      article = Article.new(params[:article])
      respond_with persist(article)
    end
    
    private
    
    def persist(article)
      ActiveRecord::Base.transaction do
        return article.save
      end
    end
    
    class Article < ActiveRecord::Base
      # ...
    
      belongs_to :category
    
      accepts_nested_attributes_for :category
    
      def category_name=(name)
        category = Category.find_by(name: name)
        if category
          self.category_id = category.id
        else
          self.category_attributes = {name: name}
        end
      end
    end