REST Style

On Sunday 06 January 2008, Anton J Aylward wrote:

like they’re obsessed with it. Ever last example I’ve see, in this
thread and on the 'Net, has it.

Because it is easy, you can get it automatically, and often it fits. In
Rails it’s what map.resources gives you for free. If it doesn’t suit
your needs, well, feel free to customize all the way you want. It’ll be
a bit more work, but can be RESTful all the same.

For example, I’m using some fairly generic code to audit changes to
resources. Display of audit logs is handled by a single controller
across all resources and I can get logs for everything, a particular
resource type, or a single resource; all of this in various formats.
Rails routing doesn’t provide the URLs I want automatically, of course,
but I can easily persuade it to do my bidding

map.with_options(:controller => ‘audits’, :action => ‘show’) do |a|
a.audits ‘/audits’, :format => ‘html’
a.audits ‘/audits.:format’
a.audits ‘:resources/audits’, :format => ‘html’
a.audits ‘:resources/audits.:format’
a.audits ‘:resources/:id/audits.:format’
a.audits ‘:resources/:id/audits’, :format => ‘html’
end

Michael


Michael S.
mailto:[email protected]
http://www.schuerig.de/michael/

On Sunday 06 January 2008, Anton J Aylward wrote:

If putting the names of the controllers in the URL is not a REST
For example, I’m using some fairly generic code to audit changes to
a.audits ‘:resources/audits’, :format => ‘html’
a.audits ‘:resources/audits.:format’
a.audits ‘:resources/:id/audits.:format’
a.audits ‘:resources/:id/audits’, :format => ‘html’
end

Have you deliberately chosen a bad example?
You’ve still got the name of the controller in each URL.
Which is what I’m trying to address in this part of the thread.

Feel free to rename the controller to ‘something_else_entirely’. I don’t
know why you would do that, though, because it comes quite naturally
that a specific resource or a specific representation format is handled
by a single controller.

And yes, Understand “its a design decision” you made. But how could
you have made it differently?

See above, I could easily have used a special controller on each of the
routes above and I could have given those controllers some weird names,
but why should I?

Michael


Michael S.
mailto:[email protected]
http://www.schuerig.de/michael/

Then you’re just reinforcing my question.
Why do all the examples put the names of the controllers in the URL?

If you talking about the default routes provided by Rails then you’re
completely missing something. It’s not the names of the controllers
that are in the URI, they are the names of the resources. The Rails
convention happens to name the controllers after the resource names.
This works well because of the same reasons that naming ActiveRecord
attributes after their column in the database makes things much
easier. This removes the need for complex object relational mapping
configuration files (convention over configuration).

What Rails is attempting to do with REST is similar. Just like with
ActiveRecord, if you decide to develop you own conventions then it’s
just going to make your life, and the life of consumer of your
service, more difficult. There’s not anything particularly wrong with
that, it comes down to choice. Do it the Rails way and it’s easy and
well understood. Do it your way and put in the extra effort to work
around the conventions.

Every decision that remains with the developer adds complexity to the
system. When those decisions are made for you by the framework it
serves to simplify your design. That’s the goal of the REST
implementation in Rails. Whether they have achieved that goal is
another story altogether.

Michael D. Ivey said the following on 06/01/08 03:33 PM:

On Jan 6, 2008, at 2:24 PM, Anton J Aylward wrote:

Why do all the examples put the names of the controllers in the URL?

I can understand it as a ‘teaching example’, to emphasize the nesting
structure by labelling it, but are the ‘labels’ mandatory? Can’t we
move past the ‘learning examples’? ARE the labels mandatory?

As I say, why does every example keep doing it?

Asked and answered: it’s the way Rails does it by default.

OK, not back up to the other questions?

It may be default but its no mandatory?
Can you take one of those ‘learning examples’ and show it without the
‘labels’?


Give a man a fish, and you’ll feed him for a day. Give him a religion,
and he’ll starve to death while praying for a fish.
–Timothy Jones

On Jan 6, 2008, at 2:24 PM, Anton J Aylward wrote:

Why do all the examples put the names of the controllers in the URL?

I can understand it as a ‘teaching example’, to emphasize the nesting
structure by labelling it, but are the ‘labels’ mandatory? Can’t we
move past the ‘learning examples’? ARE the labels mandatory?

As I say, why does every example keep doing it?

Asked and answered: it’s the way Rails does it by default.

Michael S. said the following on 06/01/08 04:39 PM:

For example, I’m using some fairly generic code to audit changes to
a.audits ‘:resources/audits’, :format => ‘html’
that a specific resource or a specific representation format is handled
by a single controller.

And yes, Understand “its a design decision” you made. But how could
you have made it differently?

See above, I could easily have used a special controller on each of the
routes above and I could have given those controllers some weird names,
but why should I?

???
I’m not asking for ‘weird names’. I’m not asking to rename the
controller.
Go back to my ‘projects’ example.

http://example.com/web/HouseRenovation/topic/SandAndvarnishFloor
vs
http://example.com/HouseRenovation/SandAndvarnishFloor

I’m asking WHY do you keep on putting that FIXED STRING that identifies
the controller (even indirectly via the ‘with options’). As I say, its
chronic for nested controllers/resources.

I can understand it for the operations like /login and /signup that are
‘out of band’ of the normal flow of the application (though I know many
CAs who believe that auditing is part of the normal flow of operations
of a business, and a lot of recent legislation seems to support that
view), but why do people keep putting it into the normal flow?

I’m asking if its mandatory.
If its not mandatory then why do it?

Please don’t say ‘its easier’ or ‘less work’ or something along those
lines. I’ve experimented with (non REST) routing in my wiki and the
difference between

   http://example.com/wiki/System/Homepage

and
http://example.com/System/Homepage

is just a few characters in routes.rb. Its about the same ‘work’ either
way. And I do even have a way to make the ‘login’ and ‘signup’ “in
band” when I choose to implement it.

How can I tell that you’re no making a ‘virtue out of a necessity’?


“To be conscious of one’s ignorance is the beginning of wisdom”.
– Sri Ram

On Sunday 06 January 2008, Anton J Aylward wrote:

I’m asking WHY do you keep on putting that FIXED STRING that
identifies the controller (even indirectly via the ‘with options’).
As I say, its chronic for nested controllers/resources.

I’m not sure I’m able to follow you. I need that fixed string, because
in some way requests have to be mapped to controllers. If I use
map.resources, Rails does the mapping behind the scenes; if I use plain
map.connect, I have to do the mapping myself.

http://example.com/web/HouseRenovation/topic/SandAndvarnishFloor
vs
http://example.com/HouseRenovation/SandAndvarnishFloor

map.connect ‘/*categories’,
:controller => ‘products’, :action => ‘index’

class ProductsController < ActionController::Base
def index
@items = Product.find_by_categories(params[categories])

end
end

class Product < ActiveRecord::Base
def self.find_by_categories(categories)
# find all products assigned to the most specific category
end
end

Michael


Michael S.
mailto:[email protected]
http://www.schuerig.de/michael/

Robert W. said the following on 06/01/08 04:50 PM:

configuration files (convention over configuration).
True, but it neither addresses my question nor helps me figure out how I
can make use of this in my applications.

Back to my “HOW” set of questions.

And as a note, some of the examples have had quote involved routes files
and generated routes for all the extra methods. Which really is
‘configuration’.


We’ll give you your money back if not satisfied, but we do suspect that
we will be quite satisfied with your money.

I’m not asking for ‘weird names’. I’m not asking to rename the controller.
Go back to my ‘projects’ example.

http://example.com/web/HouseRenovation/topic/SandAndvarnishFloor
vs
http://example.com/HouseRenovation/SandAndvarnishFloor

I’m asking WHY do you keep on putting that FIXED STRING that identifies
the controller (even indirectly via the ‘with options’). As I say, its
chronic for nested controllers/resources.
<…>

I am about to give up :frowning:
If there is fixed string it usually identifies resource (which is core
for REST), but
of course it may be that controller has the same name. It’s controller
named
after resource not the other way around, so you have names of the
resources in
your URI and you may have controllers with the same names.

Let’s take another bad example blog.
You may have:

http://blog.example.com/posts/ → this way you can get list of
resources, blog
postings.

http://blog.exampe.com/posts/1 → there you identify single resource,
a blog post.
You may choose different way to go, let’s say
http://blog.example.com/posts/the-first-post
or even http://blog.example.com/the-first-post – it doesn’t really
matter, except that
you get the first for free and another options will require some
additional work.

Now, there come comments.
http://blog.example.com/posts/1/comments - a list of comments for the
current entry.
You may as well have
http://blog.example.com/posts/the-first-post/comments
or
http://blog.example.com/the-first-post/comments/

Going down the nested resources road you will have

http://blog.example.com/posts/1/comments/2
http://blog.example.com/posts/the-first-post/comments/2
http://blog.example.com/the-first-post/comments/2

If you want you can event get rid of /comments/ and implement
http://blog.example.com/post-id-or-name/comment-id identification schema

it does not really matter.

As for http://blog.example.com/posts/1/comments/2 it is not putting the
names of the controllers into URI, it’s still about identification of
resources:
/posts/ identifies collection of posts
/posts/1 identifies specific post from that collection
/posts/1/comments identifies collection of comments for that specific
post
/posts/1/comments/2 identifies specific comment.

Of course, you can implement your own identification schema, making
all more obscure, but it can soon make life more difficult. This may
make sense if your site provides quite limited set of resources.
You can sure map your blog posts and comments to
http://blog.example.com/post-id-or-name/comment-id
but then you will have to think, how to do with categories, tags, etc.
http://blog.example.com/rest-way - is that post, or is that name of
the category?
http://blog.example.com/categories/rest-way – now it is clear.

Basicaly having full path to resource in URI makes life easier.
Just don’t think about it as about controllers. Think resources.

Regards,
Rimantas

http://rimantas.com/

Rimantas L. said the following on 06/01/08 07:09 PM:

[snip - clarification of resoruce vs controller acceped and skipped]

If you want you can event get rid of /comments/ and implement
http://blog.example.com/post-id-or-name/comment-id identification schema –
it does not really matter.

Yes, “I want”.
How?

Some day, on the corporate balance sheet, there will be an entry which
reads, “Information”; for in most cases the information is more valuable
than the hardware which processes it.

  • Adm. Grace Murray Hopper, USN Ret.

On Jan 6, 2008, at 3:59 PM, Anton J Aylward wrote:

Can you take one of those ‘learning examples’ and show it without the
‘labels’?

map.resources :webs do |webs|
webs.resources :pages
end

map.page “/:web_name/:page_name”, :controller => “pages”, :action =>
“show”

However, most apps DON’T have just one resource type. Most have lots
of Things: users, accounts, places, pages, monkeys … etc.

So be sure to put your extra resource route last.

Is that what you’re asking for?

Well, it’s /possible/, but you do get confusion. If you add this
snippet to the top of routes.rb
(There should be a better place to put it, but I was trying to do this
quickly)

module ActionController
module Resources
class Resource
def path
@path ||= “#{path_prefix}”
# this is normally @path ||= “#{path_prefix}/#{plural}”
end
end
end
end

If you then do a ‘map.resources :projects’ you will get the full
array of
REST routes, (GET, POST, PUT, DELETE) linked up as appropriate.
‘rake routes’ produces the following:

projects GET /
{:controller=>“projects”, :action=>“index”}
formatted_projects GET /.:format
{:controller=>“projects”, :action=>“index”}
POST /
{:controller=>“projects”, :action=>“create”}
POST /.:format
{:controller=>“projects”, :action=>“create”}
new_project GET /new
{:controller=>“projects”, :action=>“new”}
formatted_new_project GET /new.:format
{:controller=>“projects”, :action=>“new”}
edit_project GET /:id/edit
{:controller=>“projects”, :action=>“edit”}
formatted_edit_project GET /:id/edit.:format
{:controller=>“projects”, :action=>“edit”}
project GET /:id
{:controller=>“projects”, :action=>“show”}
formatted_project GET /:id.:format
{:controller=>“projects”, :action=>“show”}
PUT /:id
{:controller=>“projects”, :action=>“update”}
PUT /:id.:format
{:controller=>“projects”, :action=>“update”}
DELETE /:id
{:controller=>“projects”, :action=>“destroy”}
DELETE /:id.:format
{:controller=>“projects”, :action=>“destroy”}

Which is as you wanted, routing-wise.
Using

def to_param
self.name
end

In our project model means that the name is used instead of the id
number for
any generated links, and a similar change in the controller from
‘find_by_id(params[:id])’
to ‘find_by_name(params[:id])’ works similarly. Obviously all the
project names should be
unique, and in addition, you should disallow a project named ‘new’.

However, the problem comes when we decide that each project should
have tasks.

map.resources :projects, :has_many => :tasks

I won’t post the full routing list, as it is rather long, but I will
pull out
two lines from it:


project GET /:id {:controller=>“projects”, :action=>“show”}

project_tasks GET /:project_id
{:controller=>“tasks”, :action=>“index”}

As you can see, the two routes, for two different resources (the
project and
it’s subsidiary tasks) are indentical. Rails has a ‘first declared,
first
served’ policy for routing, so it’s impossible to get a list of all
the tasks
of a project. (Well, not impossible, but requires some thought to get
around -
see later) It’s also not REST, which is based around the idea of each
url
pointing to one (and only one) resource.

That is actually the only conflict you get in the case of a project
with many
tasks, but if a project also has notes, then suddenly you’re also
posting to
the same place to create several seperate resources. And obviously,
in
addition to notes and tasks needing unique names within themselves,
you can’t
have a note and a task with the same name. (‘name’ used here as a
placeholder
for whatever id parameter is used to find projects by)

Of course, with more hacking of the Resources module, you could
probably make
it such that the controller name was used for the index action. So
/projects gave you a list of all the projects
/:project_name was an individual project
/:project_name/tasks was all the tasks associated with a project
/:project_name/:task_name was an individual task
etc.

Obviously, you’d need further constrains on allowed names to stop
people using
projects, tasks, etc. as names of projects or tasks, by accident or
with
malicious intent.

Or if monkeying around in the actionpack source isn’t what you want,
hook
up all your routes manually in routes.rb. The full REST routing for a
single
resource is 14 routes, once you take into account the format and edit
and new
actions, but none of them are especially complicated to write. You
start with
something like

map.projects ‘/’, :controller => ‘projects’, :action =>
‘index’, :conditions => { :method => :get }
map.project ‘/:id’, :controller => ‘projects’, :action =>
‘show’, :conditions => { :method => :get }
and so on, changing the action and condition as appropriate.

So, that’s how you /can/ have URLs in the form you desire, but it is
not
a trivial task, at least without some thought on how you will handle
such
things as route generation and the overlaps in URLs I mentioned
earlier.

I hope this helps, however,
Jonathan.

namelessjon said the following on 07/01/08 05:56 AM:

[… snip …]

If you then do a ‘map.resources :projects’ you will get the full
array of REST routes, (GET, POST, PUT, DELETE) linked up as
appropriate. ‘rake routes’ produces the following:

Could you repost that formatted differently, please.
It seems to have wrapped in a confusing manner.

Thanks.

end

In our project model means that the name is used instead of the id
number for any generated links,

Which I strongly advocate for both security reasons (see other thread)
and user intelligibility.

However, the problem comes when we decide that each project should
have tasks.

I don’t see why its a problem.
The reason I asked about this was that in my Wiki is a real short piece
of routing. Two lines in a “map.with_options” wrapper.

map.resources :projects, :has_many => :tasks

I won’t post the full routing list, as it is rather long, but I will
pull out two lines from it:

Perhaps you could explain WHY it has to be long.
As I said, my ‘old’ way doesn’t make the routing long.

… project GET /:id {:controller=>“projects”, :action=>“show”} …
project_tasks GET /:project_id {:controller=>“tasks”,
:action=>“index”} …

As you can see, the two routes, for two different resources (the
project and it’s subsidiary tasks) are indentical. Rails has a
‘first declared, first served’ policy for routing, so it’s impossible
to get a list of all the tasks of a project.

???
Only a problem if the spec requires that the UI has that.
Things like generating html select lists can still be one ‘internally’.
If its not a requirement its not a problem, and for my design its not a
requirement. Lists of topics in a web are handled differently since
they have to have metadata, links and access control applied. Its a
design difference.

Yes, I’m making a ‘virtue out of a necessity’.

(Well, not impossible, but requires some thought to get around - see
later) It’s also not REST, which is based around the idea of each url
pointing to one (and only one) resource.

That is actually the only conflict you get in the case of a project
with many tasks, but if a project also has notes, then suddenly
you’re also posting to the same place to create several seperate
resources. And obviously, in addition to notes and tasks needing
unique names within themselves, you can’t have a note and a task with
the same name. (‘name’ used here as a placeholder for whatever id
parameter is used to find projects by)

So the ‘old way’ is superior for this class of problem.
I can keep nesting it with not much effort.

Heck,
http://Webname/Topicname/edit
from
/:web/:topic/:action

could equally well be

http://Webname/Topicname?action=edit

I’ve got a lot of flexibility.

Of course, with more hacking of the Resources module, you could
probably make it such that the controller name was used for the index
action. So /projects gave you a list of all the projects
/:project_name was an individual project /:project_name/tasks was all
the tasks associated with a project /:project_name/:task_name was an
individual task etc.

Indeed: effectively taking out-of-band of the normal ‘address space’.

In effect, /login, /signup are out of band
and its not that difficult to think of /web/:webname
a being an administrative ‘out of band’ interface.

Some Wikis are obsessive about having EVERYTHING as a wiki page, login,
signup, creating new webs, changing access control. Personally I see
those as ‘out of band’ of the working with the wiki pages. So for me,
its not a problem.

And slotting /web/:webname in as an admin function is a easy way for me
to segue into using REST.

Obviously, you’d need further constrains on allowed names to stop
people using projects, tasks, etc. as names of projects or tasks, by
accident or with malicious intent.

:slight_smile:
I was just going to ask about that. :slight_smile:

In my present setup I have

 :requirements => {
                  :web   => /[A-Z][a-z]+/,
                  :topic => /([A-Z][a-z]+){2,}/,

That is, the topic has to be a CamelWord.
(that RE probably needs refinement in due course)
and the web has only a leading uppercase.
I also have

       :action => /[a-z][a-z_]{3,}/

for where its appropriate.

Can these requirements be re-mapped?

Or if monkeying around in the actionpack source isn’t what you want,

At my level of experience with it, it feels a bit daunting.

hook up all your routes manually in routes.rb. The full REST routing
for a single resource is 14 routes,

OUCH!

once you take into account the
format and edit and new actions, but none of them are especially
complicated to write. You start with something like

map.projects ‘/’, :controller => ‘projects’, :action => ‘index’,
:conditions => { :method => :get } map.project ‘/:id’, :controller =>
‘projects’, :action => ‘show’, :conditions => { :method => :get } and
so on, changing the action and condition as appropriate.

ARRGH! Wrapping confusion! Again.

So, that’s how you /can/ have URLs in the form you desire, but it is
not a trivial task, at least without some thought on how you will
handle such things as route generation and the overlaps in URLs I
mentioned earlier.

One of the benefits being touted for REST is that it makes things
simpler. But what I’m seeing is that for what I’m doing it makes it
more complicated.

I hope this helps, however, Jonathan.

Yes.


The way that can be followed is not the Way
The truth that can be told is not the Truth

namelessjon said the following on 07/01/08 11:16 AM:

On Jan 7, 1:57 pm, Anton J Aylward [email protected] wrote:

There, a pastie should avoid the confusion and formatting:

Parked at Loopia

Thank you. Much appreciated.
That’s the rake output?
What’s the input?

indexes and so it’s rather trivial to iterate over all of them
anyway.

Which is why I “don’t do that, then”.

As I said, my ‘old’ way doesn’t make the routing long.

Well, it’s the REST that makes it so long (essentially)
Or more specifically, connecting things such that the four HTTP verbs
are mapped to appropriate URLs and Controller methods, e.g. GET
matched to show, DELETE mapped to destroy, etc.
If you used your old method, but still wanted to REST, then you would
need a lot of “if request.post?” “if request.put?” “if request.get?”
etc. in your controller methods.
In a RESTful controller, you have a more complex routing and several
small methods.

Thanks for clearing that up.
So it’s about trade-offs.

If its not a requirement its not a problem, and for my design its not a
separately, hence they should have individual URLs.
to segue into using REST.
In my present setup I have
:action => /[a-z][a-z_]{3,}/

for where its appropriate.

Can these requirements be re-mapped?

Well, keeping them within the routing is probably a good thing, but
you probably also want to add them as validations to the Web / Topic
model

I told you I was paranoid.
Guess what I do?

The purpose of the routing is send it to the right controller & method.

I could have just use

             *url

and done all the work in the controller. I chose not to.
Trade-offs.

Or similar, so that when people create invalid names, they can’t,
rather than creating a page they subsequently can’t access.

Yes, that validates the creation.
But validating the routing counts too, so that invalid URLs get routed:

http://CamelName/Noncamelname
http://nonCamelName/Noncamelname
http://Noncamelname/nonname

and they don’t even touch the controller.

I see this as pushing error checking back as early in the process as
possible.

Or if monkeying around in the actionpack source isn’t what you want,
At my level of experience with it, it feels a bit daunting.

That’s no excuse. :wink:

I don’t carry a 50mm machine gun for the same reason.
Are you suggesting I should? :slight_smile:
Let’s think what else I don’t think I’m inexperienced enough to be
doing? Do you need brain surgery or an organ transplant?:slight_smile:

Looking for that routing code was the first time I really have tried
hacking at the Rails source.

I’ll stick to OS and compilers :slight_smile:

 :action => 'index', :conditions => { :method => :get }

map.project ‘/:id’, :controller => ‘projects’,
:action => ‘show’, :conditions => { :method => :get }

and so on, changing the action and condition as appropriate.

Thanks you. I see now.
Is there some equivalent to

:requirements => { :web => /[A-Z][a-z]+/ }

for this? That the id-as-name has to meet some pattern or other
constraint?

Side question: Do these “requirements” have to be REs ?

of resources, nested or otherwise.
It makes it simple represent data in a variety of ways.
It does make it harder to have arbitrary URL schema, due to the nature
of the system, and the need for everything to have a unique URL for
performing operations on.

Trade-offs :-/

So for a wiki with URL requirements such as yours, being non-RESTful
probably makes more sense. Although, if you did still want to be
RESTful, a RESTful backend, with the full and unambiguous, though
perhaps wasteful, REST routing of “topics/:topic_id/pages/:page_id”.
This could be under an ‘/api/’ namespace, or something of that
nature. The public requests pages with the /:topic/:page/:action
routing, but the forms all POST/PUT/DELETE to the appropriate REST
controller. There would be the need for some small logic used to
correctly find the page depending on which route was used, but it
wouldn’t be complicated.

I’ll put that on the queue for a later revision.

Which, reading your email more closely up, you considered.

Or just not use REST for this application. It isn’t for everything.

You’ve been patient and helpful.
I hope others have benefited from this thread.


“The Singapore government isn’t interested in controlling information,
but wants a gradual phase-in of services to protect ourselves. It’s not
to control, but to protect the citizens of Singapore. In our society,
you can state your views, but they have to be correct.”

  • Ernie Hai, coordinator of the Singapore Government Internet Project

Hi guys,

I was rewatching the Railsconf 2006 keynote from David and its all about
REST.
He talks about the implementation of REST in combination with has_many
:through.
I think its a very good talk if you want to know more about REST.
Even without the slides you can follow a long quite well.
It gives a clear insight on how he was thinking at the time.

Its up for grabs here.
http://blog.scribestudio.com/pages/rails/

You want the David Heinemeier H. download.
And do yourself a favor and watch Martin F…

Now don’t go hammer the server all at once :slight_smile:

Regards.

Peter D.
http://www.railstation.eu/blog

PS
I will post this in ‘REST Style’ and ‘WHY Rest’

On Jan 7, 1:57 pm, Anton J Aylward [email protected] wrote:

Thanks.

There, a pastie should avoid the confusion and formatting:

http://pastie.caboo.se/136143

end

In our project model means that the name is used instead of the id
number for any generated links,

Which I strongly advocate for both security reasons (see other thread)
and user intelligibility.

Yes, it does aid in the readability, and I generally do use ‘name’-
type URLs when I make applications, REST non-withstanding. The
security aspect I am less sold on. Not, I should hasten to add that I
think security is bad, just that in many cases, the resources/pages/
whatever you want to call them already have a publically avaiable
indexes and so it’s rather trivial to iterate over all of them
anyway.

I won’t post the full routing list, as it is rather long, but I will
pull out two lines from it:

Perhaps you could explain WHY it has to be long.
As I said, my ‘old’ way doesn’t make the routing long.

Well, it’s the REST that makes it so long (essentially)
Or more specifically, connecting things such that the four HTTP verbs
are mapped to appropriate URLs and Controller methods, e.g. GET
matched to show, DELETE mapped to destroy, etc.
If you used your old method, but still wanted to REST, then you would
need a lot of “if request.post?” “if request.put?” “if request.get?”
etc. in your controller methods.
In a RESTful controller, you have a more complex routing and several
small methods.

???
Only a problem if the spec requires that the UI has that.
Things like generating html select lists can still be one ‘internally’.
If its not a requirement its not a problem, and for my design its not a
requirement. Lists of topics in a web are handled differently since
they have to have metadata, links and access control applied. Its a
design difference.

Yes, I’m making a ‘virtue out of a necessity’.

Well, when I said ‘impossible’ I was talking within the constraints of
REST, at least as I understand it, rather than ‘impossible in the
grand scheme of things’. In REST, the project is not the list of its
subtasks, they are separate entities, and so should be ‘GETable’
separately, hence they should have individual URLs.

[SNIP]

Some Wikis are obsessive about having EVERYTHING as a wiki page, login,
signup, creating new webs, changing access control. Personally I see
those as ‘out of band’ of the working with the wiki pages. So for me,
its not a problem.

And slotting /web/:webname in as an admin function is a easy way for me
to segue into using REST.

See the end of the email for comments on that, I orginally missed it
up here.

 :requirements => {

for where its appropriate.

Can these requirements be re-mapped?

Well, keeping them within the routing is probably a good thing, but
you probably also want to add them as validations to the Web / Topic
model
With:

def Topic < ActiveRecord::Base

validates_format_of :name, :with => /([A-Z][a-z]+){2,}/

validates_uniqueness_of :name

end

Or similar, so that when people create invalid names, they can’t,
rather than creating a page they subsequently can’t access.

Or if monkeying around in the actionpack source isn’t what you want,

At my level of experience with it, it feels a bit daunting.

That’s no excuse. :wink:
Looking for that routing code was the first time I really have tried
hacking at the Rails source.

hook up all your routes manually in routes.rb. The full REST routing
for a single resource is 14 routes,

OUCH!

ARRGH! Wrapping confusion! Again.

I am most sorry about that. It seems that if you go over the line
limit, it’s all treated as a paragraph and wrapped together.

map.projects ‘/’, :controller => ‘projects’,
:action => ‘index’, :conditions => { :method => :get }

map.project ‘/:id’, :controller => ‘projects’,
:action => ‘show’, :conditions => { :method => :get }

and so on, changing the action and condition as appropriate.

I should note here that it is actually 7 ‘normal’ routes, and then 7
‘formatted’ routes, for providing xml, yaml, etc. representations of
the data.

One of the benefits being touted for REST is that it makes things
simpler. But what I’m seeing is that for what I’m doing it makes it
more complicated.

Well, it depends.
It makes it simple to logically extract information from a collection
of resources, nested or otherwise.
It makes it simple represent data in a variety of ways.
It does make it harder to have arbitrary URL schema, due to the nature
of the system, and the need for everything to have a unique URL for
performing operations on.

So for a wiki with URL requirements such as yours, being non-RESTful
probably makes more sense. Although, if you did still want to be
RESTful, a RESTful backend, with the full and unambiguous, though
perhaps wasteful, REST routing of “topics/:topic_id/pages/:page_id”.
This could be under an ‘/api/’ namespace, or something of that
nature. The public requests pages with the /:topic/:page/:action
routing, but the forms all POST/PUT/DELETE to the appropriate REST
controller. There would be the need for some small logic used to
correctly find the page depending on which route was used, but it
wouldn’t be complicated.

Which, reading your email more closely up, you considered.

Or just not use REST for this application. It isn’t for everything.

Regards,
Jonathan

Thank you. Much appreciated.
That’s the rake output?
What’s the input?

I was sure I said, but anyway

That is the output of ‘rake routes’ (which you will need to be using
rails 2.0 to use - I think that’s the first gem it appeared in,
anyway) when my routes.rb consisted of:

map.resources :projects

And I had done the bit of monkey patching I pasted into an earlier
email. ( reproduced in this pastie for future reference, and syntax
highlighting. Parked at Loopia ).

I would be grateful if someone more experienced with rails could
suggest a better place to put this than the top of routes.rb

[Massive snipping]

I could have just use

validates_format_of :name, :with => /([A-Z][a-z]+){2,}/

http://CamelName/Noncamelname
http://nonCamelName/Noncamelname
http://Noncamelname/nonname

and they don’t even touch the controller.

I see this as pushing error checking back as early in the process as
possible.

Oh, no. Sorry, I should have been more positive in my agreement/
endorsement, rather than ‘is probably a good thing’.
I fully agree, keeping them in the routing is a good thing, and
catching the errors earlier rather than later is a good thing. Though
I think that catching them later would allow you to be more specific
with an error, should that be your desire.

I was just pointing out the importance of also having some model
validations, so that people couldn’t make pages they can’t access (and
because of that, probably can’t delete).

Funny you should mention it, but … no. :wink:
Though messing in the rails source is /probably/ less dangerous than
brain surgery.

Looking for that routing code was the first time I really have tried
hacking at the Rails source.

I’ll stick to OS and compilers :slight_smile:

I think I will leave that to you. :slight_smile:

map.projects ‘/’, :controller => ‘projects’,
:requirements => { :web => /[A-Z][a-z]+/ }

for this? That the id-as-name has to meet some pattern or other
constraint?

Well, according to the docs, yes. It’s :requirements , the same as
for normal routes.

map.project ‘/:id’, :controller => ‘projects’,
:action => ‘show’, :conditions => { :method => :get },
:requirements => { :id => /[A-Z][a-z]+/ }

Side question: Do these “requirements” have to be REs ?

And, yes, they do. So far as I know, anyway.

[–snip–]

Most things are in web design, no? I mean, if there weren’t there
wouldn’t be so many jobs going round, as people would be much better
placed to get it right all the time.

[–snip–]

Or just not use REST for this application. It isn’t for everything.

You’ve been patient and helpful.
I hope others have benefited from this thread.

Well, I’m glad I could help you at least.

Regards,
Jonathan