Custom URLs in rails app - ruby-on-rails

I'm trying to write a simple CMS in rails that will allow text urls rather than the standard /posts/show/<id>.
I have a model that has a title and body, I would like to replace spaces in the title and use it as the url.
I also want to have the url at the root level, not past /pages/show.

Take a look at this gem friendly_id, is used for create url from fields of the model storing it on database. Otherwise, you can create the route that you want example get 'pages/show', home#index and pointing wherever you want.

While the friendly_id gem is really nice, it's quite heavy for such a simple need. You might consider a lighter alternative approach : https://github.com/johnotander/urls_for_humans

You can override your rails urls by setting them like this:
get 'posts' => 'posts#index'
In your routes.
But since you want to format the url for the show action (which depends on a specific id for each item in posts) your best bet is to use the awesome friendly_id gem.
See: https://github.com/norman/friendly_id
Some resources:
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
http://blog.teamtreehouse.com/creating-vanity-urls-in-rails

I have figured out how to do what I wanted to do.
I am setting a route to the root url with a parameter like this (config/routes.rb):
get ':title', to: 'pages#show', as: :page
Now I have a pages controller that was generated by rails generate scaffold Page title:string body:text
which has a function set_page which I changed to do this (app/controllers/pages_controller.rb):
def set_page
#page = Page.find_by("title" => params[:title])
end

Related

Rails - Changing the URL title through Rails Routing

I asked this question on Code Review but they suggested I ask it here
I'm trying to create custom routes for every web page in my show action.
Movie.all.each do |movie|
match "/#{movie.title.downcase}", to: 'movies#show', via: 'get',
as: :"#{movie.title.downcase.gsub(/[:.]/, '').gsub(' ', '_')}"
end
This code matches every web page to my not found page.
resources :movies, except: [:show]
It should match the web page to the actual page.
I only have a show.html.erb file in my views folder. Could that be the problem?
Is it possible to use string interpolation on view file names?
I can't use Rails REST routing because I need to have better URLS.
/Movie Title
is a better URL then
/movies/1
That is why I need to optimize this code. It works, but it could use improvement.
I have no idea how to fix this. Here are a couple things I thought of.
Using Rails route redirection to another action
Using wildcard as view names (*.html.erb)
Remember: My only goal is to change the URL name to the movie's title
This can be easily achieved using FriendlyId gem
Here's the link:
https://github.com/norman/friendly_id/blob/master/README.md
Add it to your Gemfile
Then add following to your model:
class Movie < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
Then run this on rails console:
Movie.find_each(&:save)
To save slugs for existing movies
The documentation is quite good, feel free to comment if you have any trouble.

Change default attribute for routes path

Hello again stackoverflowers!
I want to create links but not using the default :id attribute, I would like for example
article_path(#article)
to generate
/articles/example-article
instead of the default
/articles/1
Bonus, I would like to make articles the default controller. I achieved this using:
root 'articles#index'
get ':name' => 'articles#show', as: 'article'
This works fine, but article_path still generates the id link
Try the friendly id gem:
https://github.com/norman/friendly_id
It is a powerful gem, I used in my old project.
have a look the following railscast to learn more about it
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid?view=asciicast

Adding a record's attribute to the URL before the ID

I'm trying to add a specific attribute of a record in Rails to the URL from something like:
domain.com/share/5
(where 5 is the record ID) to something like:
domain.com/share/johnsmith/5
where johnsmith is stored in record 5. I'm alternating between these two routes to no success:
get "/share/:name/:id" => "share#show"
resources :share, :only => [:show]
And between these two methods:
share_path(doc.user.name, doc)
share_path(doc)
The show method in the ShareController is pretty standard.
The problem:
Using share_path(doc.user.name, doc) in the view generates a link to /share/johnsmith.5, instead of /share/johnsmith/5.
get "/share/:name/:id" => "share#show" should do the job. But you may have to look at the order of routes in routes.rb, maybe Rails took the wrong route?
Best tip to look at what's happening:
Call the URL in your browser (or using curl or whatever) and then look into your console where your started rails s (or rails server).
There you should see something like this:
Processing by ShareController#show
Parameters: {"id"=>"5", "name"=>"johnsmith"}
Concerning the path methods:
Simply use rake routes, it will tell you which path methods are available.
No idea what happened but it resolved itself with this:
get "/share/:name/:id" => "share#show", :as => :share
share_path(doc.user.name, doc)
I do not get the . and / issue at all. I restarted everything and it was gone.

Rails "pretty URLs", using entries/23 or 2011/07/some-post-slug-here for creating URLs via helpers

I'm attempting to create "pretty URLs" for linking to posts in a blog. I want to maintain access to the blog entries via entries/23 and 2011/07/some-post-slug-here as I only generate a slug once an entry has been published (just in case the title of the posts changes, and, though not a strict requirement, I would prefer to be able to edit/delete posts via the entries/23 style URL. Currently, the appropriate part of what I have in my config/routes.rb:
root :to => 'entries#index'
resources :entries
match ':year/:month/:slug' => 'entries#show', :constraints => {
:year => /[0-9][0-9][0-9][0-9]/,
:month => /[0-9][0-9]/,
:slug => /[a-zA-Z0-9\-]+/
}, :as => :vanity_entry
and I use this (in my application helper) function for creating the links:
def appropriate_entry_path entry
if entry.published
vanity_entry_path entry.published_on.year.to_s, entry.published_on.month.to_s, entry.slug
else
entries_path entry
end
end
def appropriate_entry_url entry
if entry.published
vanity_entry_url entry.published_on.year.to_s, entry.published_on.month.to_s, entry.slug
else
entries_url entry
end
end
Basically, I check if the article is published (and therefore has a slug) and then use that URL/path helper, or otherwise use the default one.
However, when trying to use this, I get the following from Rails:
No route matches {:slug=>"try-this-one-on-for", :month=>"7", :controller=>"entries", :year=>"2011", :action=>"show"}
I have tried a few different solutions, including overriding to_param in my Entry model, however then I would have to create match routes for the edit/delete actions, and I would like to keep my routes.rb file as clean as possible. Ideally, I would also love to lose the appropriate_entry_path/appropriate_entry_url helper methods, but I'm not sure that this is possible?
Is there any thing I am missing regarding routing that might make this easier and/or is there any specific way of doing this that is the cleanest?
Thanks in advance.
You might want to take a look at friendly_id. It's a gem for creating seo friendly slugs :)
I found the issue with what I had been doing, the regex for :month in the route wanted two numbers, whereas I was only passing in one number. Anyways, I decided that the URLs look nicer (in my opinion) without the month padded to 2 digits, so I updated my route accordingly.

renaming routes (map, link_to, to_param) in rails

I'm having a little issue...I setup a rails application that is to serve a german website. To make use of Rails' internal pluralization features, I kept all my models in english (e.g. the model "JobDescription").
Now, if I call "http://mysite.com/job_descriptions/", I get all my job_descriptions....so far, so good. Because I didn't want the english term "job_descriptions" in my url, I put the following into my routes.rb
map.german_term '/german_term', :controller => 'job_descriptions', :action => 'index'
map.german_term '/german_term/:id', :controller => 'job_descriptions', :action => 'show'
If I call "http://mysite.com/german_term/" or "http://mysite.com/german_term/283" I get all my job_descriptions, which is fine.
However, to make the URL more SEO friendly, I'd like to exchange the id for a more userfriendly slug in the URL. Thus, I put the following in my job_description.rb:
def to_param
"#{id}-#{name.gsub(/[^a-z0-9]+/i, '-')}"
end
which, whenever I use "job_description_path" in any link_to method, renders my URLs out to something like "http://mysite/job_descriptions/13-my-job-description-title".
However, and this is where I'm stuck, I'd like to get "http://mysite/german_term/13-my-job-description-title". I already tried to exchange the "job_description_path" with "german_term_path" in the link_to code, but that only generates "http://mysite/german_term/13". Obviously, to_param isn't called.
One workaround I found is to build the link with:
<%= link_to job_description.name, german_term_path(job_description.to_param) %>
But that's rather tedious to change all the link_to calls in my code. What I want is to replace "job_description" by "german_term" whenever it occurs in a URL.
Any thoughts?!?
Regards,
Sebastian
I think you're going to need to use the restful route helpers to get what you want.
In that case, it wouldn't take much re-factoring (assuming you've mapped JobDescriptions as a resource). Leave your to_param as is and change your JobDescriptions route to something like the following:
map.resources :job_descriptions, :as => 'german_term'
Hope this helps!
Rails only utilizes the
def to_params
end
URL builder when you are using a restful route/link helper. The only way I am aware of is to do it similar to how you did, unless you are willing to just scrap your english language links and do it all in German. In that case, just get rid of the named route lines and change the to_params to use the correct name field from the database. At that point, the REST routes should behave correctly.

Resources