Restful design

I’m building out an application that will be using REST. Here is the
model. I have a list of drugs. Each drug belongs to one of 2 domains,
i.e. dental or medical. Each domain has any number of categories, i.e.
antibiotic, anesthetic, etc.

So, you could have a drug(s) that is medical antibiotics or a drug(s)
that is a dental anesthetic.

The final point is that each individual drug has a single generic name
and multiple trade names.

I want to be able to create routes like these:

This route would display all the drugs in the given domain:

/drugs/:domain
(ex: /drugs/medical or /drugs/dental)

This route would represent all the drugs of a particular domain that are
also part of that domains category, i.e. all medical drugs that are
antibiotics or all dental drugs that are dental anesthetics:

/drugs/:domain/:category
(ex: /drugs/medical/antibiotics or /drugs/dental/anethetics)

This route will display all of the trade names for a particular drug,
i.e. all the trade names for articaine (if articaine is the generic
name):

/drugs/:drug/trade_names
(ex: /drugs/articaine/trade_names)

So, the root of my question is, how do I go about designing the
controllers? Should I build a controller for drugs, domains, categories
and trade_names?

Domains, categories and trade_names are really just a different way of
display a drug. Would it be better to work on some map.resources
tomfoolery to handle the cases and create some new actions in the drug
controller?

Any advice would be most appreciated.

Any advice would be most appreciated.
You are worrying too much. You don’t have to do any upfront design.
Rails is
very agile. I would put one of the model online and slowly start adding
new
features. Run autotest as you develop. This will help you to refactor
your
code mercilessly and change your design as you learn more about your
system.

On 10/18/06, Bala P. [email protected] wrote:

Any advice would be most appreciated.

You are worrying too much. You don’t have to do any upfront design. Rails is
very agile. I would put one of the model online and slowly start adding new
features. Run autotest as you develop. This will help you to refactor your
code mercilessly and change your design as you learn more about your system.

Huh? It’s a bad idea not to do ANY upfront design. Just because
Rails is “very agile” doesn’t mean you should sit at a blank screen
and get going. Generally thinking about the problem some will do
wonders.

Anyway, that response doesn’t even have anything to do with his
question. He’s asking how he should structure the controllers, not
how to design his domain model. Sounds like he’s got it pretty much
taken care of.

Actually, he proposed the best solution himself, I think. The desired
structure would be handled quite simple with map.resources.

Pat

All the doubts about structuring the code will become clear when you get
the
feedback from your own code. RESTful design already provides you with
some
structure. So you begin with that, right?

Ok, I think we are moving away from my intended question.

Bala, you are making way to many assumptions regarding the state of my
code. I’m actually looking for advice on structuring my code, not how
to design an application. Our domain models are built, etc. I can
build it any number of ways. Given the simple scenario I’ve provided,
how would YOU go about working with the controller structure.

My goal is to find somene to share some very pragmatic input. ‘I would
have a separate controller for each model because…’ or ‘I would do it
THIS way because…’. Learning the design philosophies of others and
incorporating their ideas is how I grow.

If I came to you and said ‘I’m using Ruby. What do you think is the
best method for implementing an AbstractFactory given xxx’. You
probably wouldn’t say ‘You thinking too much, let the code solve it’,
but rather provide me with some ideas on code, heirarchy, etc.

That same kind of simple, direct response is what I’m looking for.

So, to Bala and all, if you’ve got some ideas, I would love to hear
them.

And, thanks for the feedback so far.

**
If you got a problem, my code will solve it
Check out the hook while Ruby evolves it – Smanilla Vice

Actually, he proposed the best solution himself, I think. The desired
structure would be handled quite simple with map.resources.

Pat

I did not imply doing upfront design is a bad idea. Just avoid analysis
paralysis. Do an initial design that is good enough to get you going.
Don’t
worry about getting it right the first time. If you are able to change
your
code easily without breaking the functionality then there is no penalty
in
modifying your existing code.

All the doubts about structuring the code will become clear when you get
the
feedback from your own code. RESTful design already provides you with
some
structure. So you begin with that, right?

If I came to you and said ‘I’m using Ruby. What do you think is the
best method for implementing an AbstractFactory given xxx’. You
probably wouldn’t say ‘You thinking too much, let the code solve it’,
but rather provide me with some ideas on code, heirarchy, etc.

I used to think just like you when I was programming in Java. After
watching
DHH’s screencast several times (especially the one that shows brablog
example) and reading the AWDWR book several times. I have totally
changed my
approach to development. I don’t know about the experience of others who
might have made the same kind of shift in their approach.

Chris K. wrote:

I’m building out an application that will be using REST. Here is the
model. I have a list of drugs. Each drug belongs to one of 2 domains,
i.e. dental or medical. Each domain has any number of categories, i.e.
antibiotic, anesthetic, etc.

So, you could have a drug(s) that is medical antibiotics or a drug(s)
that is a dental anesthetic.

The final point is that each individual drug has a single generic name
and multiple trade names.

I want to be able to create routes like these:

This route would display all the drugs in the given domain:

/drugs/:domain
(ex: /drugs/medical or /drugs/dental)

This route would represent all the drugs of a particular domain that are
also part of that domains category, i.e. all medical drugs that are
antibiotics or all dental drugs that are dental anesthetics:

/drugs/:domain/:category
(ex: /drugs/medical/antibiotics or /drugs/dental/anethetics)

This route will display all of the trade names for a particular drug,
i.e. all the trade names for articaine (if articaine is the generic
name):

/drugs/:drug/trade_names
(ex: /drugs/articaine/trade_names)

So, the root of my question is, how do I go about designing the
controllers? Should I build a controller for drugs, domains, categories
and trade_names?

Domains, categories and trade_names are really just a different way of
display a drug. Would it be better to work on some map.resources
tomfoolery to handle the cases and create some new actions in the drug
controller?

Any advice would be most appreciated.

Your URL scheme is a flexible, segmented way to name drugs, so all
you’re talking about so far is a drugs resource/controller. If you want
to get RESTful, you might try thinking of it from the perspective of how
a user (or client) would interact with other kinds of resources. A
category resource could be used to show lists of all drugs in that
category, etc.

If you want to follow the typical way of doing things, allow drugs to be
named in URLs by a numeric id.

/drugs # all drugs
/drugs/5 # drug with id 5
/drugs/5/trade_names # list of trade_names of drug 5
/drugs/5/trade_names/1 # guess

Then you have to think about how you want to use the other resources.
Is a category just a way to list drugs, or does it have other attributes
as well? What about trade names? Do they also indicate the company?
Price? You might want to use strings for the ids of these things, and
that’s totally easy - just use params[:id] as a string.

/categories
/categories/analgesic
/categories/analgesic/drugs
/categories/analgesic/drugs/5

At that point things can get a bit complex, if you want to have the
DrugsController handle both the top level and nested routes. I got to
that point in an app and backed off, but it might be worth it to you to
pursue it.

The point of RESTful design is to simplify your code. If you can get
more milage by following those conventions, cool. If it complicates
things, don’t bother with it.


Josh S.
http://blog.hasmanythrough.com

Josh S. wrote:

Chris K. wrote:

I’m building out an application that will be using REST. Here is the
model. I have a list of drugs. Each drug belongs to one of 2 domains,
i.e. dental or medical. Each domain has any number of categories, i.e.
antibiotic, anesthetic, etc.

So, you could have a drug(s) that is medical antibiotics or a drug(s)
that is a dental anesthetic.

The final point is that each individual drug has a single generic name
and multiple trade names.

I want to be able to create routes like these:

This route would display all the drugs in the given domain:

/drugs/:domain
(ex: /drugs/medical or /drugs/dental)

This route would represent all the drugs of a particular domain that are
also part of that domains category, i.e. all medical drugs that are
antibiotics or all dental drugs that are dental anesthetics:

/drugs/:domain/:category
(ex: /drugs/medical/antibiotics or /drugs/dental/anethetics)

This route will display all of the trade names for a particular drug,
i.e. all the trade names for articaine (if articaine is the generic
name):

/drugs/:drug/trade_names
(ex: /drugs/articaine/trade_names)

So, the root of my question is, how do I go about designing the
controllers? Should I build a controller for drugs, domains, categories
and trade_names?

Domains, categories and trade_names are really just a different way of
display a drug. Would it be better to work on some map.resources
tomfoolery to handle the cases and create some new actions in the drug
controller?

Any advice would be most appreciated.

Your URL scheme is a flexible, segmented way to name drugs, so all
you’re talking about so far is a drugs resource/controller. If you want
to get RESTful, you might try thinking of it from the perspective of how
a user (or client) would interact with other kinds of resources. A
category resource could be used to show lists of all drugs in that
category, etc.

If you want to follow the typical way of doing things, allow drugs to be
named in URLs by a numeric id.

/drugs # all drugs
/drugs/5 # drug with id 5
/drugs/5/trade_names # list of trade_names of drug 5
/drugs/5/trade_names/1 # guess

Then you have to think about how you want to use the other resources.
Is a category just a way to list drugs, or does it have other attributes
as well? What about trade names? Do they also indicate the company?
Price? You might want to use strings for the ids of these things, and
that’s totally easy - just use params[:id] as a string.

/categories
/categories/analgesic
/categories/analgesic/drugs
/categories/analgesic/drugs/5

At that point things can get a bit complex, if you want to have the
DrugsController handle both the top level and nested routes. I got to
that point in an app and backed off, but it might be worth it to you to
pursue it.

The point of RESTful design is to simplify your code. If you can get
more milage by following those conventions, cool. If it complicates
things, don’t bother with it.


Josh S.
http://blog.hasmanythrough.com

Josh,
Thanks for the input. I’ve been thinking about this post a bit since I
originally put it out there. In reality, categories, tradenames, etc.
are a way of listing drugs in a category to a non-administrative user.
So, thinking in the REST manner, they would benefit from index() and
show(). I was hung up thinking just from the user’s perpective, so I
was thinking “why create controllers that only utilize index() and
show()”. Of course, even if I did use only those methods, it would make
my code a bit cleaner.

However, when I added in the admin perspective, having controllers for
each of the entities makes sense since I can add/edit/delete things like
trade names and categories to a specific drug.

Thanks for the input. I’ve got a followup question regarding displaying
views based on roles (i.e. admin, standard user, etc.), but I will save
that for the next post :slight_smile: