免责声明:我是一个完整的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。
答案 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)
您可能需要某种历史记录。它可以记录单个实例,也可以仅记录对论坛的最新访问。
这是一个假设情景:
您要做的是从阅读主题中分离/突出显示/指定未读主题,对吧?打破这种局面,你需要:
将其变成一个非常简单的实现,你会:
现在,这个实现假定您只想在一个地方跟踪它,并且可以使用与该选择相关的限制(阅读单个主题并将其标记为已读)。
如果您愿意,可以通过创建属于用户和主题的表来消除该限制,然后在用户“读取”表时更新该表。主题(取决于您是希望他们查看主题还是仅在索引中查看主题)。
要最终回答这个问题,您需要将其细分为更多细节。 &#34;识别未读主题&#34;意味着你需要回答:
然后我要做以下事情:
touch: true
语句,以确保每当发布/编辑其他帖子时,都会修改主题的updated_at属性。after_action
创建一个Posts#show
,为该用户创建/更新阅读权限&amp;主题。