active_url 0.1.4
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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.textile +454 -0
- data/Rakefile +57 -0
- data/VERSION.yml +4 -0
- data/active_url.gemspec +72 -0
- data/lib/active_url.rb +20 -0
- data/lib/active_url/base.rb +103 -0
- data/lib/active_url/belongs_to.rb +32 -0
- data/lib/active_url/callbacks.rb +17 -0
- data/lib/active_url/configuration.rb +5 -0
- data/lib/active_url/crypto.rb +34 -0
- data/lib/active_url/errors.rb +4 -0
- data/lib/active_url/validations.rb +57 -0
- data/rails/init.rb +1 -0
- data/spec/belongs_to_spec.rb +94 -0
- data/spec/callbacks_spec.rb +45 -0
- data/spec/crypto_spec.rb +27 -0
- data/spec/instance_spec.rb +138 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/validations_spec.rb +131 -0
- metadata +91 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveUrl do
|
|
4
|
+
before(:each) do
|
|
5
|
+
ActiveUrl::Config.stub!(:secret).and_return("secret")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
context "instance with callbacks" do
|
|
9
|
+
before(:all) do
|
|
10
|
+
class ::Registration < ActiveUrl::Base
|
|
11
|
+
attribute :email
|
|
12
|
+
after_save :send_registration_email
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
after(:all) do
|
|
17
|
+
Object.send(:remove_const, "Registration")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
before(:each) do
|
|
21
|
+
@registration = Registration.new(:email => "email@example.com")
|
|
22
|
+
@registration.stub!(:valid?).and_return(true)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should not run the callback when saved if the instance is invalid" do
|
|
26
|
+
@registration.stub!(:valid?).and_return(false)
|
|
27
|
+
@registration.should_not_receive(:send_registration_email)
|
|
28
|
+
@registration.save
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should run the callback when saved if the instance is valid" do
|
|
32
|
+
@registration.should_receive(:send_registration_email)
|
|
33
|
+
@registration.save
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should not run the callback when found from its ID" do
|
|
37
|
+
@registration.stub!(:send_registration_email).and_return(true)
|
|
38
|
+
@registration.save
|
|
39
|
+
@found = Registration.new
|
|
40
|
+
Registration.should_receive(:new).and_return(@found)
|
|
41
|
+
@found.should_not_receive(:send_registration_email)
|
|
42
|
+
Registration.find(@registration.id)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
data/spec/crypto_spec.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveUrl do
|
|
4
|
+
before(:each) do
|
|
5
|
+
ActiveUrl::Config.stub!(:secret).and_return("secret")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe "crypto" do
|
|
9
|
+
it "should raise ArgumentError when no secret is set" do
|
|
10
|
+
ActiveUrl::Config.stub!(:secret).and_return(nil)
|
|
11
|
+
lambda { ActiveUrl::Crypto.encrypt("clear") }.should raise_error(ArgumentError)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should decode what it encodes" do
|
|
15
|
+
ActiveUrl::Crypto.decrypt(ActiveUrl::Crypto.encrypt("clear")).should == "clear"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should always yield URL-safe output characters" do
|
|
19
|
+
url_safe = /^[\w\-]*$/
|
|
20
|
+
(1..20).each do |n|
|
|
21
|
+
clear = (0...8).inject("") { |string, n| string << rand(255).chr } # random string
|
|
22
|
+
cipher = ActiveUrl::Crypto.encrypt(clear)
|
|
23
|
+
cipher.should =~ url_safe
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveUrl do
|
|
4
|
+
before(:each) do
|
|
5
|
+
ActiveUrl::Config.stub!(:secret).and_return("secret")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
context "instance" do
|
|
9
|
+
before(:each) do
|
|
10
|
+
@url = ActiveUrl::Base.new
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should have nil id" do
|
|
14
|
+
@url.id.should be_nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should be a new_record" do
|
|
18
|
+
@url.should be_new_record
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should be saveable" do
|
|
22
|
+
@url.save.should be_true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context "after saving" do
|
|
26
|
+
before(:each) do
|
|
27
|
+
@url.save
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should have an id" do
|
|
31
|
+
@url.id.should_not be_blank
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should not be a new record" do
|
|
35
|
+
@url.should_not be_new_record
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "derived" do
|
|
41
|
+
before(:all) do
|
|
42
|
+
class ::DerivedClass < ActiveUrl::Base
|
|
43
|
+
attribute :foo, :bar
|
|
44
|
+
attribute :baz, :accessible => true
|
|
45
|
+
attr_accessible :bar
|
|
46
|
+
|
|
47
|
+
attr_accessor :x, :y
|
|
48
|
+
attr_accessible :y
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
after(:all) do
|
|
53
|
+
Object.send(:remove_const, "DerivedClass")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "instance" do
|
|
57
|
+
it "should have individually accessible attribute readers" do
|
|
58
|
+
@url = DerivedClass.new
|
|
59
|
+
[ :foo, :bar, :baz ].each { |reader| @url.public_methods.map(&:to_sym).should include(reader) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should have individually accessible attribute setters" do
|
|
63
|
+
@url = DerivedClass.new
|
|
64
|
+
[ :foo=, :bar=, :baz= ].each { |setter| @url.public_methods.map(&:to_sym).should include(setter) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should not mass-assign attributes by default" do
|
|
68
|
+
@url = DerivedClass.new(:foo => "foo")
|
|
69
|
+
@url.foo.should be_nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should mass-assign attributes declared as attr_accessible" do
|
|
73
|
+
@url = DerivedClass.new(:bar => "bar")
|
|
74
|
+
@url.bar.should == "bar"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should mass-assigned attributes with :accessible specified on declaration" do
|
|
78
|
+
@url = DerivedClass.new(:baz => "baz")
|
|
79
|
+
@url.baz.should == "baz"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should not mass-assign virtual attributes by default" do
|
|
83
|
+
@url = DerivedClass.new(:x => "x")
|
|
84
|
+
@url.x.should be_nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "should mass-assign its accessible virtual attributes" do
|
|
88
|
+
@url = DerivedClass.new(:y => "y")
|
|
89
|
+
@url.y.should == "y"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should know its mass-assignable attribute names" do
|
|
93
|
+
@url = DerivedClass.new
|
|
94
|
+
[ :bar, :baz, :y ].each { |name| @url.accessible_attributes.should include(name) }
|
|
95
|
+
[ :foo, :x ].each { |name| @url.accessible_attributes.should_not include(name) }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should know its attribute names" do
|
|
99
|
+
@url = DerivedClass.new
|
|
100
|
+
[ :foo, :bar, :baz ].each { |name| @url.attribute_names.should include(name) }
|
|
101
|
+
[ :x, :y ].each { |name| @url.attribute_names.should_not include(name) }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context "equality" do
|
|
105
|
+
before(:all) do
|
|
106
|
+
class ::OtherClass < DerivedClass
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
after(:all) do
|
|
111
|
+
Object.send(:remove_const, "OtherClass")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should be based on class and attributes only" do
|
|
115
|
+
@url = DerivedClass.new(:bar => "bar", :baz => "baz")
|
|
116
|
+
@url2 = DerivedClass.new(:bar => "bar", :baz => "baz")
|
|
117
|
+
@url3 = DerivedClass.new(:bar => "BAR", :baz => "baz")
|
|
118
|
+
@url4 = OtherClass.new(:bar => "bar", :baz => "baz")
|
|
119
|
+
@url.should == @url2
|
|
120
|
+
@url.should_not == @url3
|
|
121
|
+
@url.should_not == @url4
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
context "class" do
|
|
127
|
+
it "should know its mass-assignable attribute names" do
|
|
128
|
+
[ :bar, :baz, :y ].each { |name| DerivedClass.accessible_attributes.should include(name) }
|
|
129
|
+
[ :foo, :x ].each { |name| DerivedClass.accessible_attributes.should_not include(name) }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "should know its attribute names" do
|
|
133
|
+
[ :foo, :bar, :baz ].each { |name| DerivedClass.attribute_names.should include(name) }
|
|
134
|
+
[ :x, :y ].each { |name| DerivedClass.attribute_names.should_not include(name) }
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe ActiveUrl do
|
|
4
|
+
before(:each) do
|
|
5
|
+
ActiveUrl::Config.stub!(:secret).and_return("secret")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
context "instance with validations" do
|
|
9
|
+
before(:all) do
|
|
10
|
+
class ::Registration < ActiveUrl::Base
|
|
11
|
+
attribute :name, :email, :password, :age, :accessible => true
|
|
12
|
+
validates_presence_of :name
|
|
13
|
+
validates_format_of :email, :with => /^[\w\.=-]+@[\w\.-]+\.[a-zA-Z]{2,4}$/ix
|
|
14
|
+
validates_length_of :password, :minimum => 8
|
|
15
|
+
validates_numericality_of :age
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
after(:all) do
|
|
20
|
+
Object.send(:remove_const, "Registration")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
context "when invalid" do
|
|
24
|
+
before(:each) do
|
|
25
|
+
@registration = Registration.new(:email => "user @ example . com", :password => "short", :age => "ten")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should not validate" do
|
|
29
|
+
@registration.should_not be_valid
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should not save" do
|
|
33
|
+
@registration.save.should_not be_true
|
|
34
|
+
@registration.id.should be_nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should raise ActiveUrl::InvalidRecord when saved with bang" do
|
|
38
|
+
lambda { @registration.save! }.should raise_error(ActiveUrl::RecordInvalid)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context "and saved" do
|
|
42
|
+
before(:each) do
|
|
43
|
+
@registration.save
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should have errors" do
|
|
47
|
+
@registration.errors.should_not be_empty
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should validate presence of an attribute" do
|
|
51
|
+
@registration.errors[:name].should_not be_blank
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should validate format of an attribute" do
|
|
55
|
+
@registration.errors[:email].should_not be_blank
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should validate length of an attribute" do
|
|
59
|
+
@registration.errors[:password].should_not be_nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should validate numericality of an attribute" do
|
|
63
|
+
@registration.errors[:age].should_not be_nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
context "when valid" do
|
|
69
|
+
before(:each) do
|
|
70
|
+
@registration = Registration.new(:name => "John Doe", :email => "user@example.com", :password => "password", :age => "10")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should validate" do
|
|
74
|
+
@registration.should be_valid
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context "and saved" do
|
|
78
|
+
before(:each) do
|
|
79
|
+
@registration.save
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should have an id" do
|
|
83
|
+
@registration.id.should_not be_blank
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "should have a param equal to its id" do
|
|
87
|
+
@registration.id.should == @registration.to_param
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
context "and re-found by its class" do
|
|
91
|
+
before(:each) do
|
|
92
|
+
@found = Registration.find(@registration.id)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "should exist" do
|
|
96
|
+
@found.should_not be_nil
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "should have the same id" do
|
|
100
|
+
@found.id.should == @registration.id
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should have the same attributes" do
|
|
104
|
+
@found.attributes.should == @registration.attributes
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "should be valid" do
|
|
108
|
+
@found.should be_valid
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
context "and subsequently made invalid" do
|
|
113
|
+
before(:each) do
|
|
114
|
+
@registration.password = "short"
|
|
115
|
+
@registration.stub!(:valid?).and_return(true)
|
|
116
|
+
@registration.save
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "should not be found by its class" do
|
|
120
|
+
@registration.id.should_not be_blank
|
|
121
|
+
lambda { Registration.find(@registration.id) }.should raise_error(ActiveUrl::RecordNotFound)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it "should raise ActiveUrl::RecordNotFound if id does not exist" do
|
|
128
|
+
lambda { Registration.find("blah") }.should raise_error(ActiveUrl::RecordNotFound)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: active_url
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.4
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Matthew Hollingworth
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-10-10 00:00:00 +11:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: activerecord
|
|
17
|
+
type: :runtime
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: "0"
|
|
24
|
+
version:
|
|
25
|
+
description: " ActiveUrl enables the storing of a model in an encrypted URL. It facilitates implementation\n of secret URLs for user (e.g. feed URLs) that can be accessed without logging in, and URLs\n for confirming the email address of a new user.\n"
|
|
26
|
+
email: mdholling@gmail.com
|
|
27
|
+
executables: []
|
|
28
|
+
|
|
29
|
+
extensions: []
|
|
30
|
+
|
|
31
|
+
extra_rdoc_files:
|
|
32
|
+
- LICENSE
|
|
33
|
+
- README.textile
|
|
34
|
+
files:
|
|
35
|
+
- .document
|
|
36
|
+
- .gitignore
|
|
37
|
+
- LICENSE
|
|
38
|
+
- README.textile
|
|
39
|
+
- Rakefile
|
|
40
|
+
- VERSION.yml
|
|
41
|
+
- active_url.gemspec
|
|
42
|
+
- lib/active_url.rb
|
|
43
|
+
- lib/active_url/base.rb
|
|
44
|
+
- lib/active_url/belongs_to.rb
|
|
45
|
+
- lib/active_url/callbacks.rb
|
|
46
|
+
- lib/active_url/configuration.rb
|
|
47
|
+
- lib/active_url/crypto.rb
|
|
48
|
+
- lib/active_url/errors.rb
|
|
49
|
+
- lib/active_url/validations.rb
|
|
50
|
+
- rails/init.rb
|
|
51
|
+
- spec/belongs_to_spec.rb
|
|
52
|
+
- spec/callbacks_spec.rb
|
|
53
|
+
- spec/crypto_spec.rb
|
|
54
|
+
- spec/instance_spec.rb
|
|
55
|
+
- spec/spec_helper.rb
|
|
56
|
+
- spec/validations_spec.rb
|
|
57
|
+
has_rdoc: true
|
|
58
|
+
homepage: http://github.com/mholling/active_url
|
|
59
|
+
licenses: []
|
|
60
|
+
|
|
61
|
+
post_install_message:
|
|
62
|
+
rdoc_options:
|
|
63
|
+
- --charset=UTF-8
|
|
64
|
+
require_paths:
|
|
65
|
+
- lib
|
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
67
|
+
requirements:
|
|
68
|
+
- - ">="
|
|
69
|
+
- !ruby/object:Gem::Version
|
|
70
|
+
version: "0"
|
|
71
|
+
version:
|
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: "0"
|
|
77
|
+
version:
|
|
78
|
+
requirements: []
|
|
79
|
+
|
|
80
|
+
rubyforge_project:
|
|
81
|
+
rubygems_version: 1.3.5
|
|
82
|
+
signing_key:
|
|
83
|
+
specification_version: 3
|
|
84
|
+
summary: A Rails library for generating secret URLs.
|
|
85
|
+
test_files:
|
|
86
|
+
- spec/belongs_to_spec.rb
|
|
87
|
+
- spec/callbacks_spec.rb
|
|
88
|
+
- spec/crypto_spec.rb
|
|
89
|
+
- spec/instance_spec.rb
|
|
90
|
+
- spec/spec_helper.rb
|
|
91
|
+
- spec/validations_spec.rb
|