Kaminari wrong url in the view - ruby-on-rails

I've found similar questions about Kaminari, however none of the answers worked on my machine.
Basically, when I'm paginating, the number of pages is correct, but the URL I'm redirected to is wrong.
This one below is the action in my controller
def index_offered
#machines = Machine.not_sponsored.offered.order("created_at DESC").page(params[:page]).per(5)
end
Now, when I implement Kaminari in the view
<%= paginate #machines%>
I obtain 3 pages (correct) of pagination, the links are:
0.0.0.0:3000/?page=2
0.0.0.0:3000/?page=3
While they should be
0.0.0.0:3000/offered-machinery?page=2
0.0.0.0:3000/offered-machinery?page=3
Could the catch be nested in the routing? Here it is the route that regards the index_offered action
match 'offered-machinery' => 'machines#index_offered', :as => :offered_machinery
I've also tried to pass params in the view by typing
<%= paginate #machines , :params => {:controller => "Machines" , :action => 'index_offered'}%>
and uncommented the line in routes.rb:
match ':controller(/:action(/:id))(.:format)'
but in that case, I obtain these URLs instead:
0.0.0.0:3000/Machines/offered-machinery?page=2
0.0.0.0:3000/Machines/offered-machinery?page=3
How could I work around this?

Try to change de controller name to "machines":
{:controller => "machines" , :action => 'index_offered'}%>

Related

Better routes in rails with params

I've been working on a movie application in Rails. I have a controller/view for the actor. When passing params to the actors controller i want the URL to be pretty. Now it looks like this: http://localhost:3000/actors/show?actor=Hayley+Atwell and i want it to look like /actors/show/Hayley+Atwell or /actors/Hayley+Atwell.
How do i do this? My link in the movies view is:
<%= link_to a.name, {:controller => 'actors', :action => 'show', :actor => a.name}, :class => "label label-default" %>
My routes.rb is now like this:
get 'actors/show'
I recommend you use friendly_id gem. It perfectly satisfies your needs!
https://github.com/norman/friendly_id
You can use the following in your ./config/route.rb file:
get '/actors/:actor', to: 'actors#show'
I'll give a series of refactoring advice as follow:
Try to make use of the actor's id instead of the name
Change the route to: get '/actors/show/:id', to: 'actors#show'
Then, you can now change the link in your view to something like:
<%= link_to a.name, {:controller => 'actors', :action => 'show', :id => a.id}, :class => "label label-default" %>
Note: the : part in the :id of your route means that this could be interchanged to anything, and whatever comes in that place will be interpreted as the id. So, in /actors/show/7, the id of the actor is 7, you can now find the actor with this id in your controller action, and do anything you want with it.
If I'm right than you try to create RESTful routes anyway.
So I would recommend you to use the Rails' resources method in your routes:
Rails.application.routes.draw do
resources :actors # If you want only the :show action than add:
# , only: [:show]
end
This automatically creates the proper routes for you.
To get the names into the URL you should use the friendly_id gem. It has a great community and is very well tested.

How to create an arbitrary link in Rails?

link_to and helpers use the names of my models and their IDs while I want to have a couple of different, arbitrary, variables in my link. I have no problems to route them, I actually keep the default routing as well, but I suddenly stuck that I cannot easily generate an arbitrary link. For instance I want to have a link like ":name_of_board/:post_number", where :name_of_board and :post_number are variables set by me, and when I use link_to I get instead "posts/:id", where "posts" it's the name of the controller. While it's not hard to use an arbitrary id like
link_to 'Reply', :controller => "posts", :action => "show", :id => number
I cannot get how I can get rid of "posts". So, is there an easy way to generate a link by variables or to convert a string into link? Sure, I can add other queries to the line above, but it will make the link even more ugly, like "posts/:id?name_of_board=:name_of_board".
You can create additional routes for your posts resource in your routes.rb, or make standalone named routes:
resources :posts do
get ':name_of_board/:id' => 'posts#show', as: :with_name_of_board
end
get ':name_of_board/:id' => 'posts#show', as: :board
Now this
#name_of_board = "foo"
#post_id = 5
link_to 'Reply', posts_with_name_of_board_path(#name_of_board, #post_id)
link_to 'Reply', board_path(#name_of_board, #post_id)
would link to /posts/foo/5 and /foo/5 respectively.
You should first edit your route entry, for example a classic show route is the follow:
get "post/:id" => "post#show", :as => :post
# + patch, put, delete have the same link but with different method
And you can call it with the following helper
link_to "Show the post", post_path(:id => #post.id)
You can edit or create a new entry in the routes, applying the parameters you want to use, e.g.:
get "post/:id/:my_platform" => "post#show", :as => :post_custom
Then
link_to "Show the post with custom", post_custom_path(:id => #post.id, :my_platform => "var")
Finally, the link generated for this last entry is for example:
"/post/3/var"
Even in this situation, you can add some other params not defined in the routes, e.g.:
link_to "Show post with params", post_custom_path(:id => #post.id, :my_platform => "var", :params1 => "var1", :params2 => "var2")
=> "/post/3/var?params1=var1&params2=var2"
RoR match your variable defined in the routes when you render a link (remember that these variables are mandatory), but you can ever add other vars that come at the end of the url ("?...&..")

Marking a string as HTML safe

I am trying to build my first Rails application and I'm using Ryan Heath's navigation_helper plugin to give me the current class in my navigation. I built my named routes as follows:
match 'games' => 'games#index', :as => :games
match 'new' => 'games#new', :as => :new
match 'previous' => 'games#previous', :as => :previous
match 'settings' => 'settings#index', :as => :settings
Then in my application_layout I added the following code
<%= navigation([:games, :new, :previous, :settings]).html_safe %>
From what I know of Rails the html_safe should force HTML to be rendered properly, but instead what I get is this:
<ul class="navigation">["<li class=\"current\"><a href=\"/games\">Games</a></li>", "<li class=\"\"><a href=\"/new\">New</a></li>", "<li class=\"\"><a href=\"/previous\">Previous</a></li>", "<li class=\"\"><a href=\"/settings\">Settings</a></li>"]</ul>
So am I doing something wrong or is the plugin doing something wrong? I know that the plugin was written back in 2.x days which from what I know handled HTML a bit differently, but I just don't know enough.
https://github.com/priceflex/navigation_helper/commit/ad7bf45db1845e9299e9da39cf214866b608dd47 try to use this fork wich fix issues for rails3
You can use raw() method to avoid escaping:
<%= raw(navigation([:games, :new, :previous, :settings])) %>

how can I add a new action to a controller?

I used the following in routes to add a new action to my Email controller:
map.resources :emails, :member => { :newfwd => :put}
The expected result was that newfwd_email_path(:id => 1) would generate the following urL: emails/1/newfwd
It does. But I get an error, it treats '1' as an action and 'newfwd' as an id. I want '1' to be interpreted as the id for emails, upon which the newfwd action acts.
I'm not sure what I'm doing wrong. (Note: I am using Rails 2.3.8)
Try
link_to newfwd_email_path(1), :method => :put
:id => 1 is as good as 1 ;)
you do not need to pass a hash to the newfwd_email_path method. Try
newfwd_email_path(1)
EDIT: you also need to use :method => :put to ensure that the PUT verb is used when request is received on the server and routing comes into effect.

Adjust routes.rb for method call in Controller

I have an online portfolio created in Rails featuring different projects. I want to be able to filter the projects by keywords. My approach is to define a method for each keyword in the ProjectsController and link the keywords to call the methods.
For Example Keyword = graphic_design:
<%= link_to 'Graphic Design', :action => "filter_"+#project.keyword.to_s %>
That way I get the error:
Couldn't find Project with ID=filter_graphic_design
This is quite obvious to me. My question: Is there a way to tell the routes.rb to behave differently only for 'filter_' methods? Any other suggestions?
Your approach is wrong. Why do you need a filter_ method for each keyword in the first place? Its pretty simple a solution. First define a named route in your routes.rb:
map.filter '/projects/:filter_this_for_me', :controller => 'projects', :action => 'filter'
In your views,
<%= link_to 'Graphic Design', filter_path("filter_" + #project.keyword.to_s) %>
In your filter action,
def filter
logger.info("Parameters that is being received: #{params}")
filter_what = params[:filter_this_for_me]
if(!filter_what.nil? && !filter_what.blank?)
# Here filter_what will have "filter_graphic_design" or "filter_something"
# With which you can filter any data that you want.
# Filter your projects here.
end
end
I think something like this could work
map.connect "/projects/filter_{filter}", :controller => 'projects', :action => 'filter'
Haven't tried it though

Resources