A post on Reddit says:
I’m not sure how best to do this. I would just set up a model, but that seems wrong to have a model with just 1 row in it (it’s a single charity). Is there a better way to do this? STI? something else?
It can seem like overkill to create a database table and a corresponding ActiveRecord model if you know for a fact that your table will only have one row. This is a pretty common situation, and there are a couple of ways to deal with this.
Note: Pat Maddox’s amazing comment on Reddit, which addresses this question, was the primary inspiration for this post.
First, if non-developers need the ability to update information that this “model” would contain, then yes, you should create an ActiveRecord model. This will of course give you all the benefits of ActiveRecord as well, like being able to use has_many
, belongs_to
and everything else.
If only developers are going to be concerned with and using this model, you don’t have to tie it to the database and can implement it as a “Plain Old Ruby Object” aka a “PORO”.
The advantage with PORO’s is that they are cheap to instantiate because you won’t be making a call to the database when you do so. Setting up association-like behavior can be as simple as defining either instance or class methods on the PORO. As Pat advises in his comments however, you should always ask yourself what benefit you’d get from implementing association-like behavior in your PORO to ensure that you’re doing it for the right reasons, and to keep your code easy to understand.
So, going with the example in the Reddit post above, where we have a Charity
model (this is the model that will only have one “row” and the one we will be writing a PORO for) which needs to define a has_many
type association with the Donation
model, you’d have something that looks like:
class Charity #this is our PORO
def name
'The Human Fund'
end
def donations
Donation.all
end
end
class Donation < ActiveRecord::Base #this corresponds to a table in the DB
validates :amount, presence: true
def charity
Charity.new
end
end
As you can see, we’re manually defining the methods (#donations
and #charity
) that we’d get automatically if we used has_many
. This allows us to get around the fact that a Charity
object does not correspond to a table in the database, and lets other parts of our code use Charity
objects as they would any other ActiveRecord object.
For more association type goodness on POROs, also check out the activemodel-associations gem.
So if you decide to go with a PORO, you next question is probably: Where should this file reside?
There are a couple of common options – in the models directory with the rest of the models in /app/models, or in the /lib directory. Pat Maddox recommends the models directory, and I concur, because if you’re going to treat it like a model in other parts of your code, it’s natural that other developers (or you in the future) will look for the class in the models directory. That being said, this is just a convention, and either way works.