Home > Blockchain >  How to make Ruby on Rails model relation with custom string column
How to make Ruby on Rails model relation with custom string column

Time:09-28

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
  • Related