在rails 3.2中使用build方法在内存中创建对象

时间:2012-07-20 14:52:30

标签: ruby-on-rails-3 activerecord

我有2个模型,如下所示


    Class Post  
      has_many :comments, :dependent => :destroy 
    end  

    Class Comment  
      validates_presence_of :post
      validates_presence_of :comment
      belongs_to :post  
    end  
  

在评论控制器中,
  


    def create
      comment = @post.comments.build(params[:comment])
      if comment.save
        // some code
      else
        // some code
      end
    end

根据验证评论无效时,评论不会保存。但是当在视图中访问@post对象时,它包含一个带有nil id的注释对象。这在Rails 2.3.11中没有发生。我们升级到Rails 3.1,然后升级到Rails 3.2。当我执行@ post.reload时,这个带有nil id的注释对象消失了。我们正在使用REE。

我试图交换构建和新方法。它与build具有相同的结果。我们的应用程序中发现了类似的行为这是预期的行为,还是我做错了什么?

2 个答案:

答案 0 :(得分:2)

这对我来说似乎是预期的行为。

通过http://guides.rubyonrails.org/association_basics.html#belongs_to-association-reference

  

4.1.1.3 build_association(attributes = {})

     

build_association方法返回关联的新对象   类型。此对象将从传递的属性中实例化,并且   通过此对象的外键的链接将被设置,但是   相关对象尚未保存。

当你致电@post.comments.build(...)时,Rails:

  1. 创建新的Comment对象
  2. comment.post_id设置为@post.id
  3. 将其插入comments数组(内存中)。
  4. 验证失败时,它不会删除注释,并且注释会在内存中的注释数组中保留。当@post进入您的观点时,@post.comments仍会包含经过严格验证的评论。

    关于如何处理它,我不确定。也许你可以做一些像(在你的控制器中)......(虽然觉得很难看。)

    def create
      comment = @post.comments.build(params[:comment])
      if comment.save
        // some code
      else
        @bad_comment = @post.comments.pop
      end
    end
    

答案 1 :(得分:0)

使用rails 3.2时遇到了类似的问题

首先,您需要在控制器中创建两个单独的方法。他们将如下:

  1. 使用'build_association'构建评论的'新'方法

    def new
        @post = Post.new
        comment = @post.build_comments
    end
    
  2. 使用'create_association'实际创建评论的'创建'方法

    def create 
        @post = Post.new(params[:post])
        comment = @post.create_comments(params[:post][:comment_attributes])
    
        if comment.save
            // some code
        else
            @bad_comment = @post.comments.pop
        end
    end
    
  3. 注意:我建议使用'fields_for'通过表单将'comment'属性作为'post'的嵌套属性传递。

    请参阅: http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for

    http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html