I have a rails 3 application in which users can find objects near them by tapping their address or by clicking on links I generates (looks like "Find objects in Dallas").
For the second way, I generates URLs like this :
www.my_website.com/search?place=Dallas
How can I transform these URLs to looks like this :
www.my_website.com/search/Dallas
It all has to do with the routes you set up.
routes.rb
get 'search/:place' => 'search_controller#search', :as => :seo_search
Use it as such
seo_search_path('Dallas')
From your controller you will get a params[:place] available.
Related
I have a route in my rails application:
get 'welcome/usertypeone' => 'welcome#usertypeone'
This doesnot look good in the browser as the URL comes out like:
www.mywebsite/welcome/usertypeone
Any way I could change the way the url looks to something like:
www.mywebsite/welcome/teacher
without needing to change the route itself as i would need to change it in loads of places. Just seeing if there is a better solution to this.
If you're explicitly defining the route (as you are, as opposed to using resource etc) you can configure the route as you'd like.
get 'welcome/teacher' => 'welcome#usertypeone'
This will make www.mywebsite.com/welcome/teacher route to the same controller and action.
You will, however, need to update the route throughout your application from welcome_usertypeone_path to welcome_teacher_path. Your text editor probably has a search and replace function making this a 10 second step.
Maybe what you want looks like this:
get 'welcome/:user_type' => 'welcome#usertypeone'
This will take whatever is after the welcome/ and put it in params as params[:user_type], but it will still go to the WelcomesController and the usertypeone action.
You can go to your routes.rb file and try:
get 'welcome/teacher' => 'welcome#usertypeone'
Then you should get the url you require: www.mywebsite/welcome/teacher
Let me fair from the outset, and tell you that I've 'solved' the problem I'm describing. But a solution that you don't understand is not really a solution, now is it?
I have a resource, Newsbites. I have an index page for Newsbites. All my CRUD actions work fine.
I created a separate index (frontindex.html.erb) that acts as the front page of my website to show the newest Newsbites. The formatting is different from my normal index so readers get a larger photo, more of the text of the article(more ads too:).
In my routing table, I have the following statements:
resources :newsbites
get 'newsbites/frontindex'
root 'newsbites#frontindex'
Rake routes show the following:
newsbites_frontindex GET /newsbites/frontindex(.:format) newsbites#frontindex
If I load my website from the root (localhost:3000), it works great. There is a separate menu page that is rendered at the top, and it loads fine. I can click on all links, except the 'Home' link, and they work fine.
The 'Home' link is:
<%= link_to 'Home', newsbites_frontindex_path %>
When I click on the linked, I get the following error:
Couldn't find Newsbite with 'id'=frontindex
The error points to the 'show' action of my Newbites controller. Here are the frontindex and show def from the controller. They appear exactly as I'm posting them:
def frontindex
#newsbites = Newsbite.all
end
def show
#newsbite = Newsbite.find(params[:id])
end
I don't get it. Why is the show action being called by newbites_frontindex_path when there is both a def and views that match? Now, I can get around this by simply pointing home to root_path. But that doesn't help me understand. What if this was not the root of the site?
Any help would be greatly appreciated.
Actually I'm very surprised your code worked at all. A route must define two things
Some sort of regex against which the URL of the user is matched (newsbites/frontindex is different than newsbites/backindex)
What do you want to do for a given URL ? You want to point to a controller action
Rails won't usually "guess" what that action is. Or maybe, he was still able to "guess" that you wanted to use the newsbites controller, but it didn't guess the action right this time :(.
You should declare the root like this, which is what you did
root 'controller#action'
For the rest, there are two ways you can declare it. I prefer the second one
resources :newsbites
get 'newsbites/frontindex', to: 'newsbites#frontindex'
resources :newsbites do
# stuff added here will have the context of the `newsbites` controller already
get 'frontindex', on: :collection # the name of the action is inferred to be `frontindex`
end
The on: :collection, means that 'frontindex' is an action that concerns ALL the newsbites, so the URL generated will be newsbites/frontindex.
On the other hand get 'custom_action', on: :member, means that the custom_action targets a specific item, the URL generated would look like newsbites/:id/custom_action
EDIT : Rails also generate path_helpers based on the route declaration
get 'test', to: 'newsbites#frontindex'
get 'test/something', to: 'newsbites#frontindex'
resources :newsbites do
get 'frontindex', on: :collection
get 'custom_action', on: :member
Will generate path helpers
test_path
test_something_path
# CRUD helpers : new/edit/show/delete, etc. helpers
frontindex_newsbites_path
custom_actions_newsbite_path(ID) # without s !
You can always override this by adding an as: option
get 'custom_action', on: :member, as: 'something_cool'
# => something_cool_newsbites_path
Rails routes thinks that frontindex is an id. That's what the error message says. So it goes to GET newsbite/:id which maps to show.
You need to find a way let Rails routes know that frontindex is not an id.
On a side note: The order in which you define routes matters. The first one matched will be used. If you have GET newsbite/:id and GET newsbite/frontindex then the one that appears first will be matched. In your case this is the first one.
Maybe try to change the order.
I'm trying to create custom URLs for my site's users:
www.mysite.com/user1
If I set the routing rule to be this:
match ':id' => "user#view", :as => :user
Then it works great! I can access www.mysite.com/user1 and it will pull up the page for user1.
However, that breaks my about page, which is at www.mysite.com/about . The error I get here is:
"Couldn't find User with id=about"
Any idea how I can fix this problem? Thanks! As an aside - I'm using friendlyid to generate the human readable slugs.
Ringo
Is the about page a static file located at public/about.html? If so, then Rails will match this first and fall back to the router if it can't find the file.
If it's a route instead, then your match :id route should be beneath the one for about, so that about is matched first.
Since the beginning I always hat this one problem with rails, short urls without the controller name.
For example, I have a blog and I don't want any dates or controller names in the url, I already have a Page model with a unique field url in my database. Rails works great with such urls:
jeena.net/pages/1
And when I modify the model I even can get it to use
jeena.net/pages/foo
But it seems not to matter what I do I can not get it to work with just:
jeena.net/foo
Of course I want the index page still to work with
jeena.net/pages
And I want creating new pages and updating old pages to work too in some was as well as the link_to()-method. All suggestions are appreciated.
To define that route, try adding the following to your routes.rb:
match '/:id' => 'your_controller#your_action'
This will pretty much match everything to the id of your model. And that's not very nice... You don't want to route youe_host/pages to the pages controller, with an id equal to 'pages'... To prevent that from happening, make sure to put that line on the end of the routes.rb file. The router uses the first route that matches the path received, so putting that line on the end of it will make sure that it will only match your route after it ran out of other meaningful options.
A better practice would be to pass regexp constraints to the router, so that it will only match ids with a specific format, like that:
match '/:id' => 'your_controller#your_action', :constraints => { :id => /your_regexp/ }
Refer to the guides if you have doubts about the rails rounting system. It is pretty well written and covers lots of important things.
Rails rounting - Official Guides
edit: to create a named route, one that you can call in your controllers and override the normal routes that you are probably creating with resource, you have to provide the :as => parameter in your routes.rb
match '/:id' => 'your_controller#your_action', :as => some_name
Then you'll be able to call it in your controller/views like this:
link_to some_name_path(#my_string_id)
Hope this helps. And take a time to read the guides, it has really lots of useful info, including more details about creating named routes.
I'm trying to send a variable through a link_to, without using url query in Ruby on Rails, from one controller's index view to be used on another controller's index.
Basically, I need to pass the Turma.id (school class id), to the Elementos_turma(peoples in the class) controller, so I can use it and filter the index: ElementosTurma.find(:all, :conditions => { :turma_id => xxxxx } ), to show the peoples of the selected class.
It it possible?
Maybe without using a session variable?
Maybe sending the variable to a method on the 1st controller, to send it the other controller? (if so how? not very RoR wise... :) )
No need for a special method to get the info you need, the magic of routes will do.
In your routes.db file, you should be able to define something like this,
map.resources :class, :has_many => :students
Then if you run 'rake routes' you should see a routes similar to this
class_students GET /classes/:class_id/students(.:format) {:controller=>"students", :action=>"index"}
You can call that path in your view like so
class_students_path(class_id)
Then in your controller you will have access to params[:class_id]
The name of the route isn't very pretty, but this should work.
EDIT--------------------------------------
According to your comment, you can't use map.resources for some reason or another...
map.class_students '/:class_id/students', :controller => 'students', :action => 'index'
That will produce the same route available in your view, same param in your controller.
That being said, I don't know how a server bug could prohibit you from using map.resources
You can not transfer data through a link without including that data in the link.
However, it sounds like you just need to be using nested resources. (Since I speak English, I'm going to not tackle another language and do what comes to me.) The URLs you want to be sending people to probably should look more like this if you want to be RESTful:
/classes/1/people/
That is the "Rails way" of indicating that you want to get people in class #1, and Rails offers built-in routing methods to make this easy. See the Rails Routing from the Outside In article in the Rails Guide.