在Rails中显示未读帖子

时间:2014-12-28 22:39:11

标签: ruby-on-rails ruby ruby-on-rails-4

免责声明:我是一个完整的Rails n00b。

我需要向论坛用户展示一些帖子,其中一些可能是“未读”。通过未读,我的意思是帖子有一个更新的:updated_at时间戳,而不是该帖子的用户的最后一个视图时间戳。我无法找到最佳方法 - 未读帖子显然对每个用户都是唯一的。

我尝试使用'未读'的宝石,但文档超出了我的理解,我无法让它工作(我甚至不确定它是否按照我的意愿去做)。

最糟糕的Rails-y方式是什么?

我正在使用Rails 4.1.6

我目前有一个用户模型和一个帖子模型:

class User
    has_many :posts
end

class Post
    belongs_to :user
end

请参阅下面的修改。


编辑1:

我尝试按照下面添加一个Look模型的例子,我认为我更接近一个解决方案(尽管不是那里的所有方式)。这是我做的:

1)rails g model Look post:references user:references + rake db:migrate。这显然产生了所需的模型:

class Look  
    belongs_to :post  
    belongs_to :user  
end

2)编辑我的用户和帖子模型:

class User  
  has_many :posts, through: :looks  
  has_many :looks  
end

class Post  
  belongs_to :user  
  has_many :looks  
  has_many :users, through: :looks  
end

3)进入rails console

user1 = User.first

post1 = Post.first
post2 = Post.last

look = Look.create(user: user1, post: post1)
look = Look.create(user: user1, post: post2)

4)我现在试图吐出结果:

seen = user1.posts
seen.map(&:title)

这很好用,它给了我user1看过这两个帖子的结果。

5)然后我尝试吐出所见帖子的ID:

ids = Look.where(user: user1).pluck(:post_id)

这也很好,我得到了一个看到的帖子ID => [2, 30]

的地图

6)然后,我设法通过在.uniq

末尾添加User.first.posts.map(&:id).uniq来解决重复的ID问题

7)这是我被卡住的地方!

应用has_many :posts, through: :looks会破坏用户与帖子之间的当前关系(创建帖子时不包含user_id)。这是我的PostsController:

def create
  @post = current_user.posts.build(post_params)

  if @post.save
    redirect_to @post
  else
    render 'new'
  end
end

private

def post_params
  params.require(:post).permit(:title, :content, :sticky, :ama_post, :post_url)
end

这是最后一道障碍。我只需要确保在创建帖子时包含user_id。

2 个答案:

答案 0 :(得分:4)

假设您有一个包含许多用户和许多帖子的典型设置,并且您想要跟踪是否有任何用户查看了任何帖子,那么您需要使用加入特定用户的第三个模型来关联用户和帖子到一个特定的职位。

从Rails指南开始:http://guides.rubyonrails.org/association_basics.html

示例模型:

class User < ActiveRecord::Base
  has_many :looks
  has_many :posts, through: looks
end

class Post < ActiveRecord::Base
  has_many :looks
  has_many :users, through: looks
end

class Look < ActiveRecord::Base
  belongs_to :user
  belongs_to :post
end

让我们使用rails控制台设置一些示例数据:

alice = User.create(name: "Alice")

post1 = Post.create(name: "Post 1")
post2 = Post.create(name: "Post 2")
post3 = Post.create(name: "Post 3")
post4 = Post.create(name: "Post 4")

look = Look.create(user: alice, post: post1)
look = Look.create(user: alice, post: post2)

查找用户看过的帖子:

seen = alice.posts
seen.map(&:name)
=> ["Post 1", "Post 2"]

要查找用户看到的帖子:

ids = seen.map(&:id)
unseen = Post.where("id not in (?)", ids)
unseen.map(&:name)
=> ["Post 3", "Post 4"]

这是获取所需记录的简单方法。

使用后,有更好的方法可以使用查询优化来获取记录。

例如,您只需获取ID号就可以检索更少的数据。以下是几种方法。

# Basic: traverses two joins, then loads all columns
ids = Post.joins(:looks => :user).where("users.id = ?", alice.id).map(&:id)

# Faster: traverses two joins, then loads one column
ids = Post.joins(:looks => :user).where("users.id = ?", alice.id).pluck(:id)

# Fastest: no joins, and only loads one column
ids = Look.where(user: alice).pluck(:post_id)

请查看unread gem以获取指导和示例代码。

答案 1 :(得分:1)

您可能需要某种历史记录。它可以记录单个实例,也可以仅记录对论坛的最新访问。

这是一个假设情景:

  • 您的论坛只有一个论坛组。
  • 您拥有每个用户的用户模型。
  • 您有一个包含单个主题的主题/主题模型,其has_many关系为:
  • Post模型,其中包含由特定用户撰写的特定帖子(与答案无关,但与方案的一部分无关)
  • 您的论坛有一个主题控制器,分配了标准的RESTful资源路由。

您要做的是从阅读主题中分离/突出显示/指定未读主题,对吧?打破这种局面,你需要:

  1. 弄清楚用户上次访问论坛的索引页面。
  2. 获取主题列表。
  3. 在呈现列表中的每个主题时,确定主题是否更多&#34;最近&#34;而不是用户的最后一次访问。无论是在上次访问后创建的,还是在上次访问后发布的帖子。
  4. 根据您的要求以不同方式(或其他)呈现它。
  5. 将其变成一个非常简单的实现,你会:

    • 添加&#34;最后一次索引访问&#34;归属于用户。
    • 访问索引时加载该值。
    • 相应地渲染主题。
    • 更新当前用户的最后一个索引访问属性(最好实现为after_action)

    现在,这个实现假定您只想在一个地方跟踪它,并且可以使用与该选择相关的限制(阅读单个主题并将其标记为已读)。

    如果您愿意,可以通过创建属于用户和主题的表来消除该限制,然后在用户“读取”表时更新该表。主题(取决于您是希望他们查看主题还是仅在索引中查看主题)。

    修改

    要最终回答这个问题,您需要将其细分为更多细节。 &#34;识别未读主题&#34;意味着你需要回答:

    • 我什么时候考虑阅读主题?当我查看个别帖子时,它是否是新的&#39;?是否在列表中的主题是&#39; new&#39;?
    • 之后
    • 我认为新的/更新的主题是什么?这是它第一次发布的时候吗?如果有人发帖回复会怎么样?

    编辑2

    然后我要做以下事情:

    • 向帖子模型与主题的关联添加touch: true语句,以确保每当发布/编辑其他帖子时,都会修改主题的updated_at属性。
    • 创建一个视图助手方法,以确定当前用户的最后一次阅读(如果有的话)是否晚于主题的updated_at时间戳。
    • 仅在after_action创建一个Posts#show,为该用户创建/更新阅读权限&amp;主题。