I have a list of names, that contain this:
<td><%= product.date %></td>
and it is in my index page. (It is the list of my applications)
I want to assign a custom link to that, and pass THAT value to the controller:
I tried this:
<td><%= link_to product.date, {:controller => "product", :action => "sort_by_date", <how do I pass the 'product.date' string?> }%></td>
I read the rails route guide but I couldn't find help
Thanks
what rakes routes returns:
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
root /
products#home.html
use like below
<%= link_to product.date, {:controller => "product", :action => "sort_by_date", :product_date => product.date %>
and in your controller you should get the date in params[:product_date]
You can also use resource helper function to pass custom parameters like below.
<%= link_to product.date, products_path(:product_date => product.date)
This method will route to the ProductsController#index with a params[:product_date]
Edit:
I just tried with following
resources :products do
collection do
get 'sort_by_date' => 'products#sort_by_date'
end
end
The rake routes are as following
sort_by_date_products GET /products/sort_by_date(.:format) products#sort_by_date
To generate the URL it will be better to use the resource helper function like below
sort_by_date_products_path(:product_date => '1/1/2012')
This will generate a url like /product/sort_by_date?product_date=1/1/2012 which will call the sort_by_date method of ProductsController and also have params[:product_date] available.
Lets check if its work...
Related
I am having index method to list all students. Now I am adding search in the index with one text_field_tag. My function is working but the search value is showing as query string in the url. I don't want this.
My view code:
<p>
<%= form_tag students_path, :method => 'get' do %>
Find by name: <%= text_field_tag :search %>
<%= submit_tag "Search", :name => nil %>
<% end %>
</p>
My controller code is
def index
searchString = params[:search]
if searchString
#students = Student.where("LastName like ?", "%#{searchString}%").paginate(:page => params[:page])
else
#students = Student.paginate(:page => params[:page])
end
end
My current url look like below:
http://localhost:3000/students?utf8=%E2%9C%93&search=A
I just need like /students. Please suggest the best practice
You need to use POST request instead of GET. In order to accomplish that, change your form_tag from:
<%= form_tag students_path, :method => 'get' do %>
to
<%= form_tag students_path, :method => 'post' do %>
What could possibly go wrong...
As #carlosramireziii mentioned, answering this question, requires a bit more work (and he is absolutely right!), so - there is update
1. Custom routes
If you are configuring your routes on your own, one of ways proceeding with this is to add a route, that will properly accept your requests. Take a look at config/routes.rb:
Rails.application.routes.draw do
match '/students', controller: :students, action: :index, via: [:get, :post]
# other definitions
end
Definition like this will create following route for you:
students GET|POST /students(.:format) students#index
This will make your new POST request nicely fall into students#index, generating expected result. However, if you are defining your routes via resources it's not that easy change. This leads us to...
2. Modifying standard resources routes
If routes for students are defined as follows:
Rails.application.routes.draw do
resources :students
# other definitions
end
the following routes are registered:
students GET /students(.:format) students#index
POST /students(.:format) students#create
new_student GET /students/new(.:format) students#new
edit_student GET /students/:id/edit(.:format) students#edit
student GET /students/:id(.:format) students#show
PATCH /students/:id(.:format) students#update
PUT /students/:id(.:format) students#update
DELETE /students/:id(.:format) students#destroy
This indicates, the POST request falls into students#create. In order to make it work, you need to change the create action, to something like:
class StudentsController < ApplicationController
# code omitted
def create
if params.include?('search')
#students = Student.where("LastName like ?", "%#{searchString}%").paginate(:page => params[:page])
render :index
else
# your current code from create action
end
end
end
While this will work, it is not recommended to do it this way. The create action does two things now, which is considered a bad pattern (or bad smell at least), and it is error prone.
So, what can we do?
Making search the right way
1. Custom search route
Define custom collection route:
Rails.application.routes.draw do
resources :students do
collection do
post :search
end
end
# other definitions
end
This registers following routes:
search_students POST /students/search(.:format) students#search
students GET /students(.:format) students#index
POST /students(.:format) students#create
new_student GET /students/new(.:format) students#new
edit_student GET /students/:id/edit(.:format) students#edit
student GET /students/:id(.:format) students#show
PATCH /students/:id(.:format) students#update
PUT /students/:id(.:format) students#update
DELETE /students/:id(.:format) students#destroy
You need to change your form_tag as follows:
<%= form_tag search_students_path, :method => 'post' do %>
And add search action to StudentsController:
class StudentsController < ApplicationController
# code omitted
def search
#students = Student.where("LastName like ?", "%#{searchString}%").paginate(:page => params[:page])
# If you don't want to create separate template for `search`,
# you can try to reuse your `index` template with
# render :index
end
end
2. Use students#index with params passed in URL
This approach is more REST-y, and it makes it available to pass the whole URL to someone else, so the another person is able to see exactly the same result of filtering, which is impossible with params "hidden" in POST request.
I hope I've covered all possibilities. If you have any questions - I'm more than happy to answer!
Good luck!
I want to change my path from root/carts/56 to root/cart.
I applied the logic from this question Rails route to username instead of id, which changes the id of the user to the username in the path. That works because the username can be set to unique.
I want a /cart to lead (obviously) to the one cart the visiter (no users) is working with and get rid of the
:cart/:id. I DO NOT use a user model, otherwise I would just do #user.cart (:user/cart)
So I (understandably so) get this error
Invalid route name, already in use: 'cart'
because this line
match '/:carts/:id' => 'carts#show', :as =>'cart', :via => :get
Relevant routes:
carts GET /carts(.:format) carts#index
POST /carts(.:format) carts#create
new_cart GET /carts/new(.:format) carts#new
edit_cart GET /carts/:id/edit(.:format) carts#edit
cart GET /carts/:id(.:format) carts#show
PATCH /carts/:id(.:format) carts#update
PUT /carts/:id(.:format) carts#update
DELETE /carts/:id(.:format) carts#destroy
UPDATE:
With resource :cart, :only => :show # note 'resource' not 'resources'
I get an improvement, but can I remove the id from the path somehow?
http://localhost:3000/cart?id=52
is what it gives me.
Sorry - the line that gives me the id in the URL is
<li><%= link_to "Cart", cart_path(id: session[:cart_id]) %></li>
Is a singular resource really what I need? I am creating the carts in a session like this
<% if session[:cart_id] == nil %>
<li><%= link_to "Cart", new_cart_path %></li>
<% else %>
The idea there being if they haven't created a cart yet, they will create one when they visit the page.
I actually followed the tutorial for the carts here
In your routes file use
resource :cart, :only => :show # note 'resource' not 'resources'
This will give you a cart_path that you can call. It will hit the show method in the carts_controller. If you need /root/ theres a few ways to add that.
Put this above the user path that's declared in the routes.rb file.
You may need some validation to ensure users don't select names that are reserved.
I am trying to add a checkout link in order to direct a client to checkout view.
I have a ProductsController, and an OrdersController where I defined the action for checkout. I am doing this because I set it so a product can have many orders.
class OrdersController < ApplicationController
def checkout
#product = Product.find(params[:id])
end
In my show.html.erb I added the line:
<%= link_to 'Contribute Now', order_checkout_path, :id => #product, :controller => "orders", :method => :get %>
And my routes look like:
root :to => 'products#index'
match '/products' => 'products#index'
get 'order/checkout'
resources :products
resources :orders
After running rake routes I get:
root / products#index
products /products(.:format) products#index
order_checkout GET /order/checkout(.:format) order#checkout
GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
I have also defined a checkout.html.erb template.
After doing all that, I keep on getting an error of:
Routing Error
uninitialized constant OrderController
Try running rake routes for more information on available routes.
What am I missing?
You want get 'orders/checkout', corresponding to the plural form of "order" used in your controller name.
I am using acts_as_taggable_on steroids and I am having problem with this piece of code that generates a link to a tag:
<%= link_to tag, tag_path(:id => tag.name) %>
when I access the URL:
http://localhost:3000/tags/rails
I get the error:
No action responded to rails. Actions: show
However, this URL works:
http://localhost:3000/tags/show/rails
I have defined the show action in my tags_controller.rb
class TagsController < ApplicationController
def show
#stories = Story.find_tagged_with(params[:id])
end
end
I have the following routes generated by rake:routes :
tags GET /tags(.:format) {:controller=>"tags", :action=>"index"}
POST /tags(.:format) {:controller=>"tags", :action=>"create"}
new_tag GET /tags/new(.:format) {:controller=>"tags", :action=>"new"}
edit_tag GET /tags/:id/edit(.:format) {:controller=>"tags", :action=>"edit"}
tag GET /tags/:id(.:format) {:controller=>"tags", :action=>"show"}
PUT /tags/:id(.:format) {:controller=>"tags", :action=>"update"}
DELETE /tags/:id(.:format) {:controller=>"tags", :action=>"destroy"}
so I know that URL tags/rails points to the route tags/:id, and I've provided an additional param to link_to to assign the tag name as the :id param, but as you can see, it's not working. A forum suggested I use the to_param but I have not Tag model and the book suggested against it. Am I missing anything?
I am following the Sitepoint book Simply Rails 2
EDIT: added working URL, see top
Try adding this to your route resource:
:requirements => { :id => /.*/ }
Shooting in the dark here but should
<%= link_to tag, tag_path(:id => tag.name) %>
be
<%= link_to tag, tag_path(:id => tag.id) %>
or
<%= link_to tag, tag_path(tag) %>
Try this for your link:
link_to tag.name, { :action => :tag, :id => tag.name }
I don't know what version of rails you're using, I'm assuming 3.
Basically, you're using the tag_path which goes off of the id. If you haven't changed anything, that means something like tag/43, tag with id 43. The reason you were suggested to override to_param is in case you want it to go off the name of the tag instead, so something like tag/rails. For that, you do something like this:
class Tag
def to_param
name
end
end
Finally, you will have to change the show action to use the name, not the id. So #stories = Story.find_tagged_with(params[:name]). Then I believe that you will want to create a route to compensate for this, so above your resources :tags, add match "/tags/:name" => "tags#show".
For me it looks like the difference in routes.rb between
resources :tags
and
resource :tags
The first will have as its default index action, the second will not have :index, but it will respond with show on default route.
I have Exam controller.
In routes.rb there is "resources :exams"
In controller there are REST-like generated methods.
I want to add my own method there:
def search
#exams = Exam.where("name like ?", params[:q])
end
In view file:
<%= form_tag(search_path, :method => "post") do %>
<%= label_tag(:q, "Szukaj: ") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Szukaj") %>
<% end %>
I know, there is no results presentation yet, it doesn't work at all at this moment (:
When i go to http://localhost:3000/exams/search it's mapping it to show controller and search is a :id paramether then...
How to get http://localhost:3000/exams/search to run the seach controller?
You forgot to add route. Put this in routes.rb, before resources :exams
map.search '/exams/search', :controller => :exams, :action => :search
Note, that resources :exams doesn't generate routes for all public methods of the controller, it generates very specific set of routes. You can find more information in the rails routing guide. (see section 3.2 in particular)
You'll need to add additional parameters to your mapping. You can add "collection" methods like so:
map.resources :exams, :collection => {:search => :get}
When you rake routes, you'll see that it generates something like so:
search_exams GET /exams/search(.:format) {:controller=>"exams", :action=>"search"}
exams GET /exams(.:format) {:controller=>"exams", :action=>"index"}
POST /exams(.:format) {:controller=>"exams", :action=>"create"}
new_exam GET /exams/new(.:format) {:controller=>"exams", :action=>"new"}
edit_exam GET /exams/:id/edit(.:format) {:controller=>"exams", :action=>"edit"}
exam GET /exams/:id(.:format) {:controller=>"exams", :action=>"show"}
PUT /exams/:id(.:format) {:controller=>"exams", :action=>"update"}
DELETE /exams/:id(.:format) {:controller=>"exams", :action=>"destroy"}