Making a Pretty Url via Ruby

Pretty URL in Rails when linking

If you are willing to accept: http:/.../1234-title-text you can just do:

def to_param
[id, title.parameterize].join("-")
end

AR::Base.find ignores the bit after the id, so it "just works".

To make the /title go away, try naming your route:

map.post ':id', :controller => 'posts', :action => 'show', :conditions => {:id => /[0-9]+-.*/ }

Ensure this route appears after any map.resources :posts call.

Rails POST forms to pretty URL

Your routes are given an automatic named path that you can see by typing rake routes. For example:

new_flag GET    /flags/new(.:format)      {:action=>"new", :controller=>"flags"}

You can refer to the path by using new_flag_path or new_flag_url

Your form_tag entry is kinda screwy. Instead of having a separate find method you could also use the index method, but that's your choice.

You may find it easier to use a standard redirect_to to redirect to a prettier URL based on inputs. If you don't want the redirect, then you'll need to use jQuery to change your form's action method dynamically. Searches typically use ugly GET parameters.

So I would change your code to look like this:

routes.rb

get 'routes/:from/to/:to' => 'finder#routes', :as => :find_from_to
post 'routes/find' => 'finder#find', :as => :find

_form.html.erb

<% form_tag find_path, :method => :post do %>
<%= label_tag(:from, "From:") %>
<%= text_field_tag(:from) %>
<%= label_tag(:to, "To:") %>
<%= text_field_tag(:to) %>
<%= submit_tag("Go") %>
<% end %>

finder_controller.rb

class FinderController < ApplicationController
def index
end

def find
if params[:from].blank? or params[:to].blank?
render :action => "invalid_results" and return
end
@from = Location.find_by_code(params[:from].upcase)
@to = Location.find_by_code(params[:to].upcase)
if @from.nil? or @to.nil?
render :action => "invalid_results" and return
end

redirect_to find_from_to_path(@from, @to)

end

def routes
@routes = Route.find_all_by_from_location_id_and_to_location_id(params[:from], params[:to])
end
end

How to make pretty url's with scopes using friendly_id?

You need friendly_id only to create slugs based on title of the category. If you want to make slug unique in scope of category you can use special friendly_id module to solve this problem.

To make nice nesting in url you can do something like this in your routes:

get 'blog/:category', to: 'articles#index', as: "category"

Something like this in your articles controller:

class ArticlesController < ApplicationController
def index
@category = Category.friendly.find(params[:category])
@articles = @category.articles
respond_to do |format|
# and so on...
end
end
end

And something like this in your views:

link_to category.title, category_url(category)

Clean url with rails

Answering the question #1:

I don't know the details of what's your overall goal, but if you'd like
to have such URLs that are based on records from the database - then yes: it's
a good approach.

Answering question #2 (regarding slugs):

I'd rather use something much more elaborate and well tested like:
https://github.com/norman/friendly_id

My 50 cents about some other things:

Is this one of your first projects in Ruby/Rails? If so - congratulations! :)
I'm asking because I noticed that you're using camel case here and there...

Also:

user_id = url.id.to_i

Why do you call this #to_i method here? Did you set up this id as a string
or something?

Hope this helps

Rails Pretty URL with Decimals

Use the :requirements => { :param_name => pattern_regex } param.

DECIMAL_PATTERN = /\A-?\d+(\.\d+)\z/.freeze
map.connect 'stores/near/:longitude/:latitude',
:controller => 'stores', :action => 'index',
:requirements => { :longitude => DECIMAL_PATTERN, :latitude => DECIMAL_PATTERN }

Parameters with dots on the URI

create a directory structure (with nested routes + pretty urls, ...)

The part of the code you should look at is:

class Location < ActiveRecord::Base
belongs_to :states
end

and it should be

class Location < ActiveRecord::Base
belongs_to :state
end

Another note, although not related to the error you are getting, Ruby programmers usually prefer array.each than for item in array.

Is it worth using pretty URLs if you don't care about SEO/SEM

It's always worth it if you just have the time to do it right.

  • Friendly-urls look a lot nicer and they give a better idea where the link will lead. This is useful if the link is shared eg. via instant message.
  • If you're searching for a specific page from browser history, human readable url helps.
  • Friendly url is a lot easier to remember (useful in some cases).
  • Like said earlier, it is also a lot easier to communicate verbally (needed more often than you'd think).
  • It hides unnecessary technical details from the user. In one case where user id was visible in the url, several users asked why their user id is higher than total amount of users. No damage done, but why have a confused user if you can avoid it.

how do I make the URL's in Ruby on Rails SEO friendly knowing a @vendor.name?

All of these solutions use find_by_name, which would definitely require having an index on that column and require they are unique. A better solution that we have used, sacrificing a small amount of beauty, is to use prefix the vendor name with its ID. This means that you dont have to have an index on your name column and/or require uniqueness.

vendor.rb

def to_param
normalized_name = name.gsub(' ', '-').gsub(/[^a-zA-Z0-9\_\-\.]/, '')
"#{self.id}-#{normalized_name}"
end

So this would give you URLs like

/1-Acme

/19-Safeway

etc

Then in your show action you can still use

Vendor.find(params[:id])

as that method will implicitly call .to_i on its argument, and calling to_i on such a string will always return the numerical prefix and drop the remaining text- its all fluff at that point.

The above assumes you are using the default route of /:controller/:action/:id, which would make your URLs look like

/vendors/show/1-Acme

But if you want them to just look

/1-Acme

Then have a route like

map.show_vendor '/:id', :controller => 'vendors', :action => 'show'

This would imply that that it would pretty much swallow alot of URLs that you probably wouldnt want it too. Take warning.



Related Topics



Leave a reply



Submit