def make_default
old_default_image = Image.find_by_default(true).update_attribute(“default”,false)
image = Image.find(params[:id])
image.update_attribute(“default”,true)
flash[:notice] = “Image has been made default.”
redirect_to images_path
end
Don’t be too paranoid about staying restful, each controller might have it’s own special method that does something “The Seven” don’t.
You use the update method in the image controller.
The link "Set as Default" should update the image default attribute
and then redirect to the products view
I was thinking that I might need to go down this route (no pun
intended =D ) but I was thinking that there might be a way do this
using the update method.
Ryan, why should he make an additional method if he can use the update
method of the imagecontroller?
The update method expects a PUT (form) and not a GET (link). I suggest
you use a form with a button or imagebutton.
If you are using rails 2.0 this will look like
<% form_for image do |f| %>
<%= f. hidden_field(:default, true) %>
<%= submit_tag "Change to default" %>
<% end %>
I believe that you would want :member => :put, rather
than :member=>:update. The value part of the hash refers to the http
verb that should be used with the member (or collection) action.
Perhaps a better solution, if you want to use a named RESTful route,
would be to use nested routes:
map.resources :products do |product|
product.resources :images, :collection=>{:set_default=>:put}
end
If you think about the problem more abstractly, what you are trying to
accomplish is to set a default image from among the collection of
images associated with a particular product. The important point to
realize is that, from the 20,000 foot view, you are doing something to
the _collection_, not to a specific object within the collection. If
you organize your resources as above you can choose to refactor your
"default image" process later. Even without considering the
refactoring, though, it's a better solution because it takes into
account that "set_default" with some image id means that you intend to
effect _two_ objects in the collection (the named one and the previous
one).
This solution puts much too much business logic in the controller.
Consider creating an instance method on your Product that sets the
default image by processing a hash (not coincidentally params is a
hash). Among the benefits, you'll be able to introduce unit testing
to make sure it works in every scenario AND you can reuse the code
more easily (e.g., you decide that the default image should always be
the first image added to the collection until otherwise specified by
the user).
I am actually using nested resources. I ended up using the update
action that already is one of the 7 restful actions. I added code to
check if there is an existing default image and to change that image
to be non-default.
I'm not understanding why this is not a good way to go. Can you help
me understand?