Wrong url with parameterize - ruby-on-rails

I'm trying to have URL rewriting with parameterize, as explain here : How do I rewrite URL's based on title?
Here is my model :
class Article < ActiveRecord::Base
belongs_to :category
self.per_page = 5
def to_param
"#{title.parameterize}"
end
end
And my link :
<%= link_to(article.title, blog_article_path(article), {:class => "blog_title"}) %>
THe problem is that I don't have a link like /blog/article/"my-article-title" but I have /blog/article."my-article-title", which is wrong and not interpreted.
Do you know the reason ?
My route.rb :
get "blog/index"
get "blog/category"
get "blog/article" (I don't use the show action of my article controller, is it the reason ?)
resources :categories
resources :articles
Thanks

Using link_to the way you are by passing in a resource only really works when you actually use resources in your route file.
This is the difference (rake routes output) with using a non-resourceful route and one generated by resources:
blog_article GET /blog/article(.:format)
article GET /articles/:id(.:format)
When you use article_path(#article) it will fill in :id with the id of the resource.
I'd advise you to use the show action of the articles controller so you would have /blog/articles/:id or you could do something like this if you really want that routing:
get "blog/article/:id" => "articles#show", :as => 'blog_article'
which turns into:
blog_article GET /blog/article/:id(.:format)
The official guides have some good info on this.

Related

In Rails, how do I write a link_to expression that results in a "/path/id" format?

This question is for Rails 5. I have a model
class Vote < ApplicationRecord
belongs_to :person
and then a config/routes.rb file that contains
resources :votes
The issue is I want to create a path
/vote/person_id
in which "person_id" is actually the ID of a person object and not a vote object. I thought I could write a "link_to" expression like the below to achieve this
<%= link_to person.name, votes_path(person), :class => 'unvotedPersonLink' %>
but instead what's happening is the link that's generated is
/votes.11
How do I adjust my "link_to" or routes file so taht I can generate a link in the format I want?
If you want to see all routes, you should run rails routes command. Your vote resource like the below:
votes_path returns /votes
new_vote_path returns /votes/new
edit_vote_path(:id) returns /votes/:id/edit
vote_path(:id) returns /votes/:id
You can see more info about Rails routes in the following link:
http://guides.rubyonrails.org/routing.html
this might solve the routing problem.
routes.rb
resources :votes, param: :person_id
view
votes_path(person_id: person.id)
In your views you need to pass person id as below:
votes_path(person: person)
Or like this:
votes_path(person, #vote)
Or :
votes_path(person: current_user)
Also, if you want to use the person id to add vote I would recommend you to inject the person id through controller using current_user

Short url with Ruby on Rails routes

I am trying to create short url links for books in Ruby on Rails. I want to get something like this: www.domain.com/book123, where book is the controller name (or custom controller name) and 123 is an id of the book.
Right now my routes look as follow:
resources :books, except: [:edit], path: "book" do
put :new, on: :new
member do
get ':id' => 'books#show'
get 'general' => 'books#general'
get 'additional' => 'books#additional'
get 'photos' => 'books#photos'
get 'map' => 'books#map'
end
resources :photos, only: [:create, :destroy]
end
This is what I get: http://localhost:3000/book/40 or www.domain.com/book/40.
I was trying to find similar questions and I found that the only way to achieve this is to use regex. I am new in Ruby on Rails and I want to find the right and efficient way of doing it.
Also, I might be wrong but I've noticed that some of the urls can affect on the website performance, so I don't want to have such problems.
Any help, information or examples will be highly appreciated. Thank you for your help and time.
You could try this route:
get 'book*id' => 'bookscontroller#show'
Check this article: https://www.railsmine.net/2014/10/route-globbing-in-ruby-on-rails.html
As #qdx47 has mentioned you'd better follow convention, but if you must not, I think you can override to_param on book model, like:
def to_param
"book#{id}"
end
and then define routes like
get ':id', to: 'books#show', constraints => { :book_id => /book[0-9]+/ }
I think you can give a try to below gem.
Friendly Id Gem
Then you will be able to generate slug that can be any unique string. By default it will be uuid but you can override it. Follow gem documentation. It will allow you generate routes like http://localhost:3000/books/book123.
In general, I think you would be going against convention and best practices by formatting your route in this way.
With that caveat, you should be able to define a route like so:
get(':book_id', 'books#show', constraints => { :book_id => /book[0-9]+/ })
You would then need to extract the id from the 'book' literal in the controller.

Rails 4 - Hash in route gets rendered wrongly

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

Rails always routes an action to show action, and the action it self becomes the id

There's a strange behavior in rails I found recently related to routes and actions, specifically, it's on rails 2.3.5. I have a controller, let's call it Users. In the routes, I declare Users as a resources.
map.resources :users
And within the controller, I have the standard action: index, show, edit, update & destroy. Also, I added other action to fullfil certain requirements.
def generated_pdf_report
# do something
end
The problem is, when I go to page /users/generated_pdf_report, I get this on the console:
Processing UsersController#show (some timestamps) [GET]
Parameters: {"action"=>"show", "id"=>"generated_pdf_report", "controller"=>"users"}
As you can see, the server route the request to method show rather than to method generated_pdf_report. What's interesting, is that I have other controllers having similar action and is working fine.
The solution to the above problem is easy enough, make sure the added feed is above the resources:
map.feed 'users/generated_pdf_report', :controller => 'users', :action => 'generated_pdf_report'
map.resources :users
My question is: Anyone knows why rails behaves like that? The above solution is kind of sloppy, what do you think the best practices for such problem like one mentioned above.
As outlined in the Rails 2 routing guide, you can add collection routes like so:
map.resources :users, :collection => { :generated_pdf_report => :get }
When rails looks at
/users/generate_report
That is exactly the path it would use to show a user whose id was generate_report, so that is what it does, assuming you haven't told it otherwise.
A shorter alternative to what you wrote is
resources :users, :collection => {:generate_report => :get}
Which tells rails to map a GET to /users/generate_report to your generate_report action

Routing / in Rails

I'm writing a simple Rails app with one main controller and I want to map /(:action(:id)) to this controller (basically remove the controller prefix at the beginning), but still have the path helpers I get by using map.resources.
I tried map.root :controller => 'notes', but I get an error:
undefined method `note_path' for #<ActionView::Base:0x102038b50>
where I use the link_to_unless_current function in my view.
Edit: Here is the code in index.html.erb that gives the error.
<% for note in category.notes %>
<h3><%= link_to_unless_current h(numbered_title note), note %></h3>
<% end %>
UPDATE: I don't know how I came to this question, but author just pointed out that this is 3 years old, which I totally missed. I will leave this answer if somebody needs that behaviour in rails 3. In rails 2 it is not valid...
Route root will not work with whole controller as this has to point on specific action.
First parameter of resources will be used to determine path (normally it would be /notes) and at the same time to create helpers like notes_path. What you want to do is set this to '/', but also add :as option to give proper helpers names. So finally it should look like:
resources '/', controller: :notes, as: :notes
Also quite important thing to notice, if you want to use any other resources, you should put them above notes route. Otherwise rails will recognize resources name as id of notes action show.
Example:
resources '/', controller: :notes, as: :notes
resources :comments
Going to /comments will try to find note with id 'comments'.
resources :comments
resources '/', controller: :notes, as: :notes
Opening /comments will go to comments_controller#index.

Resources