【问题标题】:Rails, Drop column from table and delegate it to an associated table and use the delegated column within where clauseRails,从表中删除列并将其委托给关联表并在 where 子句中使用委托列
【发布时间】:2020-04-22 14:33:34
【问题描述】:

我目前正在开发一种产品,出于某些原因,我们决定从特定表中销毁 email 列,然后使用活动记录委托方法将该列委托给关联表

https://apidock.com/rails/Module/delegate

我的问题是关于要遵循什么方法以确保所有使用 email 列的 where 子句也被委托。因为查遍我们用过table.where(dropped_column: value的所有地方基本上都需要很多时间@)

示例

class Station < ActiveRecord::Base
  has_one :contact
  delegate :email, to: :contact
end

class Contact < ActiveRecord::Base
  belongs_to :station
end

我知道可以将所有查询从Station.where(email: value) 切换到Station.joins(:contact).where('contacts.email': value),但是这种方法需要很长时间,而且where 子句可以用多种不同的方式编写,因此搜索代码源并更新所有这些都不足以覆盖所有情况。

如果有人遇到类似情况并设法以节省我们时间和错误的方式解决问题,我将很高兴听到您采用的方法。

谢谢。

Rails 版本:'5.2.3'

【问题讨论】:

    标签: ruby-on-rails ruby activerecord rails-migrations ruby-on-rails-5.2


    【解决方案1】:

    为了确保所有使用 email 列的 where 子句也被委派,要遵循什么方法

    您不能“委托”SQL 命令。您需要全部更新。

    我知道可以将所有查询从Station.where(email: value) 切换到Station.joins(:contact).where('contacts.email': value),但这种方法需要很长时间

    是的,这就是你需要做的,抱歉!

    如果有人遇到类似情况并设法以节省我们时间和错误的方式解决,我将很高兴听到您遵循的方法。

    在删除列之前,您可以先这样做:

    class Station < ActiveRecord::Base
      self.ignored_columns = ['email']
    
      has_one :contact
      delegate :email, to: :contact
    
      # ...
    end
    

    这样,您可以阻止应用程序访问该列,而无需从数据库中实际删除它(如“软删除”),这样可以很容易地恢复。

    在分支上执行此操作,并将所有规格设为绿色。 (如果你有很好的测试覆盖率,你就完成了!但如果你的覆盖率很差,部署后可能会出现错误......)

    如果在部署后出现问题,您可以恢复整个 PR,或者在推送修复时暂时再次注释掉 ignored_columns。

    最后,一旦您的应用程序运行顺利且没有错误,请删除该列。

    【讨论】:

    • 这是有效的,因为 rails 不会(除非您执行原始 SQL!)通过 select * from table_name 获取数据;相反,它总是像select table_name.col1, table_name.col2, table_name.col3 from table_name 一样明确声明每一列。因此,如果您告诉 rails 显式 ignore 列,那么任何引用该列的 SQL 查询都会失败。
    • 忽略该列是在删除之前软删除它的好方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多