当外键存储在元数据

时间:2017-08-03 22:25:45

标签: ruby-on-rails activerecord

在Rails 4应用程序中,我有一个STI模型,它将元数据存储在jsonb列中。

基类:

class Post < ActiveRecord::Base
  ...
end

子类:

class JobPost < Post
  # has a jsonb column for metadata
end

JobPost的元数据列中的一个数据属性是对另一个表(company_id)的foreign_key引用。我想在JobPost模型中添加belongs_to :company引用。这似乎应该可以通过做

这样的事情来实现
class JobPost < Post
  belongs_to :company do
    Company.find_by_id self.metadata['company_id']
  end
end

但这似乎不起作用。帮助

注意:我不一定打算使用belongs_to而不是手动编写def company所需的方法,但我确实需要一种方法来在列出职位时急切加载公司。如果有一种方法可以在没有belongs_to关系的情况下进行那种热切的加载,我就会全力以赴。

UPDATE1

我也尝试了以下内容,但似乎无效:

class JobPost < Post
  belongs_to :company, foreign_key: "(posts.metadata->>'company_id')::integer".to_sym
end

UPDATE2

更清楚我的意图和需要:

1)一个公司的JobPost belongs_to,但是Post(和Post的其他子类)没有。当其他子类不使用时,我宁愿不要将company_id列添加到posts表中。

2)JobPost可以证明拥有自己的桌子(也许与公司的关系足以证明它的合理性)。有理由说这不是理想的,但如果这是唯一的答案,我会接受它。然而,在走上这条道路之前,我会更喜欢一个更明确的“你要做的事情无法做到”的回应。

主要问题是您是否可以自定义belongs_to以便它使用元数据列而不是期望外键成为表中的列。

第二个问题是,在没有建立belongs_to关系的情况下,您是否可以将公司加入公司和工作岗位。

1 个答案:

答案 0 :(得分:1)

修改

UPD 2

您需要添加&#34; company_id&#34;列到STI表的基类。如果JobPost继承自Post,它应该有&#34; company_id&#34;然后添加&#34; company_id&#34;列到帖子(基表)。

记住STI代表&#34;单表继承&#34;所以在数据库模式级别上只有一个表。想象一下Post表的一列,其中很少有数据记录是具有company_id的公司的外键条目,以及具有非JobPost子类类型的该列的其他记录,它们是空/空吗?因此,关系是使用父STI表定义的,子类继承了这些关系。 STI中的附加类型列定义子类类型。

检查here

如果JobPost和Post都与公司有关系,您可能需要进一步挖掘Polymorphic classes而不是STI,否则创建两个单独的模型,因为它们往往有一些独特的关系和列字段。

<强> UPD

基于更新的问题

  1. 应用程序/模型/ company.rb
  2. &#13;
    &#13;
    class Company < ActiveRecord::Base 
        has_many :posts 
        delegate :jobposts, to: :posts
    end
    &#13;
    &#13;
    &#13;

    1. 应用程序/模型/ post.rb
    2. &#13;
      &#13;
      class Post < ActiveRecord::Base 
          belongs_to :company 
          self.inheritance_column = :ptype 
      
          scope :job_posts, -> { where(ptype: 'JobPost') } 
      
          def self.ptype
            %w(JobPost)
          end
      
      end
      &#13;
      &#13;
      &#13;

      1. app / models / jobpost.rb
      2. &#13;
        &#13;
        class JobPost < Post; end
        &#13;
        &#13;
        &#13;

        1. 创建公司
        2. &#13;
          &#13;
          company = Company.create!(company_params)
          &#13;
          &#13;
          &#13;

          1. 创建一些帖子并将其添加到公司
          2. &#13;
            &#13;
            company.posts << JobPost.new(jobpost_params)
            &#13;
            &#13;
            &#13;

            1. 按公司关系取得职位
            2. &#13;
              &#13;
              company.job_posts
              &#13;
              &#13;
              &#13;

              如果你将jonb中的company_id存储在任何哪一列中,只需相应地格式化你的jobpost_params哈希输入,它应该为你做契约

              OLD ASK

              按主键查找

              Company.find(id)
              

              在您的情况下,ID为self.metadata [&#39; company_id&#39;]

              通过其他键找到

              Company.find_by(key: value)
              

              不再推荐使用Company.find_by_id

              请删除你的模型中的belongs_to之后的do和end,而不是在你的控制器中你可以写:

              Jobpost.all.each do |x|
                  # your do
              end
              

              关于外键,因为rails是约定优于配置,它默认包含对Jobpost的company_id引用,您可以在Company.rb模型中更改