# in routes.rb MyAwesomeSite::Application.routes.draw do namespace :api do namespace :v1 do resources :topics end end end # in app/controllers/api/v1/topics_controller.rb class API::V1::TopicsController < API::V1::APIController def create respond_with Topic.create(params[:topic]) end end This unfortunately won''t work, as it is going to complain about the missing topic_url helper. Instead I''ll have to do this: class API::V1::TopicsController < API::V1::APIController def create topic = Topic.create(params[:topic]) respond_with topic, location: api_v1_topic_url(topic) end end But this still won''t work, because when there are validation errors in topic, api_v1_topic_url will raise an exception. So you''ll need… class API::V1::TopicsController < API::V1::APIController def create topic = Topic.build(params[:topic]) if topic.save respond_with topic, location: api_v1_topic_url(topic) else respond_with topic end end end …which almost defeats the purpose of using respond_with in the first place. Did I miss any obvious solution? If not, I''d like to see improve this. I have a few ideas: 1. In the URL helpers, return nil instead of raising an exception 2. Accept a proc for the location option in respond_with. Since respond_with won''t even look at the location option when there are errors in the object passed in, the proc will only be called when the object was saved successfully and thus avoids the exception in the url helper: class API::V1::TopicsController < API::V1::APIController def create topic = Topic.create(params[:topic]) respond_with topic, location: ->{ api_v1_topic_url(topic) } end end 3. Respect the controller''s namespace when constructing the location object, so it will try to use api_v1_topic_url, api_topic_url and topic_url in that order. My favourite is #3, but I''d have to do some research to find out how to do this or if it''s possible at all. Any comments / feedback / pointers are welcomed! Godfrey -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
Hi, This seems to work well for me: def create respond_with :api, :v1, Topic.create(params[:topic]) end Is this the behavior you want? The documentation for respond_with is pretty detailed and mentions this solution (under nested resources): http://apidock.com/rails/ActionController/Responder Your 3rd suggestion is something that could be done by writing a custom responder if this seems like boilerplate to you. Looking at your code, your model is not namespaced, so technically it is behaving correctly. If it were namespaced under Api::V1 same as the controller it would just work without any hints (because the path is generated based on model_name). On Wed, Aug 29, 2012 at 11:44 PM, Godfrey Chan <godfreykfc@gmail.com> wrote:> # in routes.rb > > MyAwesomeSite::Application.routes.draw do > namespace :api do > namespace :v1 do > resources :topics > end > end > end > > # in app/controllers/api/v1/topics_controller.rb > > class API::V1::TopicsController < API::V1::APIController > def create > respond_with Topic.create(params[:topic]) > end > end > > This unfortunately won''t work, as it is going to complain about themissing> topic_url helper. > > Instead I''ll have to do this: > > class API::V1::TopicsController < API::V1::APIController > def create > topic = Topic.create(params[:topic]) > respond_with topic, location: api_v1_topic_url(topic) > end > end > > But this still won''t work, because when there are validation errors in > topic, api_v1_topic_url will raise an exception. So you''ll need… > > class API::V1::TopicsController < API::V1::APIController > def create > topic = Topic.build(params[:topic]) > if topic.save > respond_with topic, location: api_v1_topic_url(topic) > else > respond_with topic > end > end > end > > …which almost defeats the purpose of using respond_with in the firstplace.> > Did I miss any obvious solution? If not, I''d like to see improve this. I > have a few ideas: > > 1. In the URL helpers, return nil instead of raising an exception > > 2. Accept a proc for the location option in respond_with. Sincerespond_with> won''t even look at the location option when there are errors in the object > passed in, the proc will only be called when the object was saved > successfully and thus avoids the exception in the url helper: > > class API::V1::TopicsController < API::V1::APIController > def create > topic = Topic.create(params[:topic]) > respond_with topic, location: ->{ api_v1_topic_url(topic) } > end > end > > 3. Respect the controller''s namespace when constructing the locationobject,> so it will try to use api_v1_topic_url, api_topic_url and topic_url inthat> order. > > My favourite is #3, but I''d have to do some research to find out how to do > this or if it''s possible at all. Any comments / feedback / pointers are > welcomed! > > Godfrey > > > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Core" group. > To post to this group, send email to rubyonrails-core@googlegroups.com. > To unsubscribe from this group, send email to > rubyonrails-core+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/rubyonrails-core?hl=en.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.
> def create > respond_with :api, :v1, Topic.create(params[:topic]) > endThat works great! Didn''t make the connection between singleton resources and namespaces the first time I saw it. I''m quite happy with this solution!> Looking at your code, your model is not namespaced, so technically it is behaving correctly. If it were namespaced under Api::V1 same as the controller it would just work without any hints (because the path is generated based on model_name).I understand that the path is currently generated based on model_name, but I wasn''t sure if this is the most sensible default, since this code resides in the controller, it could make use of the information to make a better guess at the naming (it seems quite unlikely to cause problem, because if your models are namespaced, chances are your controllers are also namespaced, but the reverse is not typically true outside of engines). I guess I''d try implementing the custom responder in my app and see how that goes, and if that worked out well for me I might open a PR and see what others think. Thanks again for your help, really appreciate it! Godfrey -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com. To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en.