【问题标题】:Rails 4 - Mapping a model dynamically on two different database tablesRails 4 - 在两个不同的数据库表上动态映射模型
【发布时间】:2015-07-30 07:31:21
【问题描述】:

我有一个多域应用程序与旧数据库通信。 在那个数据库中,我有两个不同名称的表,我们称它们为USER_AUSER_B。它们的结构和数据类型完全一样,唯一的区别是它们的数据来自不同的域。

现在,我想要一个 single scaffold (model/controller/view),它根据域映射到正确的数据库表。

域 A 将与名为 User 的模型/控制器一起工作,该模型/控制器在内部映射到数据库表 USER_A,而域 B 将与相同的模型/控制器 User 一起工作,但映射到表 USER_B

我还想在我的路线中使用resource :user 以通过rails 方式访问模型。

所以我需要在初始化时覆盖模型,但我不太确定如何去做。

如何使用 Rails ActiveRecord 来解决这个问题?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 model-view-controller rails-activerecord ruby-on-rails-4.2


    【解决方案1】:

    我没有准备好测试的多表数据库,所以这是对解决方案的有根据的猜测:

    # respective models
    class User < ActiveRecord::Base
    end
    
    class DomainAUser < User
      self.table_name = "USER_A"
    end
    
    class DomainBUser < User
      self.table_name = "USER_B"
    end
    
    # controller
    def set_user
      @user = if request.subdomain(0) == "DomainA" 
                DomainAUser.find(params[:id])
              else 
                DomainBUser.find(params[:id])
              end
    end
    

    编辑:这是另一种元编程hackery,它在父类本身内进行子类实例化。测试和工作。

    我真的不想维护这样的东西。

    # model
    class User < ActiveRecord::Base
      def self.for_domain(domain_suffix)
        class_eval "class DomainUser < User; self.table_name='user_#{domain_suffix}'; end"
        "User::DomainUser".constantize
      end
    end
    
    # controller
    User.for_domain("a").new
    

    【讨论】:

    • 这样做你不需要 User 类。目前正在这样做,但它不是很干......
    • @mahatmanich:子类中唯一的应该是self.table_name 调用。所有验证/关系/等都应该进入父User 类。您如何认为它是非 DRY 的?
    • 我想要完成的是将一个模型、一个控制器映射为路由中的资源。有点像伪 MTI,因为我确实应该使用 STI,但我不能更改数据库结构。
    • @mahatmanich:不要认为在初始化之后定义table_name 是可能的,所以这里有一个替代方案,它可以在模型本身中完成。不过会推荐第一种方法。
    • 感谢您抽出宝贵时间提供帮助。目前,我实际上正在尝试让您的第一个建议发挥作用,看看效果如何。
    猜你喜欢
    • 1970-01-01
    • 2021-10-23
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    • 2012-10-28
    • 2015-05-14
    相关资源
    最近更新 更多