Hello all,
I’m fairly new to Rails and decided I wanted to give it a go for a
fairly simple internal application that I want to refine and use it as
the building blocks for possible future applications.
The application will act, for now at least, as webservice API used by
external applications to POST and GET data. After watching DHH 2006
Rails conference talk I liked the fact that you could use one piece of
code with different interfaces. However I feel like I’m coming up
against difficultly modeling my domain and the interaction with the
external application yet still allowing room for a web interface if
required down the road.
Essentially what we have are error reporting applications out in the
field where those applications are tied to a specific location. The
application knows its location and what it is, it looks to use that
information to post an error report. The current php version of this
application simply posts the data as an Error Report. Doing so kicks
off a trigger that inserts into a summary table if the application and
location doesn’t exist.
With that in mind Here is my current vision for the model.
Location (1) --> (1 … *) Application (1) --> (0 … *) Error Report
The problem is a new location and application can come online without
being placed into the database prior to reporting an error. Thus the
question is, should the external reporting application check to see if
its Location and Application exists in the database first by
searching, then creating new Location and Application records if
required and then POSTing the Error Report? That seems very verbose.
It would be nice to simply POST the error report and if required the
related data objects created.
My questions:
- Is this possible?
- If it is possible would it be considered bad practice to have the
creation of a resource create other resources?
- Might there a better way to solve this problem that I just can’t
see?
Sincerely,
Michael
On Aug 27, 7:01 pm, mledford [email protected] wrote:
Hello all,
[snip]
My questions:
- Is this possible?
Sure. Consider ErrorReport to be a resource in your application, and
post your data to the /errorreports/create action.
- If it is possible would it be considered bad practice to have the
creation of a resource create other resources?
I don’t think so. Create the other resources as necessary. Just be
aware of possible concurrency issues if multiple users are posting
error reports simultaneously.
- Might there a better way to solve this problem that I just can’t
see?
If you prefer, you could require the client application to create the
location resource first. If you can make the creation code
idempotent, so that multiple calls to create the same location would
be handled safely, then you could return an error response code if the
location does not exist when they try to create the error report.
Then the application would know to first create the location and then
try again to create the report. But that seems like the long way
around to me.
Hope this helps…?
Sincerely,
Michael
Jeff
essentialrails.com
Hi –
On Tue, 28 Aug 2007, mledford wrote:
code with different interfaces. However I feel like I’m coming up
location doesn’t exist.
required and then POSTing the Error Report? That seems very verbose.
It would be nice to simply POST the error report and if required the
related data objects created.
My questions:
- Is this possible?
Sure.
- If it is possible would it be considered bad practice to have the
creation of a resource create other resources?
Not by me, for several reasons. The resource is “Error report for
location x and application y”, and all that matters is that there’s an
API for exchanging representations of that resource. How the data
behind the representations is persisted (or not) is an implementation
detail. And if a new location gets created behind the scenes – and
assuming you consider a location also to be a resource, in its own
right – that just means that the creation has taken place in some way
other than the use of the API. I don’t think there’s anything
un-REST-like about that. If, say, your resource is “Jane Eyre”, and
you have various representations available (plain text, PDF,
movie…), it’s unlikely that any of the data involved were put there
via connecting to a URL.
I’m putting an emphasis here on [my understanding of] the REST concept
of a resource, for which I think the “resource” in Rails resource
routing is not necessarily an exact synonym. Nor is that necessarily
bad; Rails is not purporting to be a generalized, opinionless (hardly!
conduit for REST principles, so it make sense that “resource” in
Rails tends to evoke very specific persistence techniques and so
forth. Still, I think it’s helpful to keep the conceptual nature of
resources in view, especially for situations where you need to think
through resource and/or storage issues like this.
David
–
I wonder if it is still acceptable to do this in nested resources.
For example:
POST /locations/100/applications/2/errors
Would create location and application if it did not exist and of
course create the error. Or should this only create the last resource?
Which is my gut feeling. If this is true this brings up a red flag for
me… which as David would say mean I need to think about it a little
more. Yet, I feel like I’m over thinking this.
If you shouldn’t create the referring nested resources then the
following pops up.
- I need the errors resource in two places; /locations/100/
applications/2/errors and /errors
- These two resources would expect different input for creating vs
modifying. /errors would need to have the location and application
specified in it’s input where /locations/100/applications/2/errors
derives it from the resource.
- In my mind the output should be the same as the input. If I’m right
you would be using the same error report controller but with different
routes. It seems like it would be difficult to have two different
outputs since the output is usually the underlying model.
Any further input would be much welcomed!
Sincerely,
Michael
Jeff & David,
Many thanks for your thoughtful replies. I will keep them in mind
while I proceed down this very new road for me.
Sincerely,
Michael