ricordami 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -3
- data/lib/ricordami/has_attributes.rb +1 -0
- data/lib/ricordami/has_indices.rb +1 -2
- data/lib/ricordami/unique_index.rb +20 -5
- data/lib/ricordami/unique_validator.rb +5 -1
- data/lib/ricordami/version.rb +1 -1
- data/spec/ricordami/can_be_validated_spec.rb +14 -1
- data/spec/ricordami/has_attributes_spec.rb +6 -0
- data/spec/ricordami/has_indices_spec.rb +7 -0
- data/spec/ricordami/model_spec.rb +0 -3
- data/spec/ricordami/unique_index_spec.rb +7 -0
- data/spec/ricordami/unique_validator_spec.rb +14 -0
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
# Changelog #
|
2
2
|
|
3
|
-
## 0.0.
|
3
|
+
## 0.0.4 (March 13th, 2011) ##
|
4
|
+
|
5
|
+
- add a scope option to validates_uniqueness_of validation macro
|
6
|
+
- allow to pass nil when creating a new instance
|
7
|
+
- added a spec for update_attributes with an invalid model
|
8
|
+
|
9
|
+
## 0.0.3 (March 12th, 2011) ##
|
4
10
|
|
5
11
|
- added serialization (use: "model\_can :be_serialized") to have
|
6
12
|
access to Model#to_json and Model#to_xml
|
7
13
|
|
8
|
-
## 0.0.2 (March 5th, 2011)
|
14
|
+
## 0.0.2 (March 5th, 2011) ##
|
9
15
|
|
10
16
|
- added examples and fixed README
|
11
17
|
- created a basic Ricordami::Model#to_s method
|
12
18
|
|
13
|
-
## 0.0.1 (March 5th, 2011)
|
19
|
+
## 0.0.1 (March 5th, 2011) ##
|
14
20
|
|
15
21
|
Initial release.
|
16
22
|
|
@@ -12,8 +12,7 @@ module Ricordami
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def index(options = {})
|
15
|
-
|
16
|
-
options.assert_valid_keys(:unique, :get_by, :value)
|
15
|
+
options.assert_valid_keys(:unique, :get_by, :value, :scope)
|
17
16
|
fields = options.delete(:unique)
|
18
17
|
return unique_index(fields, options) if fields.present?
|
19
18
|
field = options.delete(:value)
|
@@ -4,13 +4,17 @@ module Ricordami
|
|
4
4
|
class UniqueIndex
|
5
5
|
SEPARATOR = "_-::-_"
|
6
6
|
|
7
|
-
attr_reader :model, :fields, :name, :need_get_by
|
7
|
+
attr_reader :model, :fields, :name, :need_get_by, :scope
|
8
8
|
|
9
9
|
def initialize(model, fields, options = {})
|
10
10
|
@model = model
|
11
|
-
@fields =
|
12
|
-
@need_get_by = options[:get_by] && @fields != [:id]
|
11
|
+
@fields = normalize_array(fields)
|
13
12
|
@name = @fields.join("_").to_sym
|
13
|
+
@need_get_by = options[:get_by] && @fields != [:id]
|
14
|
+
if options.has_key?(:scope)
|
15
|
+
@scope = normalize_array(options[:scope])
|
16
|
+
@fields.push(*@scope)
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
20
|
def uidx_key_name
|
@@ -22,7 +26,7 @@ module Ricordami
|
|
22
26
|
end
|
23
27
|
|
24
28
|
def add(id, value)
|
25
|
-
value =
|
29
|
+
value = normalize_value(value)
|
26
30
|
@model.redis.sadd(uidx_key_name, value)
|
27
31
|
@model.redis.hset(ref_key_name, value, id) if @need_get_by
|
28
32
|
end
|
@@ -35,7 +39,7 @@ module Ricordami
|
|
35
39
|
return commands
|
36
40
|
end
|
37
41
|
@model.redis.hdel(ref_key_name, id) if @need_get_by
|
38
|
-
value =
|
42
|
+
value = normalize_value(value)
|
39
43
|
@model.redis.srem(uidx_key_name, value)
|
40
44
|
end
|
41
45
|
|
@@ -55,5 +59,16 @@ module Ricordami
|
|
55
59
|
def include?(value)
|
56
60
|
@model.redis.sismember(uidx_key_name, value)
|
57
61
|
end
|
62
|
+
|
63
|
+
def normalize_value(value)
|
64
|
+
value.is_a?(Array) ? value.join(SEPARATOR) : value
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def normalize_array(array)
|
70
|
+
return [] if array.nil?
|
71
|
+
[array].flatten.map(&:to_sym)
|
72
|
+
end
|
58
73
|
end
|
59
74
|
end
|
@@ -6,6 +6,10 @@ module Ricordami
|
|
6
6
|
return true unless record.new_record? || record.send(:attribute_changed?, attribute)
|
7
7
|
index_name = attribute.to_sym
|
8
8
|
index = record.class.indices[index_name]
|
9
|
+
if index.scope
|
10
|
+
scope_values = index.scope.map { |field| record.send(field) }
|
11
|
+
value = index.normalize_value([value].push(*scope_values))
|
12
|
+
end
|
9
13
|
if index.include?(value)
|
10
14
|
attr_def = record.class.attributes[attribute]
|
11
15
|
unless record.persisted? && attr_def.read_only?
|
@@ -15,7 +19,7 @@ module Ricordami
|
|
15
19
|
end
|
16
20
|
|
17
21
|
def setup(klass)
|
18
|
-
attributes.each { |attribute| klass.index :unique => attribute }
|
22
|
+
attributes.each { |attribute| klass.index :unique => attribute, :scope => options[:scope] }
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
data/lib/ricordami/version.rb
CHANGED
@@ -50,7 +50,7 @@ describe Ricordami::CanBeValidated do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
describe "#save" do
|
53
|
+
describe "#save and #update_attributes" do
|
54
54
|
uses_constants("Post")
|
55
55
|
|
56
56
|
before(:each) do
|
@@ -69,6 +69,11 @@ describe Ricordami::CanBeValidated do
|
|
69
69
|
it "can save if it is not valid but passed :validate => false" do
|
70
70
|
Post.new.save(:validate => false).should be_true
|
71
71
|
end
|
72
|
+
|
73
|
+
it "can't #update_attributes if it is not valid" do
|
74
|
+
post = Post.create(:title => "blah")
|
75
|
+
post.update_attributes(:title => "").should be_false
|
76
|
+
end
|
72
77
|
end
|
73
78
|
|
74
79
|
describe "validate attribute uniqueness" do
|
@@ -111,5 +116,13 @@ describe Ricordami::CanBeValidated do
|
|
111
116
|
fred.should have(1).error
|
112
117
|
fred.errors[:wife].should == ["is already used"]
|
113
118
|
end
|
119
|
+
|
120
|
+
it "allows to validate the uniqueness using a scope" do
|
121
|
+
User.validates_uniqueness_of(:wife, :scope => :username)
|
122
|
+
serge = User.create(:id => "serge", :username => "Gainsbourg", :wife => "Rita")
|
123
|
+
fred = User.new(:username => "Chichin", :wife => "Rita")
|
124
|
+
fred.should be_valid
|
125
|
+
fred.should have(0).errors
|
126
|
+
end
|
114
127
|
end
|
115
128
|
end
|
@@ -38,6 +38,12 @@ describe Ricordami::HasAttributes do
|
|
38
38
|
attribute.initial_value.should == "2"
|
39
39
|
attribute.initial_value.should == "3"
|
40
40
|
end
|
41
|
+
|
42
|
+
it "can create a new instance without parameters, with nil or an empty hash" do
|
43
|
+
Boat.new.attributes.should == {"id" => nil}
|
44
|
+
Boat.new(nil).attributes.should == {"id" => nil}
|
45
|
+
Boat.new({}).attributes.should == {"id" => nil}
|
46
|
+
end
|
41
47
|
end
|
42
48
|
|
43
49
|
describe "an instance" do
|
@@ -27,6 +27,13 @@ describe Ricordami::HasIndices do
|
|
27
27
|
Car.indices[:model].should == index
|
28
28
|
end
|
29
29
|
|
30
|
+
it "can give a scope to a unique index with :scope option" do
|
31
|
+
Car.attribute :brand
|
32
|
+
index = Car.index :unique => :model, :scope => :brand
|
33
|
+
Car.indices[:model].scope.should == [:brand]
|
34
|
+
Car.indices[:model].fields.should == [:model, :brand]
|
35
|
+
end
|
36
|
+
|
30
37
|
it "discards the subsequent declarations if the same index is created more than once" do
|
31
38
|
Car.index :unique => :model, :get_by => true
|
32
39
|
Car.indices[:model].need_get_by.should be_true
|
@@ -6,6 +6,7 @@ describe Ricordami::UniqueIndex do
|
|
6
6
|
before(:each) do
|
7
7
|
create_constant("DataSource")
|
8
8
|
DataSource.attribute :name
|
9
|
+
DataSource.attribute :owner
|
9
10
|
@index = subject.new(DataSource, :id)
|
10
11
|
end
|
11
12
|
|
@@ -15,6 +16,12 @@ describe Ricordami::UniqueIndex do
|
|
15
16
|
@index.name.should == :id
|
16
17
|
end
|
17
18
|
|
19
|
+
it "can have a scope" do
|
20
|
+
index = subject.new(DataSource, :id, :scope => :owner)
|
21
|
+
index.scope.should == [:owner]
|
22
|
+
index.fields.should == [:id, :owner]
|
23
|
+
end
|
24
|
+
|
18
25
|
it "returns its internal index name with #uidx_key_name" do
|
19
26
|
@index.uidx_key_name.should == "DataSource:udx:id"
|
20
27
|
end
|
@@ -38,4 +38,18 @@ describe Ricordami::UniqueValidator do
|
|
38
38
|
validator.validate_each(sophie, :name, record.name)
|
39
39
|
sophie.errors[:name].should == ["come on, man!"]
|
40
40
|
end
|
41
|
+
|
42
|
+
it "accepts a scope option to limit the unicity constraint" do
|
43
|
+
Call.attribute :family
|
44
|
+
validator = Ricordami::UniqueValidator.new(:attributes => [:name], :scope => :family)
|
45
|
+
validator.setup(Call)
|
46
|
+
Call.create(:name => "john", :family => "jones")
|
47
|
+
john = Call.new(:name => "john", :family => "jones")
|
48
|
+
validator.validate_each(john, :name, john.name)
|
49
|
+
john.should have(1).error
|
50
|
+
john.family = "doe"
|
51
|
+
john.errors.clear
|
52
|
+
validator.validate_each(john, :name, john.name)
|
53
|
+
john.should have(0).errors
|
54
|
+
end
|
41
55
|
end
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: ricordami
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Mathieu Lajugie
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-03-12
|
13
|
+
date: 2011-03-12 23:00:00 -08:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|