direct_address 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,25 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+
23
+ *.yml
24
+ *.log
25
+ *.gem
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Mike Nelson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,87 @@
1
+ = direct_address
2
+
3
+ Direct Address provides a rails app with simple address features. This is a streamlined implementation of address functionality. Direct Address provides you with address, country, and region classes. It also provides a generator which generates the necessary javascript and rake tasks to implement properly. You'll also get form helpers to easily implement Direct Address in your views. A rake task is provided that allows up to date country and region information to be downloaded from geoname.org.
4
+
5
+ == Installation
6
+
7
+ Add direct_address to your environment.rb
8
+
9
+ config.gem 'direct_address'
10
+
11
+ Then install the gem:
12
+
13
+ rake gems:install
14
+
15
+ After you've installed the gem, you'll need to generate your classes, javascript, and rake task.
16
+
17
+ script/generate direct_address
18
+
19
+ Once that's complete, migrate your database
20
+
21
+ rake db:migrate
22
+
23
+ Now you're ready to download up-to-date country and region information from geoname.org
24
+
25
+ rake direct_address:pull
26
+
27
+ <b>This will take a few minutes and should be done on a decent connection.</b>
28
+
29
+ == Usage
30
+
31
+ Once you've run the generators there's not much you need to do. You can utilize the classes as they are or you can use the acts_as_addressable option. To use acts_as_addressable, include it in your class like this:
32
+
33
+ class User < ActiveRecord::Base
34
+ acts_as_addressable
35
+ end
36
+
37
+ By doing this you are giving the user a single address. One thing to note is that the generator didn't create an addresses_controller or add any routes regarding addresses. By default, it is expected that the address form will be nested in the parent form. For this reason, the accepts_nested_attributes_for and attr_accessors are included in acts_as_addressable. If you'd like to implement things differently, create a controller and implement your models to your liking.
38
+
39
+ == Form Helpers
40
+
41
+ By including Direct Address in your project you've added a few form helpers. Their implementation is very easy. You can either use it within a form_for like this:
42
+
43
+ <% form_for @user do |user_form| %>
44
+ ...
45
+ <% user_form.fields_for :address do |address_form| %>
46
+ ...
47
+ <%= address_form.country_select %>
48
+ ...
49
+ <% end %>
50
+ ...
51
+ <% end %>
52
+
53
+ Or you can use it via a tag helper like this:
54
+
55
+ <%= country_select_tag 'user[account]' %>
56
+
57
+ Either way produces the same exact thing. Take note that this does require loading at least prototype *beforehand* and the country_select file before the page load is complete. If you do like to defer the loading of extra scripts, feel free to do so with country_select. The setup doesn't occur until the window.onload event is fired. An example load order would be:
58
+
59
+ <script type="text/javascript" src="javascripts/prototype.js"></script>
60
+
61
+ POINT A
62
+
63
+ ...
64
+ <% form... %>
65
+ <%= f.country_select %>
66
+ <% end %>
67
+ ...
68
+
69
+ POINT B
70
+
71
+ Where the following call could be at either POINT A or POINT B:
72
+
73
+ <script type="text/javascript" src="javascripts/country_select.js"></script>
74
+
75
+ == Note on Patches/Pull Requests
76
+
77
+ * Fork the project.
78
+ * Make your feature addition or bug fix.
79
+ * Add tests for it. This is important so I don't break it in a
80
+ future version unintentionally.
81
+ * Commit, do not mess with rakefile, version, or history.
82
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
83
+ * Send me a pull request. Bonus points for topic branches.
84
+
85
+ == Copyright
86
+
87
+ Copyright (c) 2010 Mike Nelson. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "direct_address"
8
+ gem.summary = "short summary"
9
+ gem.description = "long summary"
10
+ gem.email = "mn@mcaddie.com"
11
+ gem.homepage = "http://github.com/mnelson/direct_address"
12
+ gem.authors = ["Mike Nelson"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "direct_address #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,76 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{direct_address}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Mike Nelson"]
12
+ s.date = %q{2010-02-17}
13
+ s.description = %q{long summary}
14
+ s.email = %q{mn@mcaddie.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "direct_address-0.0.2.gem",
27
+ "direct_address.gemspec",
28
+ "generators/direct_address/direct_address_generator.rb",
29
+ "generators/direct_address/templates/controllers/regions_controller.rb",
30
+ "generators/direct_address/templates/js/country_select.js",
31
+ "generators/direct_address/templates/migrations/direct_address_migration.rb",
32
+ "generators/direct_address/templates/models/address.rb",
33
+ "generators/direct_address/templates/models/country.rb",
34
+ "generators/direct_address/templates/models/region.rb",
35
+ "generators/direct_address/templates/tasks/harvest.rake",
36
+ "generators/direct_address/templates/views/index.json.erb",
37
+ "lib/direct_address.rb",
38
+ "lib/direct_address/acts_as_addressable.rb",
39
+ "lib/direct_address/form_builder.rb",
40
+ "lib/direct_address/form_helper.rb",
41
+ "lib/direct_address/harvester/extend_string.rb",
42
+ "lib/direct_address/harvester/geoname.rb",
43
+ "spec/database.yml",
44
+ "spec/debug.log",
45
+ "spec/direct_address_spec.rb",
46
+ "spec/model/user.rb",
47
+ "spec/schema.rb",
48
+ "spec/spec.opts",
49
+ "spec/spec_helper.rb"
50
+ ]
51
+ s.homepage = %q{http://github.com/mnelson/direct_address}
52
+ s.rdoc_options = ["--charset=UTF-8"]
53
+ s.require_paths = ["lib"]
54
+ s.rubygems_version = %q{1.3.5}
55
+ s.summary = %q{short summary}
56
+ s.test_files = [
57
+ "spec/direct_address_spec.rb",
58
+ "spec/model/user.rb",
59
+ "spec/schema.rb",
60
+ "spec/spec_helper.rb"
61
+ ]
62
+
63
+ if s.respond_to? :specification_version then
64
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
65
+ s.specification_version = 3
66
+
67
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
68
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
69
+ else
70
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
71
+ end
72
+ else
73
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
74
+ end
75
+ end
76
+
@@ -0,0 +1,24 @@
1
+ class DirectAddressGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+
5
+ m.file "js/country_select.js", "public/javascripts/country_select.js"
6
+
7
+ m.directory "app/views/regions"
8
+ m.file "views/index.json.erb", "app/views/regions/index.json.erb"
9
+
10
+ m.file "controllers/regions_controller.rb", "app/controllers/regions_controller.rb"
11
+
12
+ %w(address country region).each do |model|
13
+ m.file "models/#{model}.rb", "app/models/#{model}.rb"
14
+ end
15
+
16
+ m.route_resources :regions
17
+
18
+ m.migration_template "migrations/direct_address_migration.rb", "db/migrate", {:migration_file_name => "direct_address_migration"}
19
+
20
+ m.file "tasks/harvest.rake", "lib/tasks/direct_address_harvest.rake"
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ class RegionsController < ApplicationController
2
+
3
+ def index
4
+ @regions = params[:country_id] && Region.by_country(params[:country_id])
5
+ respond_to do |format|
6
+ format.json
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,33 @@
1
+ if(typeof(Prototype) != 'undefined'){
2
+
3
+ CountrySelect = Class.create({
4
+ initialize : function(args){
5
+ this.country_select = $(args['country_select_id']);
6
+ this.region_select = $(args['region_select_id']);
7
+ this.country_select.observe('change', this.update_regions.bind(this));
8
+ },
9
+ update_regions : function(event){
10
+ this.region_select.selectedIndex = -1;
11
+ var country_id = this.selected_country()[0];
12
+ new Ajax.Request('/regions.json?country_id=' + country_id, {method : 'get', onComplete : function(transport){
13
+ var regions = transport.responseJSON;
14
+ this.populate_regions(regions);
15
+ }.bind(this)});
16
+ },
17
+ selected_country : function(){
18
+ var elem = this.country_select.childElements()[this.country_select.selectedIndex];
19
+ return [elem.value, elem.innerHTML]
20
+ },
21
+ populate_regions : function(regions){
22
+ var html = ['<option value="">Select a Region</option>', regions.collect(function(region){
23
+ return '<option value="' + region.id + '">' + region.name + '</option>';
24
+ })].flatten().join('');
25
+ this.region_select.update(html);
26
+ if(regions.length == 0)
27
+ this.region_select.hide();
28
+ else
29
+ this.region_select.show();
30
+ }
31
+ });
32
+
33
+ } else { try{ console.log('Prototype must be preloaded for country_select.js to work properly.'); } catch (e) {}}
@@ -0,0 +1,39 @@
1
+ class DirectAddressMigration < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :regions do |t|
4
+ t.references :country
5
+ t.string :name
6
+ t.timestamps
7
+ end
8
+
9
+ add_index :regions, :country_id
10
+
11
+ create_table :addresses do |t|
12
+ t.references :addressable, :polymorphic => true, :null => false
13
+ t.references :country
14
+ t.references :region
15
+ t.string :street1
16
+ t.string :street2
17
+ t.string :city
18
+ t.string :postal
19
+ t.timestamps
20
+ end
21
+
22
+ add_index :addresses, [:addressable_id, :addressable_type]
23
+ add_index :addresses, [:country_id]
24
+ add_index :addresses, [:region_id]
25
+
26
+ create_table :countries do |t|
27
+ t.string :abbreviation
28
+ t.string :name
29
+ t.timestamps
30
+ end
31
+
32
+ end
33
+
34
+ def self.down
35
+ drop_table :regions
36
+ drop_table :countries
37
+ drop_table :addresses
38
+ end
39
+ end
@@ -0,0 +1,24 @@
1
+ class Address < ActiveRecord::Base
2
+
3
+ belongs_to :addressable, :polymorphic => true
4
+ belongs_to :country
5
+ belongs_to :region
6
+
7
+
8
+ def single_line
9
+ multiline.join(', ')
10
+ end
11
+
12
+ def multiline
13
+ [street1, street2, [city, region_name, postal].compact.join(' '), country_abbrev].compact.collect{|s| s.length > 0 && s}
14
+ end
15
+
16
+ def region_name
17
+ self.region && self.region.name || nil
18
+ end
19
+
20
+ def country_abbrev
21
+ self.country && self.country.abbrev || nil
22
+ end
23
+
24
+ end
@@ -0,0 +1,18 @@
1
+ class Country < ActiveRecord::Base
2
+
3
+ has_many :regions
4
+
5
+ validates_presence_of :abbreviation, :name
6
+ validates_length_of :abbreviation, :is => 2
7
+ alias_attribute :abbrev, :abbreviation
8
+
9
+ default_scope :order => 'name ASC'
10
+
11
+ before_create :format_abbreviation
12
+
13
+ private
14
+
15
+ def format_abbreviation
16
+ self.abbreviation = self.abbreviation.upcase
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ class Region < ActiveRecord::Base
2
+
3
+ belongs_to :country
4
+ validates_presence_of :name, :country
5
+
6
+ default_scope :order => 'name ASC'
7
+
8
+ named_scope :by_country, lambda {|country| country && (country.is_a?(Country) && (country = country.id) || true) && {:conditions => ['country_id = ?', country]} || {}}
9
+ end
@@ -0,0 +1,13 @@
1
+
2
+ begin
3
+ require File.dirname(__FILE__) + '/../../config/environment.rb'
4
+
5
+ namespace :direct_address do
6
+ desc "pulls up to date country and region data from geonames.org"
7
+ task :pull do
8
+ Geoname.retrieve_to_db
9
+ end
10
+ end
11
+ rescue
12
+ puts "Direct address harvester not properly installed"
13
+ end
@@ -0,0 +1 @@
1
+ <%= @regions.collect{|region| {:id => region.id, :name => region.name}}.to_json %>
@@ -0,0 +1,20 @@
1
+ module Direct
2
+ module Address
3
+
4
+ def self.included(base)
5
+ base.extend ::Direct::Address::ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ def acts_as_addressable
11
+ has_one :address, :as => :addressable
12
+ accepts_nested_attributes_for :address
13
+ attr_accessible :address_attributes
14
+ end
15
+ end
16
+
17
+ end
18
+ end
19
+
20
+ ::ActiveRecord::Base.send(:include, ::Direct::Address)
@@ -0,0 +1,25 @@
1
+ module ActionView
2
+ module Helpers
3
+ module CountryAndRegion
4
+
5
+ def self.included(base)
6
+ base.class_eval do
7
+ include ActionView::Helpers::CountryAndRegion::InstanceMethods
8
+ end
9
+ end
10
+
11
+ module InstanceMethods
12
+ def country_select
13
+ @countries ||= Country.all
14
+ sanitized_object_id = self.object_name.split('[').collect{|s| (s = s.gsub(']','')) && s.size > 0 && s || nil}.compact.join('_')
15
+ html = self.select(:country_id, ([['Select a Country', nil]] + @countries.collect{|country| [country.name, country.id]}))
16
+ html << self.select(:region_id, ([['Select a Region', nil]] + (self.object && self.object.country && self.object.country.regions.collect{|region| [region.name, region.id]} || [])))
17
+ html << "<script type=\"text/javascript\">if(typeof(Prototype) != 'undefined'){Element.observe(window, 'load', function(){if(typeof(CountrySelect) == 'undefined'){try{console.log('country_select.js not loaded.');} catch (e) {};return;};new CountrySelect({country_select_id : '#{sanitized_object_id}_country_id', region_select_id : '#{sanitized_object_id}_region_id'})});}else{document.getElementById('#{sanitized_object_id}_country_id').style.display = 'none';document.getElementById('#{sanitized_object_id}_region_id').style.display = 'none';}</script>"
18
+ html
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ ::ActionView::Helpers::FormBuilder.send :include, ActionView::Helpers::CountryAndRegion
@@ -0,0 +1,30 @@
1
+
2
+ module ActionView
3
+ module Helpers
4
+ module CountryAndRegionHelper
5
+
6
+ def self.included(base)
7
+ base.class_eval do
8
+ include ActionView::Helpers::CountryAndRegionHelper::InstanceMethods
9
+ end
10
+ end
11
+
12
+ module InstanceMethods
13
+ def country_select_tag(object_string, country_id = nil, region_id = nil)
14
+ object_string = object_string.to_s
15
+ object_id = object_string.split('[').collect{|s| (s = s.gsub(']','')) && s.size > 0 && s || nil}.compact.join('_')
16
+ @countries ||= Country.all
17
+ @regions = !country_id.nil? && Region.by_country(country_id) || []
18
+ country_options = options_for_select([['Select a Country', nil]] + @countries.collect{|country| [country.name, country.id]}, country_id)
19
+ region_options = options_for_select([['Select a Region', nil]] + @regions.collect{|region| [region.name, region.id]}, region_id)
20
+ html = select_tag("#{object_string}[country_id]", country_options, :id => "#{object_id}_country_id")
21
+ html << select_tag("#{object_string}[region_id]", region_options, :id => "#{object_id}_region_id")
22
+ html << "<script type=\"text/javascript\">if(typeof(Prototype) != 'undefined'){Element.observe(window, 'load', function(){if(typeof(CountrySelect) == 'undefined'){try{console.log('country_select.js not loaded.');} catch (e) {};return;};new CountrySelect({country_select_id : '#{object_id}_country_id', region_select_id : '#{object_id}_region_id'});});}else{document.getElementById('#{object_id}_country_id').style.display = 'none';document.getElementById('#{object_id}_region_id').style.display = 'none';}</script>"
23
+ html
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+ end
30
+ ::ActionView::Base.send :include, ActionView::Helpers::CountryAndRegionHelper
@@ -0,0 +1,85 @@
1
+ # RemoveAccents version 1.0.3 (c) 2008-2009 Solutions Informatiques Techniconseils inc.
2
+ #
3
+ # This module adds 2 methods to the string class.
4
+ # Up-to-date version and documentation available at:
5
+ #
6
+ # http://www.techniconseils.ca/en/scripts-remove-accents-ruby.php
7
+ #
8
+ # This script is available under the following license :
9
+ # Creative Commons Attribution-Share Alike 2.5.
10
+ #
11
+ # See full license and details at :
12
+ # http://creativecommons.org/licenses/by-sa/2.5/ca/
13
+ #
14
+ # Version history:
15
+ # * 1.0.3 : July 23 2009
16
+ # Corrected some incorrect character codes. Source is now wikipedia at:
17
+ # http://en.wikipedia.org/wiki/ISO/IEC_8859-1#Related_character_maps
18
+ # Thanks to Raimon Fernandez for pointing out the incorrect codes.
19
+ # * 1.0.2 : October 29 2008
20
+ # Slightly optimized version of urlize - Jonathan Grenier (jgrenier@techniconseils.ca)
21
+ # * 1.0.1 : October 29 2008
22
+ # First public revision - Jonathan Grenier (jgrenier@techniconseils.ca)
23
+ #
24
+
25
+ class String
26
+ # The extended characters map used by removeaccents. The accented characters
27
+ # are coded here using their numerical equivalent to sidestep encoding issues.
28
+ # These correspond to ISO-8859-1 encoding.
29
+ ACCENTS_MAPPING = {
30
+ 'E' => [200,201,202,203],
31
+ 'e' => [232,233,234,235],
32
+ 'A' => [192,193,194,195,196,197],
33
+ 'a' => [224,225,226,227,228,229,230],
34
+ 'C' => [199],
35
+ 'c' => [231],
36
+ 'O' => [210,211,212,213,214,216],
37
+ 'o' => [242,243,244,245,246,248],
38
+ 'I' => [204,205,206,207],
39
+ 'i' => [236,237,238,239],
40
+ 'U' => [217,218,219,220],
41
+ 'u' => [249,250,251,252],
42
+ 'N' => [209],
43
+ 'n' => [241],
44
+ 'Y' => [221],
45
+ 'y' => [253,255],
46
+ 'AE' => [306],
47
+ 'ae' => [346],
48
+ 'OE' => [188],
49
+ 'oe' => [189]
50
+ }
51
+
52
+
53
+ # Remove the accents from the string. Uses String::ACCENTS_MAPPING as the source map.
54
+ def removeaccents
55
+ str = String.new(self)
56
+ String::ACCENTS_MAPPING.each {|letter,accents|
57
+ packed = accents.pack('U*')
58
+ rxp = Regexp.new("[#{packed}]", nil, 'U')
59
+ str.gsub!(rxp, letter)
60
+ }
61
+
62
+ str
63
+ end
64
+
65
+
66
+ # Convert a string to a format suitable for a URL without ever using escaped characters.
67
+ # It calls strip, removeaccents, downcase (optional) then removes the spaces (optional)
68
+ # and finally removes any characters matching the default regexp (/[^-_A-Za-z0-9]/).
69
+ #
70
+ # Options
71
+ #
72
+ # * :downcase => call downcase on the string (defaults to true)
73
+ # * :convert_spaces => Convert space to underscore (defaults to false)
74
+ # * :regexp => The regexp matching characters that will be converting to an empty string (defaults to /[^-_A-Za-z0-9]/)
75
+ def urlize(options = {})
76
+ options[:downcase] ||= true
77
+ options[:convert_spaces] ||= false
78
+ options[:regexp] ||= /[^-_A-Za-z0-9]/
79
+
80
+ str = self.strip.removeaccents
81
+ str.downcase! if options[:downcase]
82
+ str.gsub!(/\ /,'_') if options[:convert_spaces]
83
+ str.gsub(options[:regexp], '')
84
+ end
85
+ end