Search code examples
ruby-on-rails-4activerecordnamespacesdependent-destroy

Rails model namespacing dependent destroy causes mysql error unknown field


I have several models in a separate folder called jira (instance.rb, generic_field.rb, etc.). They are are all namespaced under JIRA, for example JIRA::Instance < ActiveRecord::Base, JIRA::GenericField < ActiveRecord::Base. Here are the two models:

class JIRA::GenericField < ActiveRecord::Base
  self.table_name = "jira_generic_fields"
  belongs_to :jira_instance, class_name: JIRA::Instance
end


class JIRA::Instance < ActiveRecord::Base
  self.table_name = "jira_instances"
  has_many :jira_generic_fields, dependent: :destroy, class_name: JIRA::GenericField
end

The DB schema for the tables:

create_table "jira_generic_fields", force: true do |t|
  t.string  "jira_id"
  t.string  "name"
  t.integer "jira_instance_id",      null: false
end

create_table "jira_instances", force: true do |t|
  t.string "jira_link"
  t.string "crowd_link"
end

In my rails console i create a JIRA::Instance object and when I try to destroy it I get this:

ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'jira_generic_fields.instance_id' in 'where clause': SELECT `jira_generic_fields`.* FROM `jira_generic_fields`  WHERE `jira_generic_fields`.`instance_id` = 1

Why does ActiveRecord use jira_generic_fields.instance_id instead of jira_generic_fields.jira_instance_id and how can I fix this while keeping the models under the same JIRA namespace?


Solution

  • In the end specifying the foreign_key in the models solved this ...

    class JIRA::GenericField < ActiveRecord::Base
      self.table_name = "jira_generic_fields"
      belongs_to :jira_instance, foreign_key: 'jira_instance_id', class_name: JIRA::Instance
    end
    
    class JIRA::Instance < ActiveRecord::Base
      self.table_name = "jira_instances"
      has_many :jira_generic_fields, dependent: :destroy, foreign_key: 'jira_instance_id', class_name: JIRA::GenericField
    end
    

    I don't really like it but it will have to do for now.