我正在关注团队之家课程。正在重新考虑的事情之一是能够将发布状态的user_id限制为仅限当前登录用户的状态。我们已经建立了一个必须登录才能发布的过滤器,所以我们在这里尝试做的唯一事情就是阻止用户将状态作为另一个用户发布。
用户has_many :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])
现在我们正在为我们的用户模型使用Devise,因此当前用户由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吗?
答案 0 :(得分:2)
诀窍是,current_user.statuses
不返回数组。当然它看起来像一个数组,如果你尝试current_user.statuses.class
,它甚至会告诉你它是一个数组,但是在它被懒惰评估之后。 实际返回的是ActiveRecord::Relation
对象,您可以通过在rails控制台中尝试current_user.statuses.foo
来自行确认;你会得到像undefined method 'foo' for #<ActiveRecord::Relation:0x007fba7d603918>
这样的消息。 ActiveRecord :: Relation是ActiveRecord的一个非常有用的部分,它在你将对象链接在一起时为你管理范围,并且在你要求的东西不是另一个ActiveRecord :: Relation时,它实际上不会对数据库执行查询。 p>
Ryan Bates在Railscast中对此进行了相当好的解释,这里有一篇讨论ActiveRecord::Relation vs. Arel的博客,其中也讨论了这一点。