因此,其中三分之二有效。每次用户阅读文章时,都会创建一个历史记录(has_many through),它只是说"用户在Read_Date_X"阅读文章。
数据库没问题,模型没问题,历史记录控制器允许使用read_date参数,以下操作同时工作1)检查用户之前是否读过文章和2)创建新的历史记录如果这是第一次在这篇文章上。
但我无法弄清楚为什么中间位(只是更新现有记录上的read_date)不起作用。如果我用h.save尝试它并不重要!或者h.update()。
h = History.where(article_id: @article, user_id: current_user)
if h.exists?
h = History.where(article_id: @article, user_id: current_user)
h.read_date = Time.now
h.save!
else
h = History.new
h.article_id = @article.id
h.user_id = current_user.id
h.read_date = Time.now
h.save!
end
如果找到现有记录,则抛出的错误是:
undefined method `read_date=' for #<History::ActiveRecord_Relation:0x007fe7f30a5e50>
更新:工作回答
所以Derek是对的,这个版本有效。中间位需要单个实例,而不是数组,这是顶级条件(没有.first)检查的内容。但是,使用它来返回单个记录意味着你需要交换&#34;存在?&#34;到&#34;出席?&#34;在第二部分。
h = History.where(article_id: @article, user_id: current_user).first
if h.present?
h.read_date = Time.now
h.save!
else
h = History.new
h.article_id = @article.id
h.user_id = current_user.id
h.read_date = Time.now
h.save!
end
答案 0 :(得分:1)
History.where(article_id: @article, user_id: current_user)
正在返回History::ActiveRecord_Relation
。如果你想设置read_date,你想要获得一条记录。
这是您使用目前所拥有的一种方式:
h = History.where(article_id: @article, user_id: current_user).first
另一种可以处理此问题的方法是使用find_by
代替where
。这将返回单个记录。像这样:
h = History.find_by(article_id: @article, user_id: current_user)
但是,如果用户有可能拥有很多文章的历史记录,我会坚持你做事的方式并做出改变。如果由于某种原因你有很多历史记录,那么这可能不是很有效。
histories = History.where(article_id: @article, user_id: current_user)
histories.each { |history| history.update(read_date: Time.now) }
答案 1 :(得分:1)
我意识到这个问题已经回答了。以下是一些额外的想法和建议。
我没有单独的read_date
属性。只需使用updated_at
代替。它已经在你身边了。而且,代码的工作方式,read_date
和updated_at
将始终(基本上)相同。
在查看历史记录是否存在时,您可以执行current_user.histories.where(article: @article)
。 IMO,似乎比History.where(article_id: @article, user_id: current_user).first
更清晰。
只需检查exists?
分配是否成功,即可避免所有present?
和h
业务。因此,if h = current_user.histories.where(article: @article)
。
如果您选择使用updated_at
代替read_date
,则只需执行updated_at
即可将Time.now
设置为h.touch
。
我会使用<<
提供的has_many :through
方法(而不是手动构建history
记录)。同样,如果您使用updated_at
代替read_date
,则可以使用此方法。
因此,您可以将代码简化为:
if h = current_user.histories.where(article: @article)
h.touch
else
current_user.articles << @article
end
你可以使用三元运算符而不是if then else
,在这种情况下它可能看起来像:
current_user.histories.where(article: @article).tap do |h|
h ? h.touch : current_user.articles << @article
end