I have a case on url that generated by kaminari paginate as the url depends on a condition. Here is my routes
concern :search do
scope '/search', as: :search do
get '/', to: 'users#search'
get '/schedule/:id', to: 'schedules#doctor', as: :schedule
end
end
concerns :search
scope :dashboard, as: :dashboard do
concerns :search
end
As you can see, the :search is accessible through /search and /dashboard/search. The problem is, paginate #doctors gives /search which basically will goes to search_path even though I'm on dashboard_search_path (it should gives /dashboard/search path).
My question is, how can I pass a custom path to paginate? I'd like paginate to use search_path when I open /search and use dashboard_search_path when I'm on /dashboard/search/path.
You don't have to provide how to decide /search or /dashboard/search, I just need to know how to pass it to paginate as an argument. Ta
Kaminari accepts parameters for paginate, one of them is params for the links. It works the same as url_for in rails. Didn't test it, but try for dashboard pages, should work.
paginate #doctors, params: { script_name: "/dashboard" }
From docs for url_for:
:script_name - specifies application path relative to domain root. If provided, prepends application path.
use url param for paginate and have your custom code in proc which will define the final url:
paginate #doctors, url: proc{|page| some_condition ? search_path : dashboard_search_path}
Related
I have a ruby on rails app and I use will_paginate to render my products from categories.
I have 3 routes for some action:
/category1
/category2
/category3
When I am on /category2 or /category3 page, the will_paginate generate URLs with /category1?page=nr_page NOT for /category1 url.
From what I noticed, if I change the order of the routes, will_paginate will generate URLs with the first route from my routes file.
will_paginate uses url_for and params to figure out the path for pagination. According to what you said, your routes file looks something like this:
get '/themes' => 'category#show_category', as: :all_themes
get '/templates' => 'category#show_category', as: :all_templates
get '/design-system' => 'category#show_category', as: :all_design_system
When you add `<%= self.params.inspect %> to your view. you will see something like this (maybe with more params in the hash):
<ActionController::Parameters {"controller"=>"category", "action"=>"show_category"} permitted: false>
This means that will paginate takes these parameters and uses them in the url_for method. The call looks like this:
url_for controller: 'category', action: 'show_category', page: 123
it doesn't see the current path in the browser, only the controller and action names. In this case it goes through all of the routes from the top until it finds first defined rule for given controller and action and takes the url from this rule. This means it will always use the URL for the first defined category in your list.
Possible solutions
Define different actions for every category. It will work fine for you if you want to use it this way
get '/themes' => 'category#themes', as: :all_themes
get '/templates' => 'category#templates', as: :all_templates
get '/design-system' => 'category#design_system', as: :all_design_system
Define one route with the parameter
get '/category/:category' => 'category#show_category', as: 'show_category'
and then in your views or controller use following links:
show_category_path(category: 'themes')
Just URLs will not look as nice as before.
I have this line of code in routes.rb
get 'products#:id' => 'products#index', as: :products_hash
It works, but the problem is that the hash symbol (#) gets rendered as %23.
http://localhost:3000/products%2368
This is what it should be:
http://localhost:3000/products#68
How can I achieve this? Thanks!
Rails
I feel you're missing the point of Rails' routing system, which is that you are meant to construct it around objects (hence why you call resources :controller etc).
Although I don't understand why you're defining the route you are, I'll give you some ideas. There is a "wildcard" setting for your routes in Rails, which allows you to define & pass parameters to your application out of the scope of the typical "CRUD" based applications:
#config/routes.rb
get 'products#*id' => 'products#index', as: :products_hash
This will give you the ability to send requests to the following route:
<%= link_to "Product", products_hash_path("68") %>
You'd then be able to call the param in the controller:
#app/controllers/products_controller.rb
class ProductsController < ApplicationController
def index
id = params[:id]
end
end
I am working on my first RoR website. You can consider it as a shop with products.
I use Ruby 2.0, Rails 4.0, and Kaminari for pagination.
Here is my route.rb file
scope '(:locale)' do
get 'product/all', as: :product
get 'product/all', as: :home
get 'all', :to => 'product#all'
get 'page/:page', :action => :all, :controller => :product
root 'product#all'
end
As you see, I want to have pagination links like this one:
http://website/uk/page/2
And Kaminari creates links like that when I use paginate helper in views
However when I try to use path helper, I receive correct but not pretty links:
http://website/en/product/all?page=2
Here is the helper call:
product_path(page: 2, locale: I18n.locale)
As you see, locale scope works ok, but page is still appended as parameter.
So, here is the question:
Is it possible to modify route.rb to have path helpers work the same way as kaminari helper?
I'm trying to change the will_paginate links from the format of /list?page=1 to /list/page/1. I have the routes setup right for this, but will_paginate is using the query string in links rather than my pretty URL style. How to tell it otherwise?
I'm using will_paginate 2.3.16 and Rails 2.3.14.
will_paginate uses the url_for helper. If you define routes containing the parameters it uses, it should generate pretty urls.
map.connect '/lists/page/:page', :controller => 'lists', :action => 'index'
Please make sure, you define this route above any routes that could also match your controller action. Even better: exclude the index action like this:
map.resources :lists, :except => [:index]
You have several options here:
1st option: monkey patch WillPaginate::ActionView::LinkRenderer#url, which currently has the following url logic:
def url(page)
#base_url_params ||= begin
url_params = merge_get_params(default_url_params)
merge_optional_params(url_params)
end
url_params = #base_url_params.dup
add_current_page_param(url_params, page)
#template.url_for(url_params)
end
So, I imagine that you can do something like "/list/page/#{page}" instead.
The other way is to fully implement the renderer (by subclassing WillPaginate::ViewHelpers::LinkRenderer), and then providing it as :renderer => MyRendererClass when calling will_paginate.
I would like my rails url to look like:
/posts/345/the-great-concept
when i use the following in my posts model,
def to_param
"#{id}/#{name.parameterize.downcase}"
end
the urls look great upon mousover in the browser. and function correctly. however, once the page is loaded in the browser url it looks like:
/posts/345%2Fthe-great-concept
and to be clear, the "name" is just for good looks - the post is retrieved only by id. also i do not want to use a database slug approach.
how should i better approach this?
ps. don't want "/posts/345-the-great-concept" either ...
Its escaped because its not part of the path, but a param, so it needs to be escaped or you will be on the wrong uri.
def to_param
"#{id}-#{name.parameterize.downcase}"
end
edit: Okay, so the slash is indeed important; Here's how to tackle it:
Create a custom route for that:
# in config/routes.rb
resources :posts
match '/posts/:id/:slug' => 'posts#show', :as => :slug
Then create your slug method:
# in app/models/post.rb
def slug
title.parameterize.downcase
end
Then change your routes to the show action so the link to the fancy url:
# in any link to show; redirect after create, etc..
link_to slug_path(#post, :slug => #post.slug)
I created an app to test all this out, if interested, you can check it out at:
https://github.com/unixmonkey/Pretty-Path