egyamado
egyamado

Reputation: 1121

Which relationship is good to use STI or Polymorphism?

I have read about them but still not clear to me which one I suppose to use and how. I have User model, Message model and Place model

Message model:

class Message < ActiveRecord::Base
    belongs_to :user
end

Messages Table:

create_table "messages", force: true do |t|
  t.string   "title"
  t.integer  "user_id"
  t.datetime "created_at"
  t.datetime "updated_at"
end

User model:

class User < ActiveRecord::Base
    has_many :messages
end

Users Table:

create_table "users", force: true do |t|
  t.string   "email"
  t.string   "password_digest"
  t.datetime "created_at"
  t.datetime "updated_at"
  t.string   "username"
end

Now, what I want to do is: "USER" says "MESSAGES" from "PLACES"

eg. "AHMED" says "HELLO" from "EARTH"

For me both Models (Message and Place) have same data (data type) and same behaviours. So places table should be:

create_table "places", force: true do |t|
  t.string   "name"
  t.integer  "user_id"
  t.datetime "created_at"
  t.datetime "updated_at"
end

Now may be I'm confused or making big deal than it should be.

What kind of relation should Message and Place have? should it be STI or Polymorphism? How should I decide?

I'd appreciate the thinking process of how and why I decide specific association.

Upvotes: 0

Views: 80

Answers (1)

wacko
wacko

Reputation: 3424

This example, despite Messages and Places having the same data, doesn't seems a STI/Polymorphism scenario and they should have two different tables.

This could work as a solution:

create_table "users" do |t|
  t.string   "username"
end
create_table "messages" do |t|
  t.string   "text"
  t.integer  "user_id"
  t.integer  "place_id"
end
create_table "places" do |t|
  t.string   "name"
end

class User < ActiveRecord::Base
  has_many :messages
  has_many :places, through: :messages
end

class Place < ActiveRecord::Base
end

class Message < ActiveRecord::Base
  belongs_to :user
  belongs_to :place
  def to_s
    "#{user.username} says #{title} from #{place.name}"
  end
end

ahmed = User.new(username: "AHMED")
earth = Place.new(name: "EARTH")
message = Message.new(text: "HELLO", user: ahmed, place: earth)
puts message
# => "AHMED says HELLO from EARTH"

Upvotes: 1

Related Questions