voormedia / rails-erd

Generate Entity-Relationship Diagrams for Rails applications
http://voormedia.github.io/rails-erd/
MIT License
4k stars 367 forks source link

ERD doesn't display foreign keys #359

Open kurt-mueller-osumc opened 4 years ago

kurt-mueller-osumc commented 4 years ago

I have a foreign key specified in the database that isn't reflected when I create an er diagram.

ActiveRecord::Schema.define(version: 2020_09_09_163334) do

  # These are extensions that must be enabled in order to support this database
  enable_extension "pgcrypto"
  enable_extension "plpgsql"

  create_table "patients", id: false, force: :cascade do |t|
    t.integer "mrn", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["mrn"], name: "index_patients_on_mrn", unique: true
  end

  create_table "samples", id: false, force: :cascade do |t|
    t.string "sample_id", null: false
    t.integer "patient_mrn", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["sample_id"], name: "index_samples_on_sample_id", unique: true
  end

  add_foreign_key "samples", "patients", column: "patient_mrn", primary_key: "mrn", name: "key_samples_on_patient_mrn"
end

class Patient < ApplicationRecord
  self.primary_key = :mrn

  has_many :samples,
           primary_key: :mrn,
           foreign_key: :patient_mrn
end

class Sample < ApplicationRecord
  self.primary_key = :sample_id

  belongs_to :patient,
             primary_key: :mrn,
             foreign_key: :patient_mrn
end

The .erdconfig file:

attributes:
  - primary_keys
  - foreign_keys
  - content
  - timestamps
indirect: true
inheritance: false
markup: true
notation: crowsfoot
sort: true
warn: true
exclude: null
only: null
only_recursion_depth: null
splines: spline

The ER Diagram


The gem seems to mark columns as foreign keys only if the column and foreign_key attribute are the default types. Override them and FK won't show up in the er diagram.

kurt-mueller-osumc commented 4 years ago

It seems to be happening here:

# Returns +true+ if this attribute is used as a foreign key for any
# relationship.
def foreign_key?
  @domain.relationships_by_entity_name(@model.name).map(&:associations).flatten.map { |associaton|
    associaton.send(Domain.foreign_key_method_name)
  }.include?(name)
end

I dropped a binding.pry debugging statement into the code:

13] pry(#<RailsERD::Domain::Attribute>)> whereami

From: .../rails-erd-1.6.0/lib/rails_erd/domain/attribute.rb:80 RailsERD::Domain::Attribute#foreign_key?:

    79: def foreign_key?
 => 80:   binding.pry
    81:   @domain.relationships_by_entity_name(@model.name).map(&:associations).flatten.map { |associaton|
    82:     associaton.send(Domain.foreign_key_method_name)
    83:   }.include?(name)
    84: end

[14] pry(#<RailsERD::Domain::Attribute>)> @model.name
=> "Sample"
[15] pry(#<RailsERD::Domain::Attribute>)> name
=> "patient_mrn"
[16] pry(#<RailsERD::Domain::Attribute>)> @domain.relationships_by_entity_name(@model.name).map(&:associations).flatten.map { |associaton|
[16] pry(#<RailsERD::Domain::Attribute>)*   associaton.send(Domain.foreign_key_method_name)          
[16] pry(#<RailsERD::Domain::Attribute>)* }  
=> [:patient_mrn, :patient_mrn, :sample_id]
[17] pry(#<RailsERD::Domain::Attribute>)> _.include?(name)
=> false