模型关联回调
Model associations callbacks
我想在我的应用程序中添加评论部分。更具体地说,用户可以为商店留下评论,然后商店可以回复该评论。但我不确定模型关联和审查 table 迁移是否正确。
class User < ActiveRecord::Base
has_many :reviews
end
class Review < ActiveRecord::Base
belongs_to :user
end
class ReviewReply < ApplicationRecord
belongs_to :user, optional: true
belongs_to :review, optional: true
end
class Shop < ActiveRecord::Base
has_many :reviews
end
class CreateReviews < ActiveRecord::Migration[6.0]
def change
create_table :reviews do |t|
t.text :body
t.integer :rating
t.references :shop, null: false, foreign_key: true
t.references :user, null: false, foreign_key: true
t.timestamps
end
end
end
在您的迁移中,reviewable
的多态关系设置不正确 - reviewable_type
上的唯一索引将阻止添加多条记录,最好使用
t.references :reviewable, polymorphic: true
在现代 rails 中,它默认在两列上添加非唯一索引(您可以使用 index: true
明确表示,但无论如何这都不同于单独在每一列上添加两个单独的索引)
而且您很可能希望您的唯一索引包含用户 ID,以便每个用户都可以对每个可审核的内容进行一次审核:
t.index [:reviewable_type, :reviewable_id, :user_id], unique: true, name: 'idx_unique_user_review'
同时包含 shop
和 reviewable
的原因尚不清楚,但这取决于您的应用程序和目标。如果商店本身是 reviewable
(如 has_many :reviews, as: :reviewable
所建议)- 那么 shop
参考是无用的。但事实上,如果您不打算扩展对商店以外的其他内容的评论 - 现在使用非多态参考会更容易。
在大型应用程序中,相关事物最好有共同的名称前缀,因此 ReviewReply
模型名称更好。 belongs_to :review
估计不是可选的,什么都不回复很奇怪。而且它很可能有 belongs_to :shop
(也不是可选的)而不是 user
,因为商店是回复的人。
如果它是一个真正的应用程序(= 不仅仅是您正在玩弄的东西),我会更改一些东西:
- 我会从
ReviewReply
中的两个关联中删除 optional: true
,因为如果他们没有作者或没有关联,回复就没有意义(数据方面)评论。
- 我还将
review_replies
中的这两列设置为 null: false
。
- 您应该考虑添加一些删除级联(在模型中添加
dependent: :some_action
或在数据库列上使用 on_delete: :some_action
– 我推荐后者):
- 删除评论时删除评论回复?
- 删除用户后删除评论回复? (或者只是将其设置为
NULL
,然后在 UI 中显示“已删除的用户”?)
- 在删除商店时删除评论?
- 删除用户时删除评论? (或者只是将其设置为
NULL
,然后在 UI 中显示“已删除的用户”?)
架构:
1。计算评分
控制台:
rails g migration add_rating
迁移:
def change
add_column :shops, :average_rating, :integer, default: 0, null: false
add_column :reviews, :rating, :integer, default: 0, null: false
end
user.rb
has_many :reviews
shop.rb
has_many :reviews
def update_rating
if reviews.any? && reviews.where.not(rating: nil).any?
update_column :average_rating, reviews.average(:rating).round(2).to_f
else
update_column :average_rating, 0
end
end
review.rb
belongs_to :user
belongs_to :shop
has_one :review_reply
after_save do
unless rating.nil? || rating.zero?
shop.update_rating
end
end
after_destroy do
shop.update_rating
end
review_reply.rb
belongs_to :review
2。回复评论
views/reviews/show.html.erb:
<% unless @review.review_reply.present? %>
<%= link_to "Write a Reply", new_review_reply_path(review_id: @review.id) %>
<% end %>
views/review_replies/form.html.erb
= f.input :review_id, input_html: {value: params[:review_id]}, as: :hidden
我想在我的应用程序中添加评论部分。更具体地说,用户可以为商店留下评论,然后商店可以回复该评论。但我不确定模型关联和审查 table 迁移是否正确。
class User < ActiveRecord::Base
has_many :reviews
end
class Review < ActiveRecord::Base
belongs_to :user
end
class ReviewReply < ApplicationRecord
belongs_to :user, optional: true
belongs_to :review, optional: true
end
class Shop < ActiveRecord::Base
has_many :reviews
end
class CreateReviews < ActiveRecord::Migration[6.0]
def change
create_table :reviews do |t|
t.text :body
t.integer :rating
t.references :shop, null: false, foreign_key: true
t.references :user, null: false, foreign_key: true
t.timestamps
end
end
end
在您的迁移中,reviewable
的多态关系设置不正确 - reviewable_type
上的唯一索引将阻止添加多条记录,最好使用
t.references :reviewable, polymorphic: true
在现代 rails 中,它默认在两列上添加非唯一索引(您可以使用 index: true
明确表示,但无论如何这都不同于单独在每一列上添加两个单独的索引)
而且您很可能希望您的唯一索引包含用户 ID,以便每个用户都可以对每个可审核的内容进行一次审核:
t.index [:reviewable_type, :reviewable_id, :user_id], unique: true, name: 'idx_unique_user_review'
同时包含 shop
和 reviewable
的原因尚不清楚,但这取决于您的应用程序和目标。如果商店本身是 reviewable
(如 has_many :reviews, as: :reviewable
所建议)- 那么 shop
参考是无用的。但事实上,如果您不打算扩展对商店以外的其他内容的评论 - 现在使用非多态参考会更容易。
在大型应用程序中,相关事物最好有共同的名称前缀,因此 ReviewReply
模型名称更好。 belongs_to :review
估计不是可选的,什么都不回复很奇怪。而且它很可能有 belongs_to :shop
(也不是可选的)而不是 user
,因为商店是回复的人。
如果它是一个真正的应用程序(= 不仅仅是您正在玩弄的东西),我会更改一些东西:
- 我会从
ReviewReply
中的两个关联中删除optional: true
,因为如果他们没有作者或没有关联,回复就没有意义(数据方面)评论。 - 我还将
review_replies
中的这两列设置为null: false
。 - 您应该考虑添加一些删除级联(在模型中添加
dependent: :some_action
或在数据库列上使用on_delete: :some_action
– 我推荐后者):- 删除评论时删除评论回复?
- 删除用户后删除评论回复? (或者只是将其设置为
NULL
,然后在 UI 中显示“已删除的用户”?) - 在删除商店时删除评论?
- 删除用户时删除评论? (或者只是将其设置为
NULL
,然后在 UI 中显示“已删除的用户”?)
架构:
1。计算评分
控制台:
rails g migration add_rating
迁移:
def change
add_column :shops, :average_rating, :integer, default: 0, null: false
add_column :reviews, :rating, :integer, default: 0, null: false
end
user.rb
has_many :reviews
shop.rb
has_many :reviews
def update_rating
if reviews.any? && reviews.where.not(rating: nil).any?
update_column :average_rating, reviews.average(:rating).round(2).to_f
else
update_column :average_rating, 0
end
end
review.rb
belongs_to :user
belongs_to :shop
has_one :review_reply
after_save do
unless rating.nil? || rating.zero?
shop.update_rating
end
end
after_destroy do
shop.update_rating
end
review_reply.rb
belongs_to :review
2。回复评论
views/reviews/show.html.erb:
<% unless @review.review_reply.present? %>
<%= link_to "Write a Reply", new_review_reply_path(review_id: @review.id) %>
<% end %>
views/review_replies/form.html.erb
= f.input :review_id, input_html: {value: params[:review_id]}, as: :hidden