Reputation: 29251
I have two sequel models user
and event
, which is currently handled by a single join table.
Users can be invited to events, and these invitations have a status attached to them; this is handled by another join table.
class Event < Sequel::Model(:events)
many_to_many :users
many_to_many :invitations, :join_table => :events_invitations, :right_key => :user_id, :class => :User, :select=>[Sequel.expr(:users).*, :events_invitations__status]
end
class User < Sequel::Model(:users)
many_to_many :events
many_to_many :invitations, :join_table => :events_invitations, :right_key => :event_id, :class => :Event, :select=>[Sequel.expr(:events).*, :events_invitations__status]
end
I am able to create and access the associated invitations, but the changes are never saved (i'm assuming due to the way i've set up the many_to_many)
user = User.create(name: "bob")
event = Event.create(title: "super fete")
user.add_event(e)
event.add_invitation(e)
invite = user.invitations.first
# this returns a reference to the event, with the extra status column from the join table
# <Event @values={:id=>1, :title=>"fete", :owner_id=>nil, :user_id=>nil, :status=>"pending"}>
# does not actually save back to the table if I modify it...
invite[:status] = "accepted"
How should I model this so as to be able to see and set the status of invitations for users and events?
Upvotes: 1
Views: 84
Reputation: 303321
First, some (ultimately unhelpful) basics.
Sequel is letting you treat the model like a hash, insofar as you can store extra read-only values on it. However, as with Sequel's hashes returned from a dataset, just setting the key does not update it. For example:
bob = DB[:users][name:'Bob'] #=> {:id=>1, :name=>"Bob"}
bob[:name] = 'Mary'
p bob #=> {:id=>1, :name=>"Mary"}
p DB[:users][1] #=> {:id=>1, :name=>"Bob"}
This is true for Model instances as well:
bob = User[name:'Bob'] #=> #<User @values={:id=>1, :name=>"Bob"}>
bob[:name] = 'Mary'
p bob #=> #<User @values={:id=>1, :name=>"Mary"}>
p User[1] #=> #<User @values={:id=>1, :name=>"Bob"}>
bob.name = 'Jerome'
p bob #=> #<User @values={:id=>1, :name=>"Jerome"}>
p User[1] #=> #<User @values={:id=>1, :name=>"Bob"}>
For the Dataset, you need to update
your dataset to change values in the database.
For the Model, you need to either update the values as above and then save
your changes to that model instance (e.g. bob.save
) or you need to use your instances to update
it with new values (e.g. bob.update name:'Mary'
).
But really, you are abusing the many_to_many
class
and select
values to make a thing that looks like an Event
, but which is not. If 20 people are invited to the fête, it's incorrect to have 20 different "events" all named "super fete" but with differing status. Those aren't events, those are invitations.
You want an Invitation
model to represent your join, associated with the join table. Then you can get an instance that has a status
, and you can update
it as you like. You can't update
from the Event
instance because it doesn't know anything about the events_invitations
table or the status
column, other than to fetch them when asked.
Upvotes: 1