Customizing Sideloads
This cookbook will help you understand sideloading. It would be great to live in a world where everything follows default ActiveRecord table conventions, but in my experience this is rarely the case. From legacy code to alternate datastores, we need to think in Real World terms.
Our Employee Directory sample application
has a clean schema - let’s screw with it. Let’s say Department
has a
column called watcher_emails
, which is an array of strings. We want to
sideload Department > Watchers
. Though the relationship is called
watchers
, these will be Employee
records.
Let’s start by adding a spec:
Add the relationship:
Run the test and you’ll get this error:
How would we track down this error? Well, we know Resources connect together with Links. Let’s take a look at the query parameters that would be used to connect these two Resources:
Note - we’re using pry to debug here.
The value of hash
here is:
Which makes sense. If we say has_many :things
, by default we expect
Thing
to have a department_id
we can query.
That’s not our case, though. Instead, let’s customize those parameters to fit our use case:
Instead of querying by department_id
, we need to query by email
. And
the value we pass in will be an array of email addresses
We’d need to add an email
filter to EmployeeResource
to make this
work. This gets us querying correctly, but there’s another error:
Here’s the thing to keep in mind: let’s say our request was
/departments?include=watchers
. We queried all the data, and we now
have an array of Department
s and an array of Employee
s. Now we need
to specify which employees should be assigned as watchers of which
department.
Let’s write that code manually:
We’re selecting all relevant Employee
s for a given Department
by
checking the array of watcher_emails
.
This code can be tightened up a little with assign_each
(recommended).
This way we don’t have to iterate departments or worry about the
assignment ourselves:
Note that we’re using #select
to return an array of relevant
Employee
s. If this was a belongs_to
or has_one
relationship, we’d
probably want to use #find
to return a single Employee
.
OK there’s one last error:
This one is simple - the assign
function will call your Adapter’s
assignment logic, which by default will be a simple department.watchers
= relevant_employees
. That means we need to add a getter/setter for
this property:
And we’re done! The test should now pass. Check out the working code here.