The following code:
map.resources :users, :has_many => :items
Could be written like this in a block:
map.resources :users do |user|
user.resources :items
end
How could I write the following code in a block?
map.resources :users, :member => { :start => :post }
Also, where could I find documentation on writing routes in blocks?
The Routes Documentation does not seem to show it.
Thank you!
Rails 2.x doesn't allow you to use blocks for member definition.
With Rails 3.x you can write
resources :users do
member do
post :start
end
end
You can do it like so in Rails 2 (2.3.5 is the version I tested it on):
map.resources :users, :member => { :start => :post } do |user|
user.resources :items
end
From here: http://www.engineyard.com/blog/2010/the-lowdown-on-routes-in-rails-3/
Related
I need to add some collection routes for a nested resource. I have a subscription controller and I need two new methods to add here. change_plan and update_plan
Basically I need the urls looks like;
http://localhost:3007/admin/accounts/1/subscriptions/7/change_plan
http://localhost:3007/admin/accounts/1/subscriptions/7/update_plan
So where to add change_plan and update_plan? this is what I have so far.
map.namespace :admin do |admin|
admin.resources :payments
admin.resources :accounts, :collection=>{:profile=>:get}, :has_many => [:payments,:subscriptions]
end
Thanks for any help.
Use the alternative syntax for has_many:
admin.resources :accounts, :collection=>{:profile=>:get} do |account|
account.resources :subscriptions, :member => { :change_plan => :get, ... }
...
end
I'm new to testing, and I'm having some difficulties trying to run a functional test.
I've a messages_controller, and a user_controller here.
in the routes, I've defined that the users resources has_many message resources.
Now I'm trying to run a simple test in the messages controller:
def test_index
get :index, { :user_id => 1 }
assert_template 'index'
end
But get a routing error from rails, that he cant find a route to messages. I don't want to include a route to messages only because of the tests. How can I tell the test that he must access from the /users/messages url?
the full routes.rb:
ActionController::Routing::Routes.draw do |map|
map.login 'login', :controller => :user_sessions, :action => :new
map.logout 'logout', :controller => :user_sessions, :action => :destroy
map.signin 'signin', :controller => :users, :action => :new
map.connect 'search/:action/:word', :controller => :search
map.connect 'search/:word', :controller => :search, :action => :index
map.resources :forums do |forums|
forums.resources :forum_posts, :collection => {:preview => :post }, :as => :posts do |post|
post.resources :forum_posts, :as => :reply
post.resources :reports
end
end
map.resources :newsitems, :as => :news do |news|
news.resources :comments do |comment|
comment.resources :reports
end
end
map.resource :user_sessions
map.resources :users,
:as => :profiles,
:controller => :profiles,
:has_many => [ :messages ]
map.resource :profiles
map.resource :me,
:controller => :me,
:has_many => [ :messages ]
map.resources :comments, :has_many => [ :reports ]
map.resources :forum_posts, :has_many => [ :reports ]
map.resources :reports
map.home '/', :controller => :home
map.root :controller => :home
map.namespace :admin do |admin|
admin.namespace :forum do |forum|
forum.resources :categories
forum.resources :posts
forum.resources :forums
forum.root :controller => :home
end
admin.resources :notices
admin.resources :users
admin.workflow 'workflow/:action', :controller => :workflow
admin.resources :newsitems
admin.resources :reports
admin.resources :comments
admin.root :controller => :home
end
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
UPDATE
I've noticed that every functional test get a routing error. Even the simpliests ones like newsitem. I've no idea why.
I recreated your scenario in a blank rails app with the routing code and and test you specified, and it worked without a problem, as it should. I'll paste my controller code here since that's the only part you left out:
class MessagesController < ApplicationController
def index
#messages = User.find(params[:user_id]).messages
end
end
If yours is doing basically the same thing, then a routing issue could be caused by a conflict in your routing file, which is what I suspect might be the case. Can you post it? FYI, I wrote an article on testing your routes, and that would be a very good idea because it would catch routing errors early, before they interfere with controllers.
Anyway, if you can post your routes I can take a look.
UPDATE: After looking at your routes, there are a couple conflicts. You can have messages as a sub-resource of more than one other resource, but in your messages controller you're going to have to account for the possibility of either a params[:me_id] or params[:profile_id]. It looks like they're both really the user model underneath, so it can be as simple as:
#user = User.find(params[:me_id] || params[:profile_id])
and you'll probably want to abstract that out into a method you call with before_filter.
The other issue is that you have two overlapping profiles routes, and I'm not sure why. I don't think it's a routing error in the test, because tests bypass the routing engine anyway. I think it's an error in the index view, because it probably contains links to messages with improperly formatted urls. If you have a link to a message, for instance, and you have a #profile object, then you'll need to call them like this:
<%= link_to message.name, profile_message_path(#profile, #message) %>
However, if you're using non-nested paths like message_path(#message), it will fail because there are no non-nested message routes.
It was a problem in my "journey" gem. They made routes more stricter in journey 1.0.4 which only show up on "test" environment. It is good for "developement" and "production".
** Ensure you are using exactly the same parameters as declared in routes **
Either add:
get :index, :locale => "en"
or in your Gemfile update:
gem 'journey', '1.0.3'
The second solution is a workaround for time being. Ideally you should be testing your routes will all exact params. Journey 1.0.4 is a lot stricter
I have a controller which has a method called history
class UsersController < ApplicationController
def history
User.return_history(params[:id])
end
end
I have the following in my routes.rb file
map.resources :users, :shallow => true do |user|
user.resources :friends, :shallow => false
user.resources :posts, :collection=>{:no_access => :get}
user.resources :photos
end
How do I try to Ajax call the history method of the users_controller.rb? Using link_to_remote in the following way
link_to_remote 'History', :url=>history_user_path(#user), :update=>"history", :method=>'get'
throws me an error saying history_user_path() not found. How can this be? edit_user_path() shows no error and edit is not even explicitly defined in the User.rb file. Thanks.
mapresources :users creates a bunch of url/path helper methods, including edit_users_path. If you need others. you've got to add it as either a :member, or :collection option for map.resources.
This will let you do what you want:
map.resources :users, :shallow => true, :member => {:history => :get} do |user|
user.resources :friends, :shallow => false
user.resources :posts, :collection=>{:no_access => :get}
user.resources :photos
end
This is an excerpt from my config/routes.rb file:
resources :accounts do |account|
account.resource :profile, :except => [:new, :create, :destroy]
account.resources :posts,
:collection => { :fragment => :get },
:has_many => [:comments, :likes]
# even more code
end
I would like that each nested resource to be loaded from from the account namespace such as Account::PostsController instead of PostsController.
Using resources :accounts, :namespace => 'account' tries to load AccountPostsController.
Trying to nest the structure doesn't really work all that well:
map.namespace :account do |account|
..
end
The previous code will load the files from the locations I want, however it does add the namespace to the url and the generated paths so I'll have methods such as account_account_posts_url and similar paths.
Another alternative is to use something like:
account.resource :profile, :controller => 'account/profile'
I really don't like this as it involves both code duplication and forces me to remove some of the rails magic helpers.
Any thoughts and suggestions?
Changing my routes.rb and running rake routes I came up with the following:
map.resources :accounts do |accounts|
accounts.namespace :account do |account|
account.resource :profile, :except => [:new, :create, :destroy]
end
end
This gets you what you want. The correct url and pointing to account/... controller.
See Rails Routing for more detailed info and options on what can be done with Rails Routes.
So what's specifically wrong with namespacing? I think this is what you're trying to do:
map.namespace :account do |account|
account.resource :profile
end
This will try to load the controller at app/controllers/account/profiles_controller.rb and will generate routes such as account_profile_path.
Updated based on comment:
map.resources :accounts do |account|
account.resource :profile
end
Will give you /accounts/22/profile.
Projects have many tasks and a task has a custom RESTful action called 'approve'.
I'm expecting the helper to look something like this approve_project_task_url
This isn't working for me:
map.resources :projects,
:has_many => :tasks,
:member => { :approve => :post }
I once had the same problem but I never searched long and hard for a fix. Instead I just opted for the older style which since then I've always used:
map.resources :projects do |project|
project.resources :tasks, :member => {:approve => :post}
end
That will give you your required approve_project_task_url(#project, #task) routes/helpers.
I guess you may already know this approach? If so and you don't like it hopefully I'll learn something from your other responses :)
**This is syntax correction to above solution**
map.resources :projects do |project|
project.resources :tasks, :member => {:approve => :post}
end