【问题标题】:Combining records from 2 tables into 1 ActiveRecord model将 2 个表中的记录组合成 1 个 ActiveRecord 模型
【发布时间】:2021-09-30 16:35:53
【问题描述】:

我正在寻找有关如何处理以下问题的建议。可能有设计模式或 Rails 方式来处理这个问题。

问题

我目前有一个用于 legacy_posts 的表格和模型。 legacy_posts 表中存储了几种不同类型的帖子。它不是真正可扩展的,也不适合目的,所以我正在从这个设置中迁移出来。

我将使用一个名为帖子的新表格和模型。我必须逐一迁移每种帖子类型,而不会影响最终用户。 我没有选择,必须一次完成一种帖子类型。最终用户在迁移时不应注意到任何差异。

我遇到麻烦的地方是我的 legacy_posts 和 posts 表的索引页面。到目前为止,仅使用 legacy_notes 表,使用 ActiveRecord 显示、分页和排序我的数据是微不足道的。但是,现在我需要在此页面上同时列出帖子和 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

这对我来说很好,但感觉很hacky。我想知道是否有更好的方法来解决这个问题,或者是否有可以使用的模式?

【问题讨论】:

  • 我不认为它真的那么 hacky。你有一个不寻常的情况,你需要两个表的联合,我可能会做同样的事情。您可以做些什么来清理它是使用 Arel 创建联合,而不是使用插值创建 SQL 字符串。

标签: ruby-on-rails activerecord refactoring


【解决方案1】:

我认为创建数据库视图将是最简洁的解决方案。您可以通过创建一个新的迁移并执行类似的操作来做到这一点。

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.....

阅读:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 2016-10-19
    • 1970-01-01
    相关资源
    最近更新 更多