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.
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.
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
I have a model called Company, this model is used for both companies and clients, I know this is not the best approach for companies/clients but the software I'm working on was built that way and to change that, it would take months of job.
class Company < ActiveRecord::Base
has_many :companies
belongs_to :company
has_many :orders, dependent: :destroy
end
My other model is Orders, where the companies are linked by the company_id column and the customers by the customer_id column, that is, an order is linked to a company and a customer of that company.
class Order < ActiveRecord::Base
belongs_to :company
end
Currently, I created a method to get the customer but I would like to call a has_one to get the customer from the order, but I am not able to point the customer_id column of the order to the company id column using the rails class_name.
If I understand your question correctly (in the first para you mentioned clients and in the second you are saying customers so I am assuming clients == customers and customer is also a Company object) you are trying to do this:
class Order < ActiveRecord::Base
belongs_to :company
has_one :customer, class_name: 'Company'
end
which seems incorrect as it should be belongs_to:
class Order < ActiveRecord::Base
belongs_to :company
belongs_to :customer, class_name: 'Company'
end
This should work but you can also specify foreign_key:
belongs_to :customer, class_name: 'Company', foreign_key: :customer_id
From the docs: https://api.rubyonrails.org/v7.0.2.4/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_one
has_one specifies a one-to-one association with another class. This method should only be used if the other class contains the foreign key. If the current class contains the foreign key, then you should use belongs_to instead.
I have two models:
Ticket and User
A ticket belongs_to a User, and a User has_many Tickets.
The thing here is that I want to associate these two models with:
The ticket has a ref_token column and the User has a token column. So, basically when trying to find the User for a given token (token123), I would expect the following query:
SELECT * FROM tickets WHERE token = 'token123'
How can I set the association to accomplish this (basically I want to specify the columns that set the association. In this case they are different than the primary keys).
I have this now:
User
has_many :tickets, foreign_key: 'ref_token', primary_key: 'token'
Ticket
belongs_to :user, foreign_key: 'ref_token', primary_key: 'token'
And I am able to do user.tickets, but I can't do ticket.user. It keeps returning nil.
I guess it should be:
has_many :tickets, foreign_key: "ref_token"
belongs_to :user, foreign_key: "token"
I have two models in Rails. One is for Users and one is for Jobs that can be owned by users. In the User model, I have a has_many association, and in the Jobs object I have a belongs_to association. Jobs have an owner column which is the user id of the owner (associated via a foreign key).
User: (id, name, email)
Class User < ActiveRecord::Base
has_many :jobs, dependent: :destroy, class_name: 'Job', foreign_key: :owner
end
Job: (id, owner, job_code)
Class Job < ActiveRecord::Base
belongs_to :user, class_name: 'User', foreign_key: :owner
end
This works fine in one direction: User.first.jobs will display a list of all of the Jobs that belong to that user. Unfortunately however, if I try to user Job.first.owner, I get simply the user's id integer, not a user object. What a I missing to be able to select the owner without having to re-query the database to get a user by ID?
1st Issue:
Don't use "object" as your model name, this keyword is already reserved.
Let's say you have got user model and job model, one user has got many jobs.
User (id, name, email) Job (id, job_code, owner)
here, the owner column holds the userID to which the job belongs to.
class User < ActiveRecord::Base
has_many :jobs, class_name: 'Job', foreign_key: 'owner'
end
class Job < ActiveRecord::Base
belongs_to :user , class_name: 'User', foreign_key: 'owner'
end
Now:
User.first.jobs #will give you first users jobs.
Job.first.user #will give you the owner info of the job
Hope it helps :)
I have a User model and a Message model. My message table has the columns created_for, and created_by and these are both foreign keys to the User table.
I'm currently getting this error message:
undefined methodcreated_for_id' for #`
How can I get this to work without having to change my columns to created_for_id and created_by_id?
class User < ActiveRecord::Base
has_one :message
end
class Message < ActiveRecord::Base
#belongs_to :user
belongs_to :created_by, :class_name => "User" # Basically tell rails that created_by is a FK to the users table
belongs_to :created_for, :class_name => "User" # Basically tell rails that created_for is a FK to the users table
attr_accessible :created_by, :created_for, :message
end
You can specify the foreign key for the belongs_to via:
belongs_to :created_for, class_name: 'User', foreign_key: :created_for
I suspect you are going to run into an issue having the relation name and foreign key attribute sharing a name. Here is the belongs_to documentation, scroll down to the "Options"
I'm in the process of building a back-end admin panel for our customers.
I'm integrating a feature to allow users to upgrade and downgrade their monthly subscription which means adding a new model for the billing_plans table.
I'm stuck trying to get the relationship right between an account and a plan.
I have a billing_plan model:
class BillingPlan < ActiveRecord::Base
self.table_name = "billing_plans"
has_many :accounts, primary_key: 'name', foreign_key: 'audio_billing_model'
end
and an accounts model:
class Account
has_many :contacts
belongs_to :user, primary_key: :email, foreign_key: :billing_email_address
has_one :billing_plan, foreign_key: 'name', primary_key: 'audio_billing_model'
end
I'm sure this could help other people and I'm pretty certain someone must have come across it before.
Since you're trying to establish a has_many belongs_to relationship, simply define the primary key on the has_many model, then direct the belongs_to model to utilize that primary key as its foreign key:
# app/models/billing_plan.rb
class BillingPlan < ActiveRecord::Base
self.table_name = "billing_plans" # Seems unnecessary, as the table name by default is `billing_plans`
has_many :accounts, primary_key: 'name'
end
# app/models/account.rb
class Account < ActiveRecord::Base # Remember to subclass `ActiveRecord::Base`
has_many :contacts
belongs_to :user, primary_key: :email, foreign_key: :billing_email_address
has_one :billing_plan, foreign_key: 'name'
end