ricordami 0.0.3 → 0.0.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/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
|