Search code examples
rubysqlitesequel

Using a model for an association results in no PK error


My application has the concept of Users, Events, and Invitations. A user can be invited to many events, and an event can have many invited users; this relationship has a status attached to to it, which indicates whether the user has accepted the invitation or not.

I'm modeling the invitation by using an Invitation model for the join table between events and users, but I am unable to actually update the join table through the Invitation model assigned to it:

class Event < Sequel::Model
  many_to_many :users, :join_table => :invitations
  one_to_many :invitations
end

class Invitation < Sequel::Model
  many_to_one :user
  many_to_one :event
end

class User < Sequel::Model
  many_to_many :events, :join_table => :invitations
  one_to_many :invitations

  def invite (user, event)
    user.add_invitation(event: event)
  end

  def decline(event)
    i = Invitation.where(user: self, event: event).first
    i.update(status: "declined")
  end
end

user_one = User.create(name: "foo")
user_two = User.create(name: "bar")
event = Event.create(title: "fete")

user_one.add_event(event)
user_one.invite(user_two, event)

user_two.invitations
# [#<Invitation @values={:id=>nil, :status=>"pending", :event_id=>1, :user_id=>2}>]
# id is nil, which probably leads to the error below?

user_two.decline(event)
# `pk': No primary key is associated with this model (Sequel::Error)`

Edit: my table creation code:

DB.create_table :users do
  primary_key :id
  string :name

  foreign_key :event_id
end

DB.create_table :events do
  primary_key :id
  string :title

  foreign_key :owner_id
  foreign_key :user_id
end

DB.create_table :invitations do
  primay_key :id
  string :status, :default => "pending"
  foreign_key :event_id, :events
  foreign_key :user_id, :users
end

Solution

  • You've got a typo in your table creation code:

    DB.create_table :invitations do
      primay_key :id # <= should be primary_key
    

    I get the same error as you do when I introduce this typo into my code.