0

我正在学习teamtreehouse课程。正在重构的一件事是能够将发布的状态的 user_id 限制为仅当前登录用户的 user_id。我们已经建立了一个过滤器,他们必须先登录才能发布,所以我们在这里要做的唯一事情就是阻止用户以其他用户的身份发布状态。

一个用户has_many :statuses

这就是控制器中的 Statuses#create 方法的样子

 def create
    @status = Status.new(params[:status])

    respond_to do |format|
      if @status.save
        format.html { redirect_to @status, notice: 'Status was successfully created.' }
        format.json { render json: @status, status: :created, location: @status }
      else
        format.html { render action: "new" }
        format.json { render json: @status.errors, status: :unprocessable_entity }
      end
    end
  end

我们正在改变的是@status = Status.new(params[:status])

现在我们为我们的用户模型使用设计,所以当前用户由current_user

将创建以下更改:@status = current_user.statuses.new(params[:status])

这句话让我很困惑

我试图弄清楚这里发生了什么。

以下是我使用 rails 控制台对流程的探索:

irb(main):003:0> User.first.statuses
  User Load (0.5ms)  SELECT "users".* FROM "users" LIMIT 1
  Status Load (0.1ms)  SELECT "statuses".* FROM "statuses" WHERE "statuses"."user_id" = 2
=> [#<Status id: 2, content: "this is a test status", created_at: "2013-07-23 20:53:35", updated_at: "2013-07-23 20:53:35", user_id: 2>, #<Status id: 3, content: "test2", created_at: "2013-07-23 21:34:59", updated_at: "2013-07-23 21:34:59", user_id: 2>]
irb(main):004:0> User.first.statuses.class
  User Load (0.6ms)  SELECT "users".* FROM "users" LIMIT 1
  Status Load (0.3ms)  SELECT "statuses".* FROM "statuses" WHERE "statuses"."user_id" = 2
=> Array
irb(main):005:0> User.first.statuses.new.class
  User Load (0.5ms)  SELECT "users".* FROM "users" LIMIT 1
=> Status(id: integer, content: text, created_at: datetime, updated_at: datetime, user_id: integer)
irb(main):006:0> Array.new
=> []
irb(main):007:0> Array.new.class
=> Array
irb(main):008:0> 

为什么当我发现从 User.first.statuses 返回的对象的类(如预期的那样)是一个数组,但是在数组上调用的 .new 类却生成了一个新的状态。这如何/为什么起作用?当我调用 Array.new 时,我得到一个数组,我们不是在数组对象上调用 new 吗?

4

1 回答 1

2

诀窍是,current_user.statuses不返回数组。当然它看起来像一个数组,如果你尝试它甚至会告诉你它是一个数组current_user.statuses.class,但那是在它被懒惰地评估之后。实际上返回的是一个对象ActiveRecord::Relation,您可以通过current_user.statuses.foo在 rails 控制台中尝试自己确认这一点;你会收到类似的消息undefined method 'foo' for #<ActiveRecord::Relation:0x007fba7d603918>。ActiveRecord::Relation 是 ActiveRecord 的一个非常有用的部分,它在您将对象链接在一起时为您管理范围,并且在您请求不是另一个 ActiveRecord::Relation 的东西之前实际上不会对数据库执行查询。

Ryan Bates 在他的Railscast中很好地解释了这一点,这是一个讨论ActiveRecord::Relation 与 Arel的博客,其中也讨论了这一点。

于 2013-07-27T02:37:57.857 回答