Rails 3 Routing Resources with Variable Namespace - ruby-on-rails

Is it possible to have a variable namespace? I have restful resources like the following:
resources :articles
resources :persons
But I need to scope these inside a variable namespace, such that it responds to URLs of the form:
':edition/:controller/:action/:id'
for example:
/foobar/article/edit/123 or /bazbam/person/edit/345
for each of the resources. Is this possible with the resources method, or must I hand-craft these? I will not know the possible values for :edition ahead of time; these get looked up in a before_filter in my ApplicationController.
Is this all I need to do?
scope ':edition' do
resources :articles
resources :matches
resources :teams
end
UPDATE: When using the scope directive above, I get routes like I want:
articles GET /:edition/articles(.:format) {:action=>"index", :controller=>"articles"}
POST /:edition/articles(.:format) {:action=>"create", :controller=>"articles"}
new_article GET /:edition/articles/new(.:format) {:action=>"new", :controller=>"articles"}
edit_article GET /:edition/articles/:id/edit(.:format) {:action=>"edit", :controller=>"articles"}
article GET /:edition/articles/:id(.:format) {:action=>"show", :controller=>"articles"}
PUT /:edition/articles/:id(.:format) {:action=>"update", :controller=>"articles"}
DELETE /:edition/articles/:id(.:format) {:action=>"destroy", :controller=>"articles"}
matches GET /:edition/matches(.:format) {:action=>"index", :controller=>"matches"}
POST /:edition/matches(.:format) {:action=>"create", :controller=>"matches"}
new_match GET /:edition/matches/new(.:format) {:action=>"new", :controller=>"matches"}
edit_match GET /:edition/matches/:id/edit(.:format) {:action=>"edit", :controller=>"matches"}
match GET /:edition/matches/:id(.:format) {:action=>"show", :controller=>"matches"}
PUT /:edition/matches/:id(.:format) {:action=>"update", :controller=>"matches"}
DELETE /:edition/matches/:id(.:format) {:action=>"destroy", :controller=>"matches"}
teams GET /:edition/teams(.:format) {:action=>"index", :controller=>"teams"}
POST /:edition/teams(.:format) {:action=>"create", :controller=>"teams"}
new_team GET /:edition/teams/new(.:format) {:action=>"new", :controller=>"teams"}
edit_team GET /:edition/teams/:id/edit(.:format) {:action=>"edit", :controller=>"teams"}
team GET /:edition/teams/:id(.:format) {:action=>"show", :controller=>"teams"}
PUT /:edition/teams/:id(.:format) {:action=>"update", :controller=>"teams"}
DELETE /:edition/teams/:id(.:format) {:action=>"destroy", :controller=>"teams"}
I'm now able to reference :edition in my ApplicationController:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate_user!
before_filter :get_edition
def get_edition
#edition = Edition.first(:conditions => { :FriendlyName => params[:edition] } )
end
end
Now I just want to make sure this is the best way to accomplish this.

Actually, you can just do the following :
my_var = "persons"
resources my_var.to_sym
The to_sym method on a string changes it to a symbol

If you don't know the possible values for edition - then you can't use namespaces which seem like they might have solved this issue.
That said, I'd just handcraft them - your case here seems like the ideal case foregoing resources and going straight to a handcrafted path.

Related

Is there a way to fix a singular controller in rails 3.1?

I accidentally generated a singular controller comm_log without 's'. 's' was added to controller name, helpers, views, specs and routes. The customer_comm_log_path(f.customer_id, f.id) seems not right.
The relation is a comm log belongs to a customer and a customer has many comm logs.
resources :customers do
resources :comm_logs
end
The output of rake routes (related) is:
comm_logs_index GET /comm_logs/index(.:format) {:controller=>"comm_logs", :action=>"index"}
comm_logs_new GET /comm_logs/new(.:format) {:controller=>"comm_logs", :action=>"new"}
comm_logs_create GET /comm_logs/create(.:format) {:controller=>"comm_logs", :action=>"create"}
comm_logs_show GET /comm_logs/show(.:format) {:controller=>"comm_logs", :action=>"show"}
comm_logs_destroy GET /comm_logs/destroy(.:format) {:controller=>"comm_logs", :action=>"destroy"}
customer_comm_logs GET /customers/:customer_id/comm_logs(.:format) {:action=>"index", :controller=>"comm_logs"}
POST /customers/:customer_id/comm_logs(.:format) {:action=>"create", :controller=>"comm_logs"}
new_customer_comm_log GET /customers/:customer_id/comm_logs/new(.:format) {:action=>"new", :controller=>"comm_logs"}
edit_customer_comm_log GET /customers/:customer_id/comm_logs/:id/edit(.:format) {:action=>"edit", :controller=>"comm_logs"}
customer_comm_log GET /customers/:customer_id/comm_logs/:id(.:format) {:action=>"show", :controller=>"comm_logs"}
PUT /customers/:customer_id/comm_logs/:id(.:format) {:action=>"update", :controller=>"comm_logs"}
DELETE /customers/:customer_id/comm_logs/:id(.:format) {:action=>"destroy", :controller=>"comm_logs"}
Is there a way to fix the singular controller? Thanks.
Try script/destroy your_controller_name using the same controller name used to create it.

How to improve a router working with namespaces having the same name as a resource

I am using Ruby on Rails 3.0.7 and I am trying to set correctly (and as well as possible) my router.
In the routes.rb file I have:
namespace :articles do
resources :categories
end
resources :articles
In order to work as expected, I must state the namespace before the resources :articles statement so that the router intercepts requests and direct these to the namespace related to articles. Otherwise (if the resources :articles is stated before of the namespace), as it is possible deduct from the above code, all requests like
<my_site>/articles/1
<my_site>/articles/new
<my_site>/articles/1/edit
...
are intercepted so that the articles namespace will be "hardly" reached. For example, if you make a request like <my_site>/articles/categories it will generate an error as the following:
ActiveRecord::RecordNotFound
Couldn't find Article with ID=categories
So, how can I handle this situation and how can I improve the router code? What do you advice about?
Running the command rake routes in my console I get this (as it is ordered):
articles_categories GET /articles/categories(.:format)
{:action=>"index", :controller=>"articles/categories"}
POST /articles/categories(.:format)
{:action=>"create", :controller=>"articles/categories"}
new_articles_category GET /articles/categories/new(.:format)
{:action=>"new", :controller=>"articles/categories"}
edit_articles_category GET /articles/categories/:id/edit(.:format)
{:action=>"edit", :controller=>"articles/categories"}
articles_category GET /articles/categories/:id(.:format)
{:action=>"show", :controller=>"articles/categories"}
PUT /articles/categories/:id(.:format)
{:action=>"update", :controller=>"articles/categories"}
DELETE /articles/categories/:id(.:format)
{:action=>"destroy", :controller=>"articles/categories"}
articles GET /articles(.:format)
{:action=>"index", :controller=>"articles"}
POST /articles(.:format)
{:action=>"create", :controller=>"articles"}
new_article GET /articles/new(.:format)
{:action=>"new", :controller=>"articles"}
edit_article GET /articles/:id/edit(.:format)
{:action=>"edit", :controller=>"articles"}
article GET /articles/:id(.:format)
{:action=>"show", :controller=>"articles"}
PUT /articles/:id(.:format)
{:action=>"update", :controller=>"articles"}
DELETE /articles/:id(.:format)
{:action=>"destroy", :controller=>"articles"}
Check this rails documentation about controller namespaces. It says you need to namespace your categories controller like Articles::CategoriesController and you need to place your categories controller under app/controllers/articles directory.

Sophisticated route and url generation in Rails

I have a group model which has_many article model. And I want to use the following url pattern "{group_id}/{article_id}".
so I wrote these route codes:
resource :groups do
resource :articles
end
match ':group_id/:id(.:format)', :to => 'articles#show', :as => :article
match ':id', :to => 'groups#show', :as => :group
But rails fail to generate correct url for group records and article records. How can I replace the automatic generated article_path and group_path to match my routes?
You're running into problems because you aren't watching out for pluralization. When you define a singular resource route, Rails doesn't treat it as a collection where you would refer to each member with an id. You instead want a plural resources for both groups and articles:
resources :groups do
resources :articles
end
Generates the following routes:
group_articles GET /groups/:group_id/articles(.:format) {:action=>"index", :controller=>"articles"}
POST /groups/:group_id/articles(.:format) {:action=>"create", :controller=>"articles"}
new_group_article GET /groups/:group_id/articles/new(.:format) {:action=>"new", :controller=>"articles"}
edit_group_article GET /groups/:group_id/articles/:id/edit(.:format) {:action=>"edit", :controller=>"articles"}
group_article GET /groups/:group_id/articles/:id(.:format) {:action=>"show", :controller=>"articles"}
PUT /groups/:group_id/articles/:id(.:format) {:action=>"update", :controller=>"articles"}
DELETE /groups/:group_id/articles/:id(.:format) {:action=>"destroy", :controller=>"articles"}
groups GET /groups(.:format) {:action=>"index", :controller=>"groups"}
POST /groups(.:format) {:action=>"create", :controller=>"groups"}
new_group GET /groups/new(.:format) {:action=>"new", :controller=>"groups"}
edit_group GET /groups/:id/edit(.:format) {:action=>"edit", :controller=>"groups"}
group GET /groups/:id(.:format) {:action=>"show", :controller=>"groups"}
PUT /groups/:id(.:format) {:action=>"update", :controller=>"groups"}
DELETE /groups/:id(.:format) {:action=>"destroy", :controller=>"groups"}
If you want to leave off the groups and articles segments you can pass :path => '' to each of the resources definitions, but you are going to have to tread carefully because any request to http://example.com/1/2 will map to an article under groups and be uninformative to end users and bots alike.

Rails nested rources and routes and how to set them up in route.rb

I think I have a handle on nested routes (great url helpers, and access and much more) and nested resources in forms with accepts_nested_attributes_for but what do I use in routes as I see both:
resources :schools do
resources :documents
end
and also
resources :schools :has_many => :documents
end
please can you tell me the difference between these.
Obviously has_many is for a one-to-many relationship. does it produce path helpers and require correct routing and for the do block what relationship does that imply, none? just path helpers (/schools/documents) and what if I want multiple resources (other than books, say documents) under schools, the first way I can add it into the do-end block but what about the second way, just two lines, one for each has_many?
Though I've read the guides and api's I don't quite get the difference/usage here and anyone that can provide a clear explanation of the distinction between the two (in the form 'a does x whereas b does y' would be great) would be much appreciated :)
Oh and of course how they relate to having the has_many in the model - so I guess these relationships can be in the model with has_many, the controller (mostly thru usage of paths) and in the view (through forms with nested attributes).
They both do the same thing, its up to you to choose which one
I prefer the do block format as its easier to read
btw with the has_many format you could do :has_many => [:docs, :otherthings] for multiple nested routes
I think the has_many syntax was something added to Rails 2 as a shorthand for those that didn't like the block syntax. You can see a blog post about it here. I just tried it and it seems that Rails 3 ignores the has_many option. So the output for me was:
resources :schools do
resources :documents
end
created the routes:
school_documents GET /schools/:school_id/documents(.:format) {:action=>"index", :controller=>"documents"}
POST /schools/:school_id/documents(.:format) {:action=>"create", :controller=>"documents"}
new_school_document GET /schools/:school_id/documents/new(.:format) {:action=>"new", :controller=>"documents"}
edit_school_document GET /schools/:school_id/documents/:id/edit(.:format) {:action=>"edit", :controller=>"documents"}
school_document GET /schools/:school_id/documents/:id(.:format) {:action=>"show", :controller=>"documents"}
PUT /schools/:school_id/documents/:id(.:format) {:action=>"update", :controller=>"documents"}
DELETE /schools/:school_id/documents/:id(.:format) {:action=>"destroy", :controller=>"documents"}
schools GET /schools(.:format) {:action=>"index", :controller=>"schools"}
POST /schools(.:format) {:action=>"create", :controller=>"schools"}
new_school GET /schools/new(.:format) {:action=>"new", :controller=>"schools"}
edit_school GET /schools/:id/edit(.:format) {:action=>"edit", :controller=>"schools"}
school GET /schools/:id(.:format) {:action=>"show", :controller=>"schools"}
PUT /schools/:id(.:format) {:action=>"update", :controller=>"schools"}
DELETE /schools/:id(.:format) {:action=>"destroy", :controller=>"schools"}
while
resources :schools :has_many => :documents
created the routes:
schools GET /schools(.:format) {:action=>"index", :controller=>"schools"}
POST /schools(.:format) {:action=>"create", :controller=>"schools"}
new_school GET /schools/new(.:format) {:action=>"new", :controller=>"schools"}
edit_school GET /schools/:id/edit(.:format) {:action=>"edit", :controller=>"schools"}
school GET /schools/:id(.:format) {:action=>"show", :controller=>"schools"}
PUT /schools/:id(.:format) {:action=>"update", :controller=>"schools"}
DELETE /schools/:id(.:format) {:action=>"destroy", :controller=>"schools"}
I think the real answer to your question is that those are/were supposed to do the same thing, just with different syntax.

Problem with rails routing

I have the following in my routing config:
resources :users do
resources :apps, :controller => :user_apps
end
rake routes includes the following:
user_apps GET /users/:user_id/apps(.:format) {:action=>"index", :controller=>"user_apps"}
user_apps POST /users/:user_id/apps(.:format) {:action=>"create", :controller=>"user_apps"}
new_user_app GET /users/:user_id/apps/new(.:format) {:action=>"new", :controller=>"user_apps"}
edit_user_app GET /users/:user_id/apps/:id/edit(.:format) {:action=>"edit", :controller=>"user_apps"}
user_app GET /users/:user_id/apps/:id(.:format) {:action=>"show", :controller=>"user_apps"}
user_app PUT /users/:user_id/apps/:id(.:format) {:action=>"update", :controller=>"user_apps"}
user_app DELETE /users/:user_id/apps/:id(.:format) {:action=>"destroy", :controller=>"user_apps"}
However, when I try to access eg user_apps_path(1,2) I get /users/1/apps.2 rather than /users/1/apps/2.
Where am I going wrong?
I'm using rails 3.
The correct route is user_app_path(1,2) The pluralized version goes to the index action, making the second argument the format / extension of the request.

Resources