url_keyed_object 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -1,59 +1 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- require 'spec/rake/spectask'
5
- Spec::Rake::SpecTask.new(:spec) do |spec|
6
- spec.libs << 'lib' << 'spec'
7
- spec.spec_files = FileList['spec/**/*_spec.rb']
8
- end
9
-
10
- Spec::Rake::SpecTask.new(:rcov) do |spec|
11
- spec.libs << 'lib' << 'spec'
12
- spec.pattern = 'spec/**/*_spec.rb'
13
- spec.rcov = true
14
- end
15
-
16
- task :spec => :check_dependencies
17
-
18
- begin
19
- require 'cucumber/rake/task'
20
- namespace :cucumber do
21
- Cucumber::Rake::Task.new(:ok, 'Run features that should pass') do |t|
22
- t.fork = true # You may get faster startup if you set this to false
23
- t.profile = 'default'
24
- end
25
-
26
- Cucumber::Rake::Task.new(:wip, 'Run features that are being worked on') do |t|
27
- t.fork = true # You may get faster startup if you set this to false
28
- t.profile = 'wip'
29
- end
30
-
31
- desc 'Run all features'
32
- task :all => [:ok, :wip]
33
- end
34
- desc 'Alias for cucumber:ok'
35
- task :cucumber => 'cucumber:ok'
36
-
37
- task :default => :cucumber
38
-
39
- task :features => :cucumber do
40
- STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
41
- end
42
- rescue LoadError
43
- desc 'cucumber rake task not available (cucumber not installed)'
44
- task :cucumber do
45
- abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
46
- end
47
- end
48
-
49
- task :default => :spec
50
-
51
- require 'rake/rdoctask'
52
- Rake::RDocTask.new do |rdoc|
53
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
54
-
55
- rdoc.rdoc_dir = 'rdoc'
56
- rdoc.title = "url_keyed_object #{version}"
57
- rdoc.rdoc_files.include('README*')
58
- rdoc.rdoc_files.include('lib/**/*.rb')
59
- end
1
+ require 'bundler/gem_tasks'
@@ -1,4 +1,5 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
2
  require 'url_keyed_object/active_record'
3
+ require 'active_record'
3
4
 
4
- require 'spec/expectations'
5
+ require 'rspec/expectations'
@@ -1,15 +1,19 @@
1
1
  require 'fileutils'
2
2
 
3
3
  Before("@db") do |scenario|
4
- require 'activerecord'
4
+ require 'active_record'
5
+ require 'url_keyed_object/active_record'
6
+
5
7
  @db_dir = ::Dir.mktmpdir
6
8
  begin
7
- # Create the SQLite database
9
+ # Create the SQLite database, pretend the Railtie has run...
10
+ @recording_logger = RecordingLogger.new($stderr)
11
+
12
+ ActiveRecord::Base.extend UrlKeyedObject::ActiveRecord
8
13
  ActiveRecord::Base.establish_connection({'adapter' => 'sqlite3',
9
14
  'database' => "#{@db_dir}/feature.sqlite3", 'pool' => 5, 'timeout' => 5000
10
15
  })
11
16
  ActiveRecord::Base.connection
12
- @recording_logger = RecordingLogger.new($stderr)
13
17
  ActiveRecord::Base.logger = @recording_logger
14
18
  rescue
15
19
  $stderr.puts $!, *($!.backtrace)
@@ -21,4 +25,4 @@ After("@db") do |scenario|
21
25
  ActiveRecord::Base.connection.disconnect!
22
26
  FileUtils.remove_entry_secure @db_dir
23
27
  @recording_logger.reset_recorder!
24
- end
28
+ end
@@ -4,25 +4,25 @@ class RecordingLogger < Logger
4
4
  def recorded_messages
5
5
  @recorded_messages ||= {}
6
6
  end
7
-
7
+
8
8
  alias_method :add_original, :add
9
9
  def add(severity, message = nil, progname = nil, &block)
10
10
  record_it(severity, message)
11
11
  super
12
12
  end
13
-
14
-
13
+
14
+
15
15
  def reset_recorder!
16
16
  @recorded_messages = {}
17
17
  end
18
-
18
+
19
19
  def has_message_for_severity?(severity)
20
20
  (!recorded_messages[severity].nil? && !recorded_messages[severity].empty?)
21
21
  end
22
-
22
+
23
23
  private
24
-
24
+
25
25
  def record_it(severity, message)
26
26
  (recorded_messages[severity] ||= []) << message
27
27
  end
28
- end
28
+ end
@@ -1,36 +1,36 @@
1
1
  @db
2
2
  Feature: Using with ActiveRecord
3
- In order to generate and validate URL keys in an ActiveRecord::Base object
3
+ In order to generate and validate URL keys in an ActiveRecord::Base model in a Rails project
4
4
  A Rails developer
5
5
  Wants to include and use UrlKeyedObject
6
-
6
+
7
7
  # The most basic use case is for a 5-character ID, stored in the url_key column.
8
- #
9
- # Simply including the UrlKeyedObject::ActiveRecord module is enough.
8
+ #
9
+ # Simply extended the UrlKeyedObject::ActiveRecord module and calling has_url_key is enough.
10
10
  # This makes the url_key attribute protected from mass assignment and read-only.
11
11
  Background:
12
12
  Given a database, with this table defined:
13
13
  """
14
14
  create_table :things do |t|
15
15
  t.string :url_key, :null => false
16
-
16
+
17
17
  t.timestamps
18
18
  end
19
19
  """
20
20
  And this class:
21
21
  """
22
22
  class Thing < ActiveRecord::Base
23
- acts_as_url_keyed
23
+ has_url_key
24
24
  end
25
25
  """
26
-
26
+
27
27
  Scenario: An unsaved model object with UrlKeyedObject included
28
28
  When I make a bare instance:
29
29
  """
30
30
  @instance = Thing.new
31
31
  """
32
32
  Then @instance.url_key should be nil
33
-
33
+
34
34
  Scenario: A saved model object with UrlKeyedObject included
35
35
  When I make and save an instance:
36
36
  """
@@ -38,15 +38,14 @@ Feature: Using with ActiveRecord
38
38
  @instance.save!
39
39
  """
40
40
  Then @instance.url_key should match /^[a-z0-9]{5}$/
41
-
41
+
42
42
  Scenario: Attempting to mass-assign url_key ought to fail
43
43
  When I make an instance using mass-assignment:
44
44
  """
45
45
  @instance = Thing.new(:url_key => 'abcde')
46
46
  """
47
47
  Then @instance.url_key should be nil
48
- And a warning should have been logged
49
-
48
+
50
49
  Scenario: Attempting to set url_key ought to fail
51
50
  When I make an instance and set the value of url_key manually:
52
51
  """
@@ -1,36 +1,36 @@
1
1
  @db
2
2
  Feature: More advanced usage with ActiveRecord
3
- In order to generate and validate non-standard URL keys in an ActiveRecord::Base object
3
+ In order to generate and validate non-standard URL keys in an ActiveRecord::Base model in a Rails project
4
4
  A Rails developer
5
5
  Wants to include and use UrlKeyedObject
6
-
6
+
7
7
  # The default case is for a 5-character ID, stored in the url_key column.
8
8
  # Here we have an existing column we want to re-use, and we want a longer URL key
9
- #
9
+ #
10
10
  # calling acts_as_url_keyed and setting a couple of options is all that's needed.
11
11
  Background:
12
12
  Given a database, with this table defined:
13
13
  """
14
14
  create_table :advanced_things do |t|
15
15
  t.string :opaque_id, :null => false
16
-
16
+
17
17
  t.timestamps
18
18
  end
19
19
  """
20
20
  And this class:
21
21
  """
22
22
  class AdvancedThing < ActiveRecord::Base
23
- acts_as_url_keyed :url_key_column => :opaque_id, :url_key_length => 8
23
+ has_url_key :column => :opaque_id, :length => 8
24
24
  end
25
25
  """
26
-
26
+
27
27
  Scenario: An unsaved model object with UrlKeyedObject included
28
28
  When I make a bare instance:
29
29
  """
30
30
  @instance = AdvancedThing.new
31
31
  """
32
32
  Then @instance.opaque_id should be nil
33
-
33
+
34
34
  Scenario: A saved model object with an 8-character URL key on #opaque_id
35
35
  When I make and save an instance:
36
36
  """
@@ -38,15 +38,14 @@ Feature: More advanced usage with ActiveRecord
38
38
  @instance.save!
39
39
  """
40
40
  Then @instance.opaque_id should match /^[a-z0-9]{8}$/
41
-
41
+
42
42
  Scenario: Attempting to mass-assign opaque_id ought to fail
43
43
  When I make an instance using mass-assignment:
44
44
  """
45
45
  @instance = AdvancedThing.new(:opaque_id => 'abcde')
46
46
  """
47
47
  Then @instance.opaque_id should be nil
48
- And a warning should have been logged
49
-
48
+
50
49
  Scenario: Attempting to set opaque_id ought to fail
51
50
  When I make an instance and set the value of opaque_id manually:
52
51
  """
@@ -1,63 +1,58 @@
1
1
  require 'url_keyed_object'
2
- require 'active_record'
2
+ require 'active_support/concern'
3
3
 
4
4
  module UrlKeyedObject
5
- module ActiveRecordHook
6
- def acts_as_url_keyed(opts = {})
7
- attr_writer :url_key_length
8
-
9
- @url_key_column = opts[:url_key_column] if opts.has_key?(:url_key_column)
10
- @url_key_length = opts[:url_key_length] if opts.has_key?(:url_key_length)
11
-
12
- send :include, UrlKeyedObject::ActiveRecord
13
-
5
+ module ActiveRecord
6
+ def has_url_key(opts = {})
7
+ url_key_column = opts.has_key?(:column) ? opts[:column] : :url_key
8
+ url_key_length = opts.has_key?(:length) ? opts[:length] : 5
9
+
10
+ include UrlKeyedObject::ActiveRecord::Extensions
11
+
12
+ attr_protected url_key_column
14
13
  before_create :generate_valid_url_key
15
-
16
- define_method("#{url_key_column}=") { |value| logger.warn("Attempt to set ##{url_key_column}!"); nil }
14
+
15
+ @url_key_helper = UrlKeyedObject::ActiveRecord::Helper.new(self, url_key_column, url_key_length)
16
+
17
+ define_method("#{url_key_column}=") { |value| logger.warn("Attempt to set ##{url_key_column}!") if self.respond_to?(:logger); nil }
17
18
  end
18
- end
19
-
20
- module ActiveRecord
21
- # def url_key=(value)
22
- # logger.warn('Attempt to set #url_key!')
23
- # nil
24
- # end
25
-
26
- module ClassMethods
27
- def url_key_column
28
- @url_key_column ||= :url_key
19
+
20
+ class Helper
21
+ attr_reader :klass, :column, :length
22
+
23
+ def initialize(klass, column, length)
24
+ @klass = klass
25
+ @column = column
26
+ @length = length
29
27
  end
30
-
31
- def url_key_length
32
- @url_key_length ||= 5
28
+
29
+ def generate_valid_url_key(instance)
30
+ new_url_key = UrlKeyedObject.generate_checked_url_key(length) { |value| valid_url_key?(value) }
31
+ instance.send(:write_attribute, column, new_url_key)
32
+ end
33
+
34
+ def valid_url_key?(url_key)
35
+ klass.send("find_by_#{column}", url_key).nil?
33
36
  end
34
37
  end
35
-
36
- def self.included(model_class)
37
- model_class.extend ClassMethods
38
- end
39
-
40
- def to_param
41
- send url_key_column
42
- end
43
-
38
+
39
+ module Extensions
40
+ extend ActiveSupport::Concern
41
+
42
+ def to_param
43
+ send self.class.url_key_helper.column
44
+ end
45
+
46
+ module ClassMethods
47
+ def url_key_helper
48
+ @url_key_helper
49
+ end
50
+ end
51
+
44
52
  protected
45
-
46
- def generate_valid_url_key
47
- new_url_key = UrlKeyedObject.generate_checked_url_key(url_key_length) { |value| self.valid_url_key?(value) }
48
- write_attribute(url_key_column, new_url_key)
49
- end
50
-
51
- def valid_url_key?(url_key)
52
- self.class.send("find_by_#{url_key_column}", url_key).nil?
53
- end
54
-
55
- def url_key_column
56
- self.class.url_key_column
57
- end
58
-
59
- def url_key_length
60
- self.class.url_key_length
53
+ def generate_valid_url_key
54
+ self.class.url_key_helper.generate_valid_url_key(self)
55
+ end
61
56
  end
62
57
  end
63
- end
58
+ end
@@ -4,7 +4,7 @@ require 'url_keyed_object/active_record'
4
4
  module UrlKeyedObject
5
5
  class Railtie < Rails::Railtie
6
6
  initializer 'url_keyed_object.active_record_hook', :after => :preload_frameworks do
7
- ::ActiveRecord::Base.extend UrlKeyedObject::ActiveRecordHook
7
+ ::ActiveRecord::Base.extend UrlKeyedObject::ActiveRecord
8
8
  end
9
9
  end
10
- end
10
+ end
@@ -11,14 +11,14 @@ module UrlKeyedObject
11
11
  "m", "n", "p", "q", "r", "s", "v", "w", "x", "y",
12
12
  "z"]
13
13
  end
14
-
14
+
15
15
  # generates a url key from a random 5-digit base 31 number, without checking its uniqueness
16
16
  def generate_unchecked_url_key(length = 5)
17
17
  (1..length).collect do
18
18
  key_encoding[rand(31)]
19
19
  end.join('')
20
20
  end
21
-
21
+
22
22
  # Keeps generating new URL keys until the passed-in block returns true
23
23
  def generate_checked_url_key(length = 5)
24
24
  key = generate_unchecked_url_key(length)
@@ -27,16 +27,22 @@ module UrlKeyedObject
27
27
  end
28
28
  key
29
29
  end
30
-
30
+
31
31
  # Validate the well-formedness of a URL key
32
32
  def well_formed_url_key?(url_key, length = 5)
33
33
  !url_key.match(Regexp.new("^[0-9abcdefghjkmnpqrsvwxyz]{#{length.to_i}}$")).nil?
34
34
  end
35
-
35
+
36
36
  # decode a moderately dirty URL key
37
37
  def decode_url_key(url_key)
38
38
  url_key.downcase.tr('o', '0').tr('il', '1')
39
39
  end
40
+
41
+ # decode and validate a key, returning the decoded key only if it's well-formed
42
+ def decode_well_formed_url_key(url_key, length = 5)
43
+ decoded_url_key = decode_url_key(url_key)
44
+ well_formed_url_key?(decoded_url_key, length) ? decoded_url_key : nil
45
+ end
40
46
  end
41
47
  end
42
48
 
data/spec/spec_helper.rb CHANGED
@@ -1,17 +1,13 @@
1
- $:.unshift(File.dirname(__FILE__))
2
- $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
- require 'rubygems'
4
- gem 'activerecord'
1
+ lib_path = File.expand_path('../../lib', __FILE__)
2
+ $:.unshift(lib_path) unless $:.include?(lib_path)
3
+
5
4
  require 'url_keyed_object'
6
- require 'url_keyed_object/active_record'
7
- require 'spec'
8
- require 'spec/autorun'
9
5
 
10
- Spec::Runner.configure do |config|
6
+ RSpec.configure do |config|
11
7
  config.mock_with :mocha
12
8
  end
13
9
 
14
- Spec::Matchers.define :use_method do |method|
10
+ RSpec::Matchers.define :use_method do |method|
15
11
  chain :for_callback do |callback|
16
12
  @callback = callback
17
13
  end
@@ -29,9 +25,9 @@ class Class
29
25
  public *saved_private_instance_methods
30
26
  public *saved_protected_instance_methods
31
27
  end
32
-
28
+
33
29
  yield
34
-
30
+
35
31
  self.class_eval do
36
32
  private *saved_private_instance_methods
37
33
  protected *saved_protected_instance_methods
@@ -1,101 +1,94 @@
1
1
  require 'spec_helper'
2
- require 'active_record'
3
- require 'tmpdir'
4
- require 'fileutils'
5
- require 'logger'
6
-
7
- class SpecMigration < ActiveRecord::Migration
8
- def self.up
9
- create_table :things do |t|
10
- t.string :url_key, :null => false
11
-
12
- t.timestamps
2
+ require 'active_model/callbacks'
3
+ require 'active_model/mass_assignment_security'
4
+
5
+ require 'url_keyed_object/active_record'
6
+
7
+
8
+ class UrlKeyedModel
9
+ extend ActiveModel::Callbacks
10
+ include ActiveModel::MassAssignmentSecurity
11
+
12
+ define_model_callbacks :create
13
+
14
+ def initialize(attrs = {})
15
+ @attributes = sanitize_for_mass_assignment(attrs)
16
+ end
17
+
18
+ def url_key
19
+ @attributes[:url_key]
20
+ end
21
+
22
+ def read_attribute(key)
23
+ @attributes[key]
24
+ end
25
+
26
+ def write_attribute(key, value)
27
+ @attributes[key] = value
28
+ end
29
+
30
+ extend UrlKeyedObject::ActiveRecord
31
+
32
+ has_url_key
33
+
34
+ def save
35
+ run_callbacks :create do
36
+ #logic
13
37
  end
14
38
  end
15
39
  end
16
40
 
17
41
  describe UrlKeyedObject::ActiveRecord do
18
- before(:all) do
19
- @db_dir = ::Dir.mktmpdir
20
- begin
21
- # Create the SQLite database
22
- ActiveRecord::Base.establish_connection({'adapter' => 'sqlite3',
23
- 'database' => "#{@db_dir}/spec.sqlite3", 'pool' => 5, 'timeout' => 5000
24
- })
25
- ActiveRecord::Base.connection
26
- rescue
27
- $stderr.puts $!, *($!.backtrace)
28
- $stderr.puts "Couldn't create database for #{"#{@db_dir}/feature.sqlite3".inspect}"
29
- end
30
-
31
- SpecMigration.migrate(:up)
32
-
33
- @url_keyed_class = Class.new(ActiveRecord::Base)
34
- @url_keyed_class.class_eval do
35
- set_table_name 'things'
36
- def self.name
37
- 'UrlKeyedObjectMock'
38
- end
39
-
40
- acts_as_url_keyed
41
- end
42
-
43
- ActiveRecord::Base.logger = Logger.new(STDERR)
44
- end
45
-
46
- after(:all) do
47
- ActiveRecord::Base.connection.disconnect!
48
- FileUtils.remove_entry_secure @db_dir
49
- end
50
-
51
- it "should protect URL keys from mass-assignment" do
52
- url_keyed_object = @url_keyed_class.new(:url_key => 'woo')
53
-
42
+ let(:url_keyed_object) { UrlKeyedModel.new }
43
+
44
+ it "protects URL keys from mass-assignment" do
45
+ url_keyed_object = UrlKeyedModel.new(:url_key => 'woo')
46
+
54
47
  url_keyed_object.url_key.should be_nil
55
48
  end
56
-
57
- it "should not allow URL keys to be set" do
58
- url_keyed_object = @url_keyed_class.new
59
-
49
+
50
+ it "does not allow URL keys to be set" do
60
51
  url_keyed_object.url_key = 'dfghj'
61
-
52
+
62
53
  url_keyed_object.url_key.should be_nil
63
54
  end
64
-
65
- describe "ensuring unique URL keys get created " do
66
- it "should be able to verify that a URL key is valid" do
67
- @url_keyed_class.expects(:find_by_url_key).with('a_url').returns(nil)
68
- url_keyed_object = @url_keyed_class.new
69
-
70
- @url_keyed_class.publicize_methods do
71
- url_keyed_object.valid_url_key?('a_url').should be_true
72
- end
55
+
56
+ it "returns the contents of the url_key column for to_param" do
57
+ url_keyed_object.stubs(:url_key).returns('hello')
58
+
59
+ url_keyed_object.to_param.should == 'hello'
60
+ end
61
+
62
+ describe "ensuring unique URL keys get created" do
63
+ let(:ar_helper) { UrlKeyedObject::ActiveRecord::Helper.new(UrlKeyedModel, :url_key, 5) }
64
+
65
+ it "can verify that a URL key is valid" do
66
+ UrlKeyedModel.expects(:find_by_url_key).with('a_url').returns(nil)
67
+
68
+ ar_helper.valid_url_key?('a_url').should be_true
73
69
  end
74
-
75
- it "should be able to verify that a URL key is not valid" do
76
- @url_keyed_class.expects(:find_by_url_key).with('a_url').returns(@url_keyed_class.new)
77
- url_keyed_object = @url_keyed_class.new
78
-
79
- @url_keyed_class.publicize_methods do
80
- url_keyed_object.valid_url_key?('a_url').should be_false
81
- end
70
+
71
+ it "can verify that a URL key is not valid" do
72
+ UrlKeyedModel.expects(:find_by_url_key).with('a_url').returns(UrlKeyedModel.new)
73
+
74
+ ar_helper.valid_url_key?('a_url').should be_false
82
75
  end
83
-
84
- it "should be able to keep attempting to create a URL key until one is valid" do
85
- url_keyed_object = @url_keyed_class.new
86
-
76
+
77
+ it "keeps attempting to create a URL key until one is valid" do
78
+ url_keyed_object = UrlKeyedModel.new
79
+
87
80
  UrlKeyedObject.expects(:generate_checked_url_key).yields('a2url').returns('a2url')
88
- url_keyed_object.expects(:valid_url_key?).with('a2url').returns(true)
89
-
90
- @url_keyed_class.publicize_methods do
91
- url_keyed_object.generate_valid_url_key
92
-
93
- url_keyed_object.url_key.should == 'a2url'
94
- end
81
+ ar_helper.expects(:valid_url_key?).with('a2url').returns(true)
82
+
83
+ ar_helper.generate_valid_url_key(url_keyed_object)
84
+
85
+ url_keyed_object.url_key.should == 'a2url'
95
86
  end
96
-
97
- it "should use a before_create callback to ensure that a URL key is created" do
98
- @url_keyed_class.should use_method(:generate_valid_url_key).for_callback(:before_create)
87
+
88
+ it "uses a before_create callback to ensure that a URL key is created" do
89
+ UrlKeyedModel.url_key_helper.expects(:generate_valid_url_key).with(url_keyed_object)
90
+
91
+ url_keyed_object.save
99
92
  end
100
93
  end
101
- end
94
+ end
@@ -4,30 +4,30 @@ describe UrlKeyedObject do
4
4
  it "should be able to generate a 5-character URL key" do
5
5
  UrlKeyedObject.generate_unchecked_url_key.should match(/[0-9abcdefghjkmnpqrsvwxyz]{5}/)
6
6
  end
7
-
7
+
8
8
  it "should be able to generate an arbitrary-length URL key" do
9
9
  UrlKeyedObject.generate_unchecked_url_key(7).should match(/[0-9abcdefghjkmnpqrsvwxyz]{7}/)
10
10
  end
11
-
11
+
12
12
  describe "decoding a moderately dirty URL key (case insensitivity, ambiguous character replacement)" do
13
13
  it "should be able to cope with O o 0 ambiguity" do
14
14
  UrlKeyedObject.decode_url_key('Oo0ab').should == '000ab'
15
15
  end
16
-
16
+
17
17
  it "should be able to cope with 1 I i L l ambiguity" do
18
18
  UrlKeyedObject.decode_url_key('1IiLl').should == '11111'
19
19
  end
20
-
20
+
21
21
  it "should be able to cope with uppercase" do
22
22
  UrlKeyedObject.decode_url_key('ABCDE').should == 'abcde'
23
23
  end
24
24
  end
25
-
25
+
26
26
  describe "well-formedness of URL keys" do
27
27
  it "should be able to confirm that a URL key is well-formed" do
28
28
  UrlKeyedObject.well_formed_url_key?('0ab9d').should be_true
29
29
  end
30
-
30
+
31
31
  it "should report that malformed URL keys are NOT well-formed" do
32
32
  ['DfZZZ', # upper case
33
33
  'abcdef', # too long
@@ -41,12 +41,12 @@ describe UrlKeyedObject do
41
41
  UrlKeyedObject.well_formed_url_key?(malformed_url_key).should be_false
42
42
  end
43
43
  end
44
-
44
+
45
45
  it "should be able to cope with a different specified length" do
46
46
  UrlKeyedObject.well_formed_url_key?('abcdef', 6).should be_true
47
47
  end
48
48
  end
49
-
49
+
50
50
  describe "validity of URL keys" do
51
51
  it "should be able to evaluate a block to check key validity, repeating until it generates one" do
52
52
  valid_key_sequence = sequence('valid key sequence')
@@ -54,14 +54,17 @@ describe UrlKeyedObject do
54
54
  in_sequence(valid_key_sequence)
55
55
  UrlKeyedObject.expects(:generate_unchecked_url_key).with(5).returns('a2url').
56
56
  in_sequence(valid_key_sequence)
57
-
57
+
58
58
  key = UrlKeyedObject.generate_checked_url_key { |value| value != 'a1url' }
59
-
59
+
60
60
  key.should == 'a2url'
61
61
  end
62
-
63
- it "should description" do
64
-
65
- end
66
62
  end
67
- end
63
+
64
+ it "can return a decoded key that has been checked for well-formedness" do
65
+ UrlKeyedObject.expects(:decode_url_key).with('ABCDE').returns('abcde')
66
+ UrlKeyedObject.expects(:well_formed_url_key?).with('abcde', 5).returns('abcde')
67
+
68
+ UrlKeyedObject.decode_well_formed_url_key('ABCDE').should == 'abcde'
69
+ end
70
+ end
metadata CHANGED
@@ -1,73 +1,80 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: url_keyed_object
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 3
8
- - 0
9
- version: 0.3.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Matt Patterson
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2010-06-11 00:00:00 +01:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2010-06-11 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rspec
16
+ requirement: &2164422500 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '2.8'
22
+ type: :development
22
23
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 1
29
- - 2
30
- - 9
31
- version: 1.2.9
24
+ version_requirements: *2164422500
25
+ - !ruby/object:Gem::Dependency
26
+ name: mocha
27
+ requirement: &2164422000 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
32
33
  type: :development
33
- version_requirements: *id001
34
- - !ruby/object:Gem::Dependency
35
- name: cucumber
36
34
  prerelease: false
37
- requirement: &id002 !ruby/object:Gem::Requirement
38
- requirements:
39
- - - ">="
40
- - !ruby/object:Gem::Version
41
- segments:
42
- - 0
43
- - 5
44
- version: "0.5"
35
+ version_requirements: *2164422000
36
+ - !ruby/object:Gem::Dependency
37
+ name: cucumber
38
+ requirement: &2164421340 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0.5'
45
44
  type: :development
46
- version_requirements: *id002
47
- - !ruby/object:Gem::Dependency
45
+ prerelease: false
46
+ version_requirements: *2164421340
47
+ - !ruby/object:Gem::Dependency
48
48
  name: activerecord
49
+ requirement: &2164420800 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
55
+ type: :development
49
56
  prerelease: false
50
- requirement: &id003 !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- segments:
55
- - 2
56
- - 3
57
- version: "2.3"
57
+ version_requirements: *2164420800
58
+ - !ruby/object:Gem::Dependency
59
+ name: sqlite3
60
+ requirement: &2164420300 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
58
66
  type: :development
59
- version_requirements: *id003
60
- description: Making it easy to work with Rails objects which use a URL key in their URL instead of their database ID.
67
+ prerelease: false
68
+ version_requirements: *2164420300
69
+ description: Making it easy to work with Rails objects which use a URL key in their
70
+ URL instead of their database ID.
61
71
  email: matt@reprocessed.org
62
72
  executables: []
63
-
64
73
  extensions: []
65
-
66
- extra_rdoc_files:
74
+ extra_rdoc_files:
67
75
  - LICENSE
68
76
  - README.rdoc
69
- files:
70
- - VERSION
77
+ files:
71
78
  - README.rdoc
72
79
  - LICENSE
73
80
  - Rakefile
@@ -76,38 +83,44 @@ files:
76
83
  - lib/url_keyed_object/railtie.rb
77
84
  - lib/url_keyed_object.rb
78
85
  - rails/init.rb
79
- has_rdoc: true
86
+ - spec/spec_helper.rb
87
+ - spec/url_keyed_object/active_record_spec.rb
88
+ - spec/url_keyed_object_spec.rb
89
+ - features/step_definitions/database_steps.rb
90
+ - features/step_definitions/eval_steps.rb
91
+ - features/step_definitions/feedback_steps.rb
92
+ - features/support/env.rb
93
+ - features/support/hooks.rb
94
+ - features/support/recording_logger.rb
95
+ - features/for_url_key-like_uses.feature
96
+ - features/with_active_record-basic.feature
97
+ - features/with_active_record-more-advanced.feature
80
98
  homepage: http://github.com/fidothe/url_keyed_object
81
99
  licenses: []
82
-
83
100
  post_install_message:
84
- rdoc_options:
101
+ rdoc_options:
85
102
  - --charset=UTF-8
86
- require_paths:
103
+ require_paths:
87
104
  - lib
88
- required_ruby_version: !ruby/object:Gem::Requirement
89
- requirements:
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- segments:
93
- - 0
94
- version: "0"
95
- required_rubygems_version: !ruby/object:Gem::Requirement
96
- requirements:
97
- - - ">="
98
- - !ruby/object:Gem::Version
99
- segments:
100
- - 0
101
- version: "0"
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
102
117
  requirements: []
103
-
104
118
  rubyforge_project:
105
- rubygems_version: 1.3.6
119
+ rubygems_version: 1.8.10
106
120
  signing_key:
107
121
  specification_version: 3
108
122
  summary: Making it easy to work with objects with URL keys
109
- test_files:
110
- - spec/spec.opts
123
+ test_files:
111
124
  - spec/spec_helper.rb
112
125
  - spec/url_keyed_object/active_record_spec.rb
113
126
  - spec/url_keyed_object_spec.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.3.0
data/spec/spec.opts DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --format=specdoc