We’ll focus on targeting announcements to certain types of users. For instance, the admin may want to deliver an announcement only to users who have subscriptions.
A field in the Announcements table called
limit_to_users will specify which types of users should receive the announcement.
limit_to_users can contain multiple conditions, so we’ll make it an array of hashes. ActiveRecord allows objects like these to be stored in text fields in the database, using the
serialize method in a model.
This test validates that the field works as intended, storing conditions and allowing them to be retrieved. Here, we are sharing the announcement only with users who do not have a subscription.
context "an announcement limited to certain users" do
it "retrieves a field from a limited announcement" do
limited_announcement = Announcement.create(:limit_to_users => [
:field => "subscription",
:value => ""
expect(limited_announcement.limit_to_users[:field]).to eq "subscription"
Querying serialized fields is tough
It’s risky to query serialized fields in a relational database. MongoDB and similar noSQL databases are tuned for fast queries of free-form information, while Postgres and its SQL siblings are not.
We need to figure out which announcement to serve to which user, even though the conditions are stored in a query-resistant serialized field.
Houston, we’ve got loops
Maybe we should grab all active announcements that the current user has not read, and cycle through them to find the latest one that is relevant to the user.
My first try at this includes two loops, one inside the other, which:
- Cycle through each active, unread announcement
- For each announcement, cycle through each condition
Loops carry potential performance issues, especially when nested. In this case, we came as far as we could with a query, and used loops for the rest.
The loops do not re-query the database, thus avoiding an n+1 query problem, so they should be pretty quick. We’ll test performance in past 4, coming soon.
Hired.com brings Rails job offers to you. Free for candidates. Salaries from $75,000 to $250,000. Sign up now!