我正在寻找如何处理以下问题的一些建议。可能有一个设计模式或rails方法来处理这个问题。
我目前有一个表和模型的legacy_posts。在legacy_posts表中存储了几种不同类型的帖子。它不是真正可伸缩的,也不适合目的,所以我正在从这个设置迁移。
我将使用一个新的称为posts表和模型。我必须一个接一个地迁移每个帖子类型,而不影响最终用户。我没有选择,它必须做一个帖子类型一次。最终用户在迁移时不应该注意到任何差异。
我遇到麻烦的地方是在我的legacy_posts和posts表的索引页上。到目前为止,只有legacy_notes表,用ActiveRecord显示、分页和排序数据是微不足道的。然而,现在我需要在这个页面上列出posts和legacy_posts,我不想有自定义逻辑来处理我的分页,排序等。临时解决方案
我想,如果我做我的帖子和legacy_posts表的UNION连接,然后允许我的legacy_post模型从这里选择,我仍然可以使用ActiveRecord的排序,顺序,分页等。
In legacy_posts controller
def combined_posts
posts = user.posts.select(
:id,
'title as heading'
etc...
)
legacy_posts = user.legacy_posts.all
combined_posts = user.legacy_posts.select('*').from("((#{legacy_posts.to_sql}) UNION (#{posts.to_sql})) AS legacy_posts")
combined_posts.order('posted_at DESC').page(params[:page] || 0).per(params[:items])
end
这对我来说很好,但感觉很粗糙。我想知道是否有更好的方法来解决这个问题,或者是否有一个可以使用的模式?
我认为创建一个数据库视图将是最干净的解决方案。您可以创建一个新的迁移,并执行如下操作。
def up
execute <<-SQL
create view posts_view as
select id, title as heading ... from legacy_posts
union
select id, heading from posts
SQL
end
def down
execute <<-SQL
drop view posts_view
SQL
end
然后用
创建一个模型文件class PostsView < ApplicationRecord
# Not strictly necessary but I like to do this for views
# if you want to update the name later
self.table_name = "posts_view"
# Model is readonly
def readonly?
true
end
end
和其他模型一样使用
PostsView.where(user_id: 1).paginate.....
阅读:- https://www.netguru.com/blog/database-views-and-how-to-use-them-in-a-ror-based-app
- https://github.com/scenic-views/scenic