Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS 

Make your model play nice with SEO

## config/initializers/string_extensions.rb

require 'unicode'

class String
  def to_slug
    str = Unicode.normalize_KD(self).gsub(/[^\x00-\x7F]/n,'')
    str = str.gsub(/\W+/, '-').gsub(/^-+/,'').gsub(/-+$/,'').downcase
  end

  def numeric?
    if self =~ /^\d+$/
      self.to_i
    elsif self =~ /^\d+([,\.]\d+)?$/
      self.tr(',','.').to_f
    else
      false
    end
  end
end


## app/models/article.rb

# string :title
# text   :body
# string :permalink
class Article < ActiveRecord::Base
  before_save :set_permalink

  # article_path(@article)
  # >> /article/5
  # article_path(@article.permalink)
  # /article/pink-ferret
  def self.find(*args)
    if args.first.is_a?(String) and !args.first.numeric?
      find_by_permalink(args.shift,*args) or raise ActiveRecord::RecordNotFound
    else
      super
    end
  end

  # article_path(@article)
  # >> /article/5-pink-ferret
  def to_param
    "#{id}-#{permalink}"
  end

  private
  def set_permalink
    self.permalink = title.to_slug
  end
end

Helper for testing default routes generated by a resource in Ruby on Rails

These methods test that the routes for resources defined in routes.rb are working as expected. Call them from your functional (controller) tests.

Add the following 3 methods to test/test_helper.rb (updated for Rails 1.2.5 which no longer uses semicolons as a separator for the edit action):
# Test for routes generated by map.resource (singular).
def assert_routing_for_resource(controller, skip=[], nesting=[])
  routes = [
    ["new",'/new',{},:get], ["create",'',{},:post],
    ["show",'',{},:get], ["edit",'/edit',{},:get],
    ["update",'',{},:put], ["destroy",'',{},:delete]
    ]
  check_resource_routing(controller, routes, skip, nesting)
end
# Test for routes generated by map.resources (plural).
def assert_routing_for_resources(controller, skip=[], nesting=[])
  routes = [
    ["index",'',{},:get], ["new",'/new',{},:get], ["create",'',{},:post],
    ["show",'/1',{:id=>'1'},:get], ["edit",'/1/edit',{:id=>'1'},:get],
    ["update",'/1',{:id=>'1'},:put], ["destroy",'/1',{:id=>'1'},:delete]
    ]
  check_resource_routing(controller, routes, skip, nesting)
end

# Check that the expected paths will be generated by a resource, and that
# the expected params will be generated by paths defined by a resource.
# routes is array of [action, url string after controller, extra params].
def check_resource_routing(controller, routes, skip=[], nesting=[])
  # set a prefix for nested resources
  prefix = nesting.join('s/1/')
  unless prefix.blank?
    prefix += "s/1/"
  end
  # Add params for nested resources.
  # For each 'nest', include a ":nest_id=>'1'" param.
  params = {}
  nesting.each do |param|
    params["#{param}_id".to_sym] = '1'
  end
  # Test each of the standard resource routes.
  routes.each do |pair|
    unless skip.include? pair[0]
      assert_generates("/#{prefix}#{controller}#{pair[1]}",
        {:controller=>controller,
        :action=>pair[0]}.merge(pair[2]).merge(params), {}, {},
        "Failed generation of resource route for action #{pair[0]} /#{prefix}#{controller}#{pair[1]}")
      assert_recognizes(
        {:controller=>controller,
          :action=>pair[0]}.merge(pair[2]).merge(params),
        {:path=>"/#{prefix}#{controller}#{pair[1]}", :method=>pair[3]},
        {}, "Failed to recognize resource route for path #{pair[3]}:/#{prefix}#{controller}#{pair[1]}")
    end
  end
end

EXAMPLES

You can specify actions to 'skip' (if you have a special route for that action).
If using nested resources, set the nesting array (use singular strings).

So, if you have the following in routes.rb:
map.make_thing '/make', :controller=>'things', :action=>'new'
map.resources :nests do |nest|
  nest.resources :things
end
map.resource :foo

then you can use the following in things_controller_test.rb:
def test_resource_routing
  assert_routing_for_resources 'things', ['new'], ['nest']
  assert_routing_for_resource 'foo'
end
« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS