Testing a named route in rails - ruby-on-rails

I have the following route defined in routes.rb:
map.search 'fuzzyleads/search/:url', :controller => 'fuzzyleads', :action => 'search', :method => 'get'
The problem is that I cannot get this test to pass:
def test_search_route
assert_generates "fuzzyleads/search/someurl", { :controller => "fuzzyleads", :action => "search", :url => "someurl" }
end
It does not like the url part, I get the following error:
found extras <{:url=>"someurl"}>, not
<{}>
I have no idea why, can anyone see what I am doing wrong?

The output of rake routes would help us make a little better guess. Here's how I tested using rails-2.3.8:
(1) Added your route as the second route in config/routes.rb
(2) Created the following rspec test:
it "should have valid route for fuzzyleads search" do
route_for(:controller => 'fuzzyleads', :action => 'search', :url => 'someurl').should ==
"/fuzzyleads/search/someurl"
end
But this failed with the following:
ActionController::RoutingError in 'FuzzyLeadsController should have valid route for fuzzyleads search'
No route matches "/fuzzyleads/search/someurl" with {:method=>:get}
If you're expecting this failure, we suggest {:get=>"/fuzzyleads/search/someurl"}.should_not be_routable
But when I removed the :method restriction everything worked successfully. Adding :method => 'get' wasn't sufficient to make the test pass. I've seen similar failures when I've set conditions on routes that haven't been met, so I'd guess something similar is happening in your case.

Related

Rails 3 current_page unexpected behavior

I don't what to think...
In routes.rb I have a route:
match 'profile' => 'profile#index', :via => :get
I am in the /profile action.
params.inspect gives me {"action"=>"index", "controller"=>"profile"}
I don't know Why Doed current_page?(:controller => 'profile', :action => "index" ) give false?
Thanks a lot.
Try this:
current_page?(profile_path)
It's always better to use the url helpers rather than specifying controllers and actions in your code.

Why to add a connection in routes file when using link_to in rails 2

I was trying to accomplish the following:
<%= link_to "Log out", { :controller
=> 'users', :action => 'logout' }, :class => 'menulink2' %>
But it didn't work, it always redirected me to a show view. I had to had the following to my routes.rb:
map.connect 'users/logout',
:controller => 'users', :action =>
'logout'
Why didn't rails recognize the action I was passing ('logout') ?
That logic has to be specified somewhere. There's got to be some mapping from the hash {:controller => 'users', :action => 'logout'} to a url, and the place that's done in rails is the routes.rb file. In older versions of rails many routes.rb came with a default at the end:
map.connect ':controller(/:action/(:id(.:format)))'
Which would make it so that most any :controller, :action hash could be specified and then routed to host.url/:controller/:action.
With the more modern versions resource-based routes are heavily favored, and controllers which don't follow rails' REST conventions (i.e. having only :index,:show,:create,:new,:edit,:update,:destroy methods) generally have to have their routes explicitly specified in some way.
(Either with map.resources :users, :collection => {:get => :logout} or with map.connect( 'some_url', :controller => 'users', :action => 'logout'}))
I'm guessing, but the reason they did that is probably that the actions of a controller are really just its public methods.
It's frequently nice to have public methods in your controllers that aren't url-end-points for testing purposes.
For instance, you could have before_filters as public methods that you might want to test without having to use #controller.send(:your_before_filter_method) in your test code.
So they whitelist the resource actions, and make the others unreachable by default. Let me look through the rails changelog and see if I'm right.

How do I specify a default in a rails 2.3 route?

In my Rails 2.3.11 app, I want to specify that the default format for a route is :xml. According to the documentation I can do this using :defaults
map.connect '/myroute', :controller => 'mycontroller',
:action => 'myaction',
:defaults => {:format => :xml}
The documentation specifically says this should work:
You can also define other defaults in a route by supplying a hash for
the :defaults option. This even applies to parameters that are not
explicitly defined elsewhere in the route.
But if I do that, then I get this error:
/Users/simon/myproject/vendor/rails/actionpack/lib/action_controller/routing/builder.rb:107:in `assign_route_options':
format: No matching segment exists; cannot assign default (ArgumentError)
I see that a lighthouse ticket has been raised about this; a respondent notes that it works for resources but not named routes; an admin has incorrectly marked it as fixed because he's tested it on resources. Ho hum.
Elsewhere it is suggested that i do it like this:
map.connect '/myroute', :controller => 'mycontroller',
:action => 'myaction',
:format => :xml
but then if I test it
assert_generates '/myroute', :controller => 'mycontroller',
:action => 'myaction'
I get told that no route matches :controller => 'mycontroller', :action => 'myaction' - I have to put the format in by hand, so it isn't a default.
How do I specify a default in a rails 2.3 route? Do I need to get them to reopen the ticket and actually fix the bug? Is there any hope that that will happen now Rails 3 is out?
Hmmm that is pretty weird. I've used :defaults hash in a named route, and it worked for me. Can you try using a named route instead and see if it works ?
map.myroute '/myroute', :controller => 'mycontroller',
:action => 'myaction',
:defaults => {:format => :xml}

Is it possible to create a route like '~:id' in Rails 2.x?

I have been using the following route successfully in my Rails 2.x application:
map.user ':id', :controller => 'users', :action => 'show'
This, as my lowest route, properly catches things like /tsmango and renders Users#show.
I'm now trying to add a second, similar route like:
map.post '~:id', :controller => 'posts', :action => 'show'
Because neither my users or my posts are allowed to contain ~ and because this route will appear above my map.user route, I assumed this would properly catch any call starting with /~ and render my Posts#show action. Unfortunately, I'm having trouble getting this one to work.
What's interesting is that this similar route works perfectly:
map.post ':id~', :controller => 'posts', :action => 'show'
Although, I'm certainly willing to go with ':id~' since it has the same result, at this point I'm really just frustrated and curious as to how you would build a route that matches '~:id'.
It's worth mentioning that I do not want to modify my to_param method or my actual user and post slugs to include the prepended ~. I just want that in a route to indicate which action should handle it. Unless I'm mistaken, this rules out the use of something like:
:requirements => {:id => /\~[a-zA-Z0-9]/}
Thanks, in advance, for any help you can provide!
Update: I'm aware of route priority and stated above that I am placing the '~:id' route above the ':id' route. I receive the following error while trying to generate the url like post_path(#post):
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.to_sym
Routes are prioritized depending of the order in which they're declared.
When you define first the :id route, the second one is never executed.
In order for this to work, you just have to first define the ~:id route and then the :id one.
map.post '~:id', :controller => 'posts', :action => 'show'
map.post ':id', :controller => 'users', :action => 'show'

Rails: Rewrite get variables in URL to cleaner style

I am trying to figure out how to submit a search query get variables as /search/query instead of /search?search=query. Any ideas?
Define route in your routes.rb
map.search "/search/:search", :controller => "search", :action => "index", :conditions => { :method => :get }
restart server and check.
for more info ref Module ActionController::Routing

Resources