Rails:如何检查用户之前是否已将针脚标记?

时间:2014-05-27 22:04:32

标签: ruby-on-rails ruby

在我的应用中,我有针脚(帖子),用户和书签。每个用户都可以为帖子添加书签以供以后阅读这一切都很有效。

但是,如果用户之前已经在所有引脚的列表中为引脚添加了书签,我仍然不知道如何显示?对于列表中的每个引脚,我想在我的视图中检查它们是否已将其加入书签。

pin.rb(型号)

class Pin < ActiveRecord::Base

    belongs_to :user
    has_many :bookmarks, dependent: :destroy

end

user.rb(型号)

class User < ActiveRecord::Base

    has_many :pins, dependent: :destroy
    has_many :bookmarks, through: :pins, dependent: :destroy

end

bookmark.rb(型号)

class Bookmark < ActiveRecord::Base

    belongs_to :user
    belongs_to :pin

    validates :pin_id, uniqueness: { scope: :user_id, :message => "has already been bookmarked" }

end

用户可以为pin添加书签,这会在书签表中创建单个记录。书签表存储user_idpin_id

如果用户已经为某个引脚添加了书签,那么我对如何检查视图有一点大脑。我基本上只想向用户显示是或否标志。

非常感谢任何指导或建议。

谢谢, 迈克尔。

更新:

我最终修改了Lucas的anser。在我的Pin模型中,我定义了一个布尔方法:

def bookmarked_by?(user)
    return true if bookmarks.any? {|b| b.user == user }
end

...如果任何书签属于此引脚上的给定用户,则返回true。似乎工作正常,但欢迎任何其他改进。

3 个答案:

答案 0 :(得分:2)

我建议您在查询Pin时,添加与当前用户关联的Bookmark。然后检查Pin是否有任何书签。

pins = Pin.includes(:bookmarks).where("bookmarks.user_id" => current_user.id)

现在,在循环使用这些pins进行查看时,请检查pin.bookmarks.length是否为0或更多。在此基础上,您可以查看是或否。

<% pins.each do |p| %>
  <%= "yes" if p.bookmarks.length > 0 %>
<% end %>

答案 1 :(得分:1)

我会做什么,稍微建立一下@Tamer的答案是在Pin模型上创建一个方法:

class Pin < ActiveRecord::Base
  # ...
  def bookmarked?
    !bookmarks.empty?    
  end
end

然后你可以在视图中执行此操作:

<% pins.each do |p| %>
  <%= "yes" if p.bookmarked? %>
<% end %>

这个的主要原因是它封装了逻辑,用于理解是否有东西被关注到关注该信息的东西,即引脚。它还使逻辑远离视图,这对于清晰和可维护的视图非常重要。

例如,如果您想要检查并将引脚显示为仅的书签如果当前用户为其添加书签,则可以执行以下操作:

class Pin < ActiveRecord::Base
  # ...
  def bookmarked_by?(user)
    return false unless bookmarked?

    bookmarks.any? {|b| b.user == user }
  end    
end

我不喜欢bookmarks.any?调用,因为我认为它会导致另一个数据库查询,而且我认为有一种更好的方法可以做到这一点,我不确定。我找到它后会更新。

但是,在视图中,您现在可以执行以下操作:

<% pins.each do |p| %>
  <%= "yes" if p.bookmarked_by? current_user %>
<% end %>

更新

提供了一种非常有效的方法,可以将查询提取到COUNT个查询中:

class Pin < ActiveRecord::Base
  def bookmarked_by?(user)
    bookmarks.for_user(user).any?
  end
end

class Bookmark < ActiveRecord::Base
  scope :for_user, ->(user) { where(user: user) }
end


pins = Pin.includes(:bookmarks) # ... any additional conditions

<% pins.each do |pin| %>
    <%= 'yes' if pin.bookmarked_by? current_user %>
<% end %>

使用@pdobb:How does Rails handle a has_many when query uses includes?

的精彩回答,查看我在此发布的问题

答案 2 :(得分:-1)

也许这个?

<%= "yes" if Bookmark.where(pin_id: pin.id, user_id: current_user.id).first %>

制作辅助方法或者Pin类方法可能更干净

class Pin
  def bookmarked?(user)
   !!Bookmark.where(pin_id: id, user_id: user.id).first
  end
  ...

在视图中......

<%= "yes" if pin.bookmarked?(current_user) %>