class EstablishmentsController < ApplicationController
resources_controller_for :establishments
def find_resource(id = params[:id])
resource_service.find_by_slug id
end
end
so "establishments/cafes" works just fine. But when i do the same for
Places controller, and try to go to "establishments/cafes/places/
myplace" it loads "Establishment" by id via
"Ardes::ResourcesController::Specification::find_resource". I tried
"find" key but no success still - works on usual resources, not on
enclosing ones.
What can i do to make RC respect the slugs?
> What can i do to make RC respect the slugs?
If your establishments is always at the 'top' level, you should be
able to this:
map_resource :establishment do
Establishment.find_by_slug(params[:establishment_id])
end
If establishments is nested, then do this
map_resource :establishment do
enclosing_resource.establishments.find_by_slug(params[:establishment_id])
end
Or, if either of these might be the case:
map_resource :establishment do
if enclosing_resource
enclosing_resource.establishments.find_by_slug(params[:establishment_id])
else
Establishment.find_by_slug(params[:establishment_id])
end
end
This map_resource should be put in any controller that has
establishments as an enclosing resource - you can repeat it for any
such controller, or put it in ApplicationController (or a mixin that
you include in the relevant controllers)
Let me know if this works for you.
Cheers,
Ian
Or, more succinctly (but maybe more golf like)
map_resource :establishment do
(enclosing_resource ? enclosing_resource.establishments :
Establishment).find_by_slug params[:establishment_id]
end
cheers,
Ian
--
Argument from Design--We build web applications
Western House 239 Western Road Sheffield S10 1LE UK
Mobile: +44 (0)797 4678409 | Office: +44 (0)114 2667712
<http://www.ardes.com/> | <http://blog.ardes.com/>
Basically, it works for /establishments/cafes/places/myplace. but it
kills /establishments/cafes/places/. According to SQL Log it tries
to :
SELECT * FROM places WHERE (places.establishment_id = 2) AND
(places.`slug` IS NULL) LIMIT 1
which is obviously wrong.
What can be done in this case?
Sorry if this sounds a bit rude, but why is this stuff so hard to
implement? I mean, i thought this would work as is. Isn't it possible
just to call find_resource of enclosing controller?
> SELECT * FROM places WHERE (places.establishment_id = 2) AND
> (places.`slug` IS NULL) LIMIT 1
This suggests that params[:establishment_id] is nil. Can you
investigate whether something in your setup might be causing this?
Or, perhaps you've found a bug - could you send me some more details of
the code, log and stacktrace.
> Sorry if this sounds a bit rude, but why is this stuff so hard to
> implement?
find_by_slug is an edge case for RC, a lot of people find RC pretty
easy to use for the main problem it sets out to solve. But there's
always room for improvement (tested patches always welcome), and I
welcome the issue report.
Cheers,
> find_by_slug is an edge case for RC, a lot of people find RC pretty
> easy to use for the main problem it sets out to solve. But there's
> always room for improvement (tested patches always welcome), and I
> welcome the issue report.
I will try to do what I can, although as I said I am not very
experiences with R & RoR
I changed my "find_resource" definition in "resources_controller.rb"
to this:
def find_resource(id = params[:id])
resource_service.send resource_service.from_param || :find, id
end
and "find_resource" definition in "specification.rb" to this:
def find_resource
(enclosing_resource || klass).send(
(enclosing_resource || klass).from_param || :find,
controller.params[key]
)
end
OK, Not very cute, but atleast now I can do this in model:
def to_param
slug
end
def self.from_param
:find_by_slug
end
and it works just fine!
Hope you find a better way to do this, but if there're anyone who
wants slug their RC controllers, use these two hacks :)
Just come to RC today, looks very useful:
On Oct 6, 10:34 am, Ian White <ian.w.wh...@gmail.com> wrote:
> > So I have "establishments" & "places" controllers. I want to use slugs
> > instead of ids, so it's:
> > What can i do to make RC respect the slugs?
>
I am trying to do this as well. I have
map.resources :users do |users|
users.resources :contents
end
I use User#to_param to return the login name so that my urls look
like:
/users/matt/contents/<id>
In ApplicationController I have:
map_resource :user do
User.find_by_login( params[:id] )
end
However I still get:
Couldn't find User with ID=matt
I went back and added a puts into that map_resources block but it
doesn't get output suggesting that something is going wrong there.
The complication is that I am using Rails 2.0PR. From the notes about
using version <410 with 1.2.3 I guess RC should be edge compatible but
maybe that was a bad assumption on my part?
Regards,
Matt
On Oct 11, 11:54 am, Matt Mower <matt.mo...@gmail.com> wrote:
> map_resource :user do
> User.find_by_login( params[:id] )
> end
>
It's a wild stab in the dark but I am guessing this relates to
resources_controller.rb:614
return if to_spec && to_spec.segment == segment
which, according to my debugging, is true (since the segment inferred
from map_resouce is 'users') so that the custom
resource_specification_map entry is never referenced or load_into
called.
Regards,
Matt
Welcome to the RC group!
> map.resources :users do |users|
> users.resources :contents
> end
What you want should be possible - but maybe you've found a bug. SO
I'll spell out what's needed, so that you can help me verify if it is
a bug.
> map_resource :user do
> User.find_by_login( params[:id] )
> end
This looks right to me - it specifies the :user enclosing_resource, so
do this in the contents controller (or app)
The UsersController however needs something else - you'll need to
either do this:
resources_controller_for :users do
User.find_by_login( params[:id] )
end
or this:
def find_resource(id = params[:id])
resource_service.find_by_login(id)
end
Let me know how this goes.
> which, according to my debugging, is true (since the segment inferred
> from map_resouce is 'users') so that the custom
> resource_specification_map entry is never referenced or load_into
> called.
You;re right - but that's intentional (at the moment) - map resource
is for enclosing resources only.
But, maybe I should make the map_resource specifications available to
the main resource as well.
On Oct 11, 7:00 pm, "Ian White" <ian.w.wh...@gmail.com> wrote:
> > which, according to my debugging, is true (since the segment inferred
> > from map_resouce is 'users') so that the custom
> > resource_specification_map entry is never referenced or load_into
> > called.
>
Just back at home so I'm addressing your posts in the inverse order
(since this one is easier to grok):
> You;re right - but that's intentional (at the moment) - map resource
> is for enclosing resources only.
>
Maybe it's a terminology thing but I would say user *is* the enclosing
resource, i.e.
users have content
user: enclosing
content: enclosed
Am I misunderstanding?
> But, maybe I should make the map_resource specifications available to
> the main resource as well.
>
Regards,
Matt
My other post was directed at trying to figure out whether you were
getting these problems in the user, or content controller.
So, let me know if the other post makes sense, and solves your probs or not.
On Oct 11, 6:59 pm, "Ian White" <ian.w.wh...@gmail.com> wrote:
> The UsersController however needs something else - you'll need to
> either do this:
>
> resources_controller_for :users do
> User.find_by_login( params[:id] )
> end
>
I tried this.
> def find_resource(id = params[:id])
> resource_service.find_by_login(id)
> end
>
And then this. I still get the "Couldn't find User with ID=matt" error
when accessing:
/users/matt/contents
Regards,
Matt
p.s. Do you use IM or IRC?
On Oct 12, 9:33 am, Matt Mower <matt.mo...@gmail.com> wrote:
> > resources_controller_for :users do
> > User.find_by_login( params[:id] )
> > end
>
> I tried this.
I also tried putting a debugging puts in that block and, again, there
was no output so it appears that this block never gets executed
either.
Regards,
Matt.
Since this case has come up a couple of times, I'm adding it to the
spec suite. Then we can make sure we're on the same page. Will post
when that's done.
Cheers,
Ian
(from the CHANGELOG)
* added specs for when you want to find_by_(something other than id)
(users,
addresses, interests)
Fixed a bug where the resource mapping was using name instead of
segment to
match when a map should be used (this meant mapping didn't work for
non
singleton resources)
Thanks to Inviz <invi...@gmail.com> and Matt Mower
<matt.mo...@gmail.com>
in http://groups.google.com/group/resources_controller/browse_thread/thread/b71b2ce196a09d15
for the bug reports
>From the docs - (which will update online within the hour)
using non standard ids
Lets say you want to set to_param to login, and use find_by_login for
your users in your URLs, with routes as follows:
map.reosurces :users do |user|
user.resources :addresses
end
First, the users controller needs to find reosurces using
find_by_login
class UsersController < ApplicationController
resources_controller_for :users
protected
def find_resource(id = params[:id])
resource_service.find_by_login(id)
end
end
This controller will find users (for editing, showing, and destroying)
as directed. (this controller will work for any route where user is
the last resource, including the /users/dave route)
Now you need to specify that the user as enclosing resource needs to
be found with find_by_login. For the addresses case above, you would
do this:
class AddressesController < ApplicationController
resources_controller_for :addresses
nested_in :user do
User.find_by_login(params[:user_id])
end
end
If you wanted to open up more nested resources under user, you could
repeat this specification in all such controllers, alternatively, you
could map the resource in the ApplicationController, which would be
usable by any controller
If you know that user is never nested (i.e. /users/dave/addresses),
then do this:
class ApplicationController < ActionController::Base
map_resource :user do
User.find(params[:user_id])
end
end
or, if user is sometimes nested (i.e. /forums/1/users/dave/addresses),
do this:
map_resource :user do
((enclosing_resource && enclosing_resource.users) ||
User).find(params[:user_id])
end
Your Addresses controller will now be the very simple one, and the
resource map will load user as specified when it is hit by a route /
users/dave/addresses.
class AddressesController < ApplicationController
resources_controller_for :addresses
end