rails routing controller action change - ruby-on-rails

I'm struggling here with a problem:
I have a controller questions which has action new.
Whenever I need to create new question, I'm typing
/questions/new
What changes to routes.rb should I make to change the URI to
/questions/ask
Thank you.
Valve.

Try this:
map.ask_question '/questions/ask', :controller => 'questions', :action => 'new'
Then you'll have a named route and you can:
link_to "Ask a question", ask_question_path

If you are using RESTful routes maybe you'd like to use map.resources for your questions.
To rename the action urls you may do this:
map.resources :questions, :path_names => { :new => 'ask', :delete => 'withdraw' }
(I added delete for the sake of the example)

Which version of rails?
Generally the default route should catch anything like /:controller/:action, so you could just create an ask method in your questions controller. Take a look at the api documentation for named_route and map_resource if you want something a bit smoother to work with.

Related

Add a new page to a resource in rails

Ok, This seem so simple that I feel kind of dumb for asking, yet I have seen other that asked something similar but no quite the same and their answers does not solve my problem. I have a resource called servicios.
resources :servicios, created the routes for the "default" actions that are in my controller: index, new, create, show, edit, update, destroy. However, I need another action which is search that should map to my view where I'm going to implement an advance search.
How can I do that?
Editing with new info
using this approach: resources :servicios, :collection => {:search => :get}
http://localhost:3000/servicios/search
I was getting error
ActiveRecord::RecordNotFound in ServiciosController#show
Couldn't find Servicio with ID=search
If you are using Rails 3 then the route definitions will look like
resources :servicios do
collection do
get :search
end
end
resources :servicios, :collection => {:search => :get}
Will route /servicios/search to def search...end in the servicios controller.
Or...
match 'search', :to => 'servicios#search'

How do I route user profile URLs to skip the controller?

Right now my user profile URLs are like so:
http://example.com/users/joeschmoe
And that points to the show method in the user controller.
What I'd ideally like to do is offer user profile URLs like this:
http://example.com/joeschmoe
So, what sort of route and controller magic needs to happen to pull that off?
I disagree with what jcm says about this. It's not a terrible idea at all and is used in production by the two biggest social networks Facebook and MySpace.
The route to match http://example.com/username would look like this:
map.connect ':username', :controller => 'users', :action => 'show'
If you want to go the subdomain route and map profiles to a URL like http://username.example.com/, I recommend using the SubdomainFu plugin and the resulting route would look like:
map.root :controller => 'users', :action => 'show' , :conditions => {:subdomain => /.+/}
These broad, catch all routes should be defined last in routes.rb, so that they are of lowest priority, and more specific routes will match first.
I also recommend using a validation in your User model to eliminate the possibility of a user choosing a username that will collide with current and future routes:
class User < ActiveRecord::Base
validates_exclusion_of :username, :in => %w( messages posts blog forum admin profile )
…
end
This does not make sense unless you have no controllers. What happens when you want to name a controller the same as an existing user? What if a user creates a username the same as one of your controllers? This looks like a terrible idea. If you think the /user/ is too long try making a new custom route for /u/
So your custom route would be...
map.connect 'u/:id', :controller => 'my/usercontroller', :action => 'someaction'
In routes.rb this should do the trick:
map.connect ":login", :controller => 'users', :action => 'show'
Where login is the name of the variable passed to the show method. Be sure to put it after all other controller mappings.
Well, one thing you need is to ensure that you don't have name collisions with your users and controllers.
Once you do that you, can add a route like this:
map.connect ':username', :controller => 'users', :action => 'show'
Another thing people have done is to use subdomains and rewrite rules in the web server, so you can have http://joeshmoe.example.com
In Rails 4 to skip controller from url you have to do add path: ''.
resources :users, path: '' do
end

Action not found

I want to show a simple HTML template, so I added a new empty action to my controller:
def calulator
end
And created the view calculator.html.erb . Then added a link to it:
<%= link_to 'Calculator', {:controller => "mycontroller", :action => "calculator"} %>
When I click it my log shows the following error:
ActionController::UnknownAction (No action responded to show. Actions: calculator, create, destroy, edit, index, new, and update):
Why is looking for a "show" action ? I have map.resources for the controller, as I done it with scaffolding
Any ideas?
You need to add a custom route pointing to the action 'calculator'.
Something like this:
map.connect 'mycontroller/calculator', :controller => 'mycontroller', :action => 'calculator'
You can define members and collections for resources.
map.resources :samples, :member => {:calculator => :get}
Member means that it relates to an instance of the resources. For example /samples/1/calculator. If it doesn't relate to an instance you can define it for the collection and can be access via /samples/calculator.
map.resources :samples, :collection => {:calculator => :get}
This also creates a helper method calculator_samples_path for the collection and calculator_sample_path(sample) for a member. For more on this have a look at Railscast Episode 35.
You are getting No action responded to show because you have the controller routed as map.resources. When you do that, rails sets up several routes for you. One of which is show, which maps every get request matching /mycontroller/somevalue to the show action with somevalue as the id (params[:id]). In mycontroller, there is no show action, as seen in the error message.
To fix this, Nils or Trevoke's answer should work just fine.
map.resources documentation

Pretty URL in Rails when linking

Let's say I have a Ruby on Rails blogging application with a Post model. By default you would be able to read posts by http://.../post/id. I've added a route
map.connect ':title', :controller => 'posts', :action => 'show'
that will accept http://.../title (titles are unique) and the controller will do a query for the title and display the page. However when I am now calling <%= link_to h(post.title), post %> in a view, Rails still gives me links of the type post/id.
Is it possible to get Rails to automatically create the pretty links for me in this case?
If you are willing to accept: http:/.../1234-title-text you can just do:
def to_param
[id, title.parameterize].join("-")
end
AR::Base.find ignores the bit after the id, so it "just works".
To make the /title go away, try naming your route:
map.post ':id', :controller => 'posts', :action => 'show', :conditions => {:id => /[0-9]+-.*/ }
Ensure this route appears after any map.resources :posts call.
You can override ActiveRecord's to_param method and make it return the title. By doing so, you don't need to make its own route for it. Just remember to URL encode it.
What might be a better solution is to take a look at what The Ruby Toolbox has to offer when it comes to permalinks. I think using one of these will be better than to fixing it yourself via to_param.
I would use a permalink database column, a route, and I normally skip using link_to in favor of faster html anchor tags.
Setting your route like:
map.connect '/post/:permalink', :controller => 'post', :action => 'show'
then in posts_controller's show:
link = params[:permalink]
#post = Post.find_by_permalink(link)
You link would then be
Link
then in your create method, before save, for generating the permalink
#post = Post.new(params[:post])
#post.permalink = #post.subject.parameterize
if #post.save
#ect
There is a Gem for you to get this done perfectly
https://github.com/rsl/stringex

rails redirect_to problem

I am developing a rails app and have a question.
In my routes.rb:
map.connect 'admin', :controller => "/admin/users", :action => "index"
So when I go to "http://mydomain.com/admin", it redirects to "http://mydomain.com/admin/users/index".
However, the address remains as "http://mydomain.com/admin".
Thus, links in the page are wrong because they are created based on "http://mydomain.com/admin".
What's the solution to this problem?
Sam
try this:
map.connect 'admin/:action/:id', :controller => 'admin/users'
Your code is not redirecting the browser it's just setting up /admin and /admin/users to trigger the same action.
You could try:
map.connect 'admin', :controller => "/admin/users", :action => "redirect_to_index"
Then in your controller write:
def redirect_to_index
redirect_to :action => :index
end
This will send a redirect to the browser, causing it to display the correct URL.
Hopefully there is a better method that only involves routes.rb. This site might be helpful -> redirect-routing-plugin-for-rails
Make sure any same-domain links on the page start with a /, and use the full path. Generally you should use Rails route methods to generate your links when possible. Same goes for using the image_tag and stylesheet_link_tag helpers.
So if you have a link to "privacy.html", change it to "/privacy.html" and you should be all good no matter where in the route structure you are. This is extra nice when you start extracting your view code out to re-usable partials.
Use link_to and button_to (in UrlHelper)

Resources