Marking a string as HTML safe - ruby-on-rails

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])) %>

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.

params.merge instead of :overwrite_params gives different URLs

In my old Rails 2.3 application I had something like:
link_to 'Portuguese', url_for(:overwrite_params => { :lang => 'pt' })
which was returning me URLs formatted as:
.../pt
Now that I've upgraded to Rails 3.0 :overwrite_params doesn't work any more, they say params.merge can be used instead to have the same result.
This is true, the page I land to is the same, yet
link_to 'Portuguese', params.merge(:lang => 'pt')
gives me URLs the kind of:
.../?lang=pt
How could I maintain the same URLs as before?
you can use a match statement. In routes.rb file you need to mention something like
get "sign_up/:lang" => "users#new"
I tried this in console
1.9.3-p429 :001 > include Rails.application.routes.url_helpers
1.9.3-p429 :011 > url_for(:only_path => true, :controller => 'users', :action = 'new' , :lang=>'pt')
=> "/sign_up/pt"
In this manner you will pass the parameter lang as '/pt' and not '/?lang=pt'
I had this horrible-looking workaround working:
after defining a matching route
match '(/:lang)', to: 'home#index', as: :home
I create the link to it as:
link_to "Portuguese", URI(request.referer).path + "pt"

Generate the URL for a generic path with possible options in Rails

I'm creating a customisable nav menu for our site and have run into the following problem.
I need to generate a URL to any controller and action on the site and optionally pass it parameters. I was able to do the former by simply saying:
url_for(:controller => nav[:controller_name], :action => nav[:action_name])
which is great for sending you to {controller}/{action}. eg. news/articles
Throwing options in suddenly changes the game. Now I need to send you to something like:
{controller}/{action}/{category}/{slug}/{id}
eg. news/articles/world-domination/montana-max-vows-revenge/12345
the helper for the above would be something along the lines of:
news_article_path('world-domination', 'montana-max-vows-revenge', '12345')
and I haven't been able to replicate that in a vanilla url_for due to the arguments.
What I have done, and I don't really like is:
url_for(send("#{nav[:controller_name]}_#{nav[:action_name]}_path", *nav[:options]))
which generates the helper using send and then passes it a kwargs list. I'm sure there's a better way to do that surely?
You can do this cleanly if you are able to name the options (split here over lines for legibility):
url_for({
:controller => nav[:controller_name],
:action => nav[:action_name]
}.merge(nav[:options] || {}))
where
nav = {
:controller_name => 'news',
:action_name => 'articles',
:options => {
:category => 'world-domination',
:slug => 'montana-max-vows-revenge',
:id => '12345'
}
}

Kaminari wrong url in the view

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'}%>

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