i wonder if the following is possible in Rails (seems like not), and if
not, whether such database structure is discouraged for some good
reason.
I *roughly* want to have
class Payment < ActiveRecord::Base
has_one :purchase
end
where purchase can be either TicketPurchase, or MembershipPurchase, so
to have also
class TicketPurchase < ActiveRecord::Base
belongs_to :payment
end
class MembershipPurchase < ActiveRecord::Base
belongs_to :payment
end
so things need to be polymorphic.
I want this correspond to the following database structure:
payments: id | amount | purchase_type
ticket_purchases: id | number | payment_id
membership_purchases: id | membership_type | payment_id
This does not seem to be possible in Rails, to use polymorphic
associations i would need to store the foreign key in payments table.
Am i right that it is not possible, and is there a good reason for
discouraging such associations?
i wonder if the following is possible in Rails (seems like not), and if
not, whether such database structure is discouraged for some good
reason.
I *roughly* want to have
class Payment < ActiveRecord::Base
has_one :purchase
end
where purchase can be either TicketPurchase, or MembershipPurchase, so
to have also
class TicketPurchase < ActiveRecord::Base
belongs_to :payment
end
class MembershipPurchase < ActiveRecord::Base
belongs_to :payment
end
Depending on your constraints, i.e., whether or not you have control
of the schema, you might flip the association.
class TicketPurchase < ActiveRecord::Base
has_one :payment # this could just as easily be a has_many if you
need to support split tenders
end
class MembershipPurchase < ActiveRecord::Base
has_one :payment
end
class Payment < ActiveRecord::Base
belongs_to :ticket_purchase
belongs_to :membership_purchase
end
Alternatively, or perhaps in addition, the purchase hierarchy your
explanation touches on looks like a pretty classic use-case for STI
(P of EAA: Single Table Inheritance)
Thanks Bill,
i am aware of the alternatives, but i was wondering if i can keep this
database schema which i like for that case, and to still be able to use
Thanks Bill,
i am aware of the alternatives, but i was wondering if i can keep this
database schema which i like for that case, and to still be able to use
so that payment.purchase was either TicketPurchase or
MembershipPurchase, while the foreign keys were stored in purchases
tables.
The problem you're up against is that relational databases don't
support inheritance. So you'd either need to use:
payment.purchase.membership_purchase.inspect
or move to an STI model for purchases and drop the ticket_purchases
and membership_purchases tables altogether if you want / need to be
able to get any 'meaningful' information from payment.purchase.inspect
Google 'rails sti' for some good links on how Rails implements / supports STI.
Bill, i see no theoretical difficulty in implementing what i want, i was
just wondering why it is not implemented in Rails (whether it is
considered a "bad style" for some reason).
The same way as one does
class Payment < ActiveRecord::Base
belongs_to :purchase, :polymorphic => true
end
(and then one can use payment.purchase regardless of the type of
purchase)
it would be natural to expect that
class Payment < ActiveRecord::Base
has_one :purchase, :polymorphic => true
end
also be possible, the difference is in storing the foreign key on the
other side.
Maybe it is considered redundant because one can do
class Payment < ActiveRecord::Base
has_one :ticket_purchase
has_one :membership_purchase
end
but this way one has to first look up payment.purchase_type, and then
use either payment.ticket_purchase or payment.membership_purchase
accordingly.
class Payment < ActiveRecord::Base
has_one :ticket_purchase
has_one :membership_purchase
def purchase
case purchase_type
when "TicketPurchase" then ticket_purchase
when "MembershipPurchase" then membership_purchase
end
end
end
Bill, i see no theoretical difficulty in implementing what i want, i was
just wondering why it is not implemented in Rails (whether it is
considered a "bad style" for some reason).
The same way as one does
class Payment < ActiveRecord::Base
belongs_to :purchase, :polymorphic => true
end
(and then one can use payment.purchase regardless of the type of
purchase)
it would be natural to expect that
class Payment < ActiveRecord::Base
has_one :purchase, :polymorphic => true
end
also be possible, the difference is in storing the foreign key on the
other side.
How would activerecord know what tables to look at?
because the "purchase_type" column would still be in the "payments"
table, like in usual polymorphic association.
I am in fact questioning myself if there are any benefits over the usual
polymorphic association.
I thought at first that it would be nice to be able to delete purchases
tables if necessary (to clear for example member's purchase history) and
not to have to have anything to do with the payments table (with usual
polymorphic association i would need to at least nullify the foreign
keys), and also i would only need to impose uniqueness constraints on
foreign keys, and not on the pair [type, foreign key].
But on the other hand, i would not be able to ensure that there are no
references from two different "purchases" tables to the same record in
"payments" table...
So i am hesitating.