我有一个has_many
主题的群组模型。
主题模型has_many
帖子,我的用户模型只读帖子等。
我还有一个users_posts模型,用于跟踪用户是否已阅读帖子
以及他们是否喜欢'帖子,它有:group_id,:user_id和:read和:likes boolean fields。
用户创建一个组并在不同主题下添加帖子。
小组表明行动是;
@posts = Group.topics.includes(:posts)
我的问题是何时以及如何将记录添加到users_posts表? 是否应该在首次创建帖子时? 或仅在用户第一次查看帖子时?
将user_posts中的属性添加到@posts中的每条记录的最佳方法是什么? 在我使用虚拟属性的那一刻,这是正确的方法吗?
class Post < ActiveRecord::Base
belongs_to :topic
has_many :users, through: :user_entries
attr_accessor :read, :liked
答案 0 :(得分:2)
<强> ID 强>
首先,您不需要在:group_id
模型/表格中使用user_posts
Rails和关系数据库使用primary keys
为元素提供唯一ID。这意味着无论post
是否是group
的成员,您仍然会使用post_id
foreign key -
#users_posts
id | user_id | post_id | read | updated | created_at | updated_at
-
<强>属性强>
将
中的每条记录user_posts
的属性添加到@posts
执行此操作的方法是将user_posts
与User
和Post
模型相关联 -
#app/models/user.rb
Class User < ActiveRecord::Base
has_many :user_posts
has_many :posts, through: :user_posts
end
#app/models/post.rb
Class Post < ActiveRecord::Base
has_many :user_posts
has_many :users, through: :user_posts
end
这样您就可以拨打@user.posts
如果您想为每个post
关联对象附加额外的属性,您需要使用ALIAS SQL join或ActiveRecord Association Extension
:
#app/models/post.rb
Class User < ActiveRecord::Base
has_many :user_posts
has_many :posts, through: :user_posts, extend: PostUser
end
#app/models/concerns/post_user.rb
module PostUser
#Load
def load
reads.each do |caption|
proxy_association.target << read
end
end
#Private
private
#Attributes
def captions
return_array = []
through_collection.each_with_index do |through,i|
associate = through.send(reflection_name)
associate.assign_attributes({read: items[i]}) if items[i].present?
return_array.concat Array.new(1).fill( associate )
end
return_array
end
#######################
# Variables #
#######################
#Association
def reflection_name
proxy_association.source_reflection.name
end
#Foreign Key
def through_source_key
proxy_association.reflection.source_reflection.foreign_key
end
#Primary Key
def through_primary_key
proxy_association.reflection.through_reflection.active_record_primary_key
end
#Through Name
def through_name
proxy_association.reflection.through_reflection.name
end
#Through
def through_collection
proxy_association.owner.send through_name
end
#Captions
def items
through_collection.map(&:read)
end
#Target
def target_collection
#load_target
proxy_association.target
end
end
-
<强>系统强>
底线是我认为你的系统最好这样运行:
1. Set up a semi-persistent data store to track user / post reads (REDIS)
2. Every time you call a `Post`, you'll be able to call the associated `REDIS` references for it
这将使您能够创建一个首先是模块化的系统,但您也可以创建一个实例方法来确定用户是否已阅读帖子,如下所示:
#app/models/post.rb
Class Post < ActiveRecord::Base
def read?
##Redis lookup for user with post - if "read" attribute is true, return true
end
def liked?
##Redis lookup for user with post - if "liked" attribute is true, return true
end
end
这将允许您运行@user.posts.first.read?