I have Customer and Subscription models in my Ruby on Rails app.
Customer
id: ID
stripe_costumer_id: String
Subscription
id: ID
stripe_customer_id: String
I want to make a relation one to many between there two tables but use stripe_customer_id as foreign key.
I tried so far:
Subscription
belongs_to :paywall_customer, class_name: 'Customer', foreign_key: :stripe_customer_id
Customer
has_one :paywall_subscription, class_name: 'Subscription', foreign_key: :stripe_customer_id
The problem is then when I try to create a new subscription I get this error:
ActiveRecord::RecordInvalid: Validation failed: Customer must exist
I would be grateful if you could help me achieve to make posibile to get the relation between these two tables using stripe_costumer_id that is also a string in this case.
CodePudding user response:
You are conflating data (stripe_customer_id) with relational references (id). It is not advisable to fight the Rails paradigm, the id field should be the foreign key. The stripe_customer_id field is a value that pertains to a customer, so it should just be a field in the customers table and not in the subscriptions table.
For one-to-many it should be:
# in app/models/customer.rb
class Customer < ApplicationRecord
has_many :subscriptions
end
# in app/models/subscription.rb
# it has a column 'customer_id'
class Subscription < ApplicationRecord
belongs_to :customer
end
If you try to configure the relationship in non-Rails ways, you are bound to end up with problems. Rails is opinionated, and we are obligated to conform to its opinions. But it's a small price to pay b/c it works so well.
CodePudding user response:
UPDATE
You need to add primary_key: :stripe_customer_id
to the associations.
And since you want a one-to-many relationship: Customer has_many :paywall_subscriptions
Customer
has_many :paywall_subscriptions, class_name: 'Subscription', foreign_key: :stripe_customer_id, primary_key: :stripe_customer_id
Subscription
belongs_to :paywall_customer, class_name: 'Customer', foreign_key: :stripe_customer_id, primary_key: :stripe_customer_id
To create a Subscription, you must have stripe_customer_id
field filled in. And a Customer with that stripe_customer_id
must already exist.
ORGINAL
This can work if you add the model StripeCustomer
; we store the stripe_customer_id
string inside the uid
field.
Customer
id: ID
stripe_customer_id: String
Subscription
id: ID
stripe_customer_id: String
StripeCustomer
id: ID
uid: String
Customer
belongs_to :stripe_customer, primary_key: :uid
has_many :subscriptions, through: :stripe_customer
Subscription
belongs_to :stripe_customer, primary_key: :uid
has_one :customer, through: :stripe_customer
StripeCustomer
has_one :customer, primary_key: :uid
has_many :subscriptions, primary_key: :uid