datoki 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+
2
+
3
+ describe "Datoki.db" do
4
+
5
+ before {
6
+
7
+ CACHE[:datoki_db_test] ||= reset_db <<-EOF
8
+ CREATE TABLE "datoki_test" (
9
+ id serial NOT NULL PRIMARY KEY,
10
+ title varchar(123) NOT NULL,
11
+ body text DEFAULT 'hello'
12
+ );
13
+ EOF
14
+
15
+ @klass = Class.new {
16
+ include Datoki
17
+ table "datoki_test"
18
+ field(:id) { integer; primary_key }
19
+ field(:title) { varchar 1, 123 }
20
+ field(:body) { text nil, 1, 123 }
21
+ }
22
+ }
23
+
24
+ it 'raises Schema_Conflict if a field is found that allows null, but not specifed to do so' do
25
+ should.raise(Datoki::Schema_Conflict) {
26
+ Class.new {
27
+ include Datoki
28
+ table :datoki_test
29
+ field(:id) { integer; primary_key }
30
+ field(:title) { varchar 1, 123 }
31
+ field(:body) { text 1, 123 }
32
+ }
33
+ }.message.should.match /:allow_null: true != false/
34
+ end
35
+
36
+ it "requires field if value = null and :allow_null = false" do
37
+ should.raise(ArgumentError) {
38
+ @klass.create :title=>nil, :body=>"hiya"
39
+ }.message.should.match /:title is not set/
40
+ end
41
+
42
+ it "requires a value if: :text field, value = (empty string), min = 1, allow null" do
43
+ r = catch(:invalid) {
44
+ @klass.create :title=>"The title", :body=>' '
45
+ }
46
+ r.error.should == {:field_name=>:body, :msg=>'Body is required.', :value=>""}
47
+ end
48
+
49
+ it "does not turn strip.empty? strings into nulls" do
50
+ r = catch(:invalid) { @klass.create :title=>"The title", :body=>' ' }
51
+ r.clean[:body].should == ''
52
+ end
53
+
54
+ it "imports field names into class" do
55
+ @klass.fields.keys.should == [:id, :title, :body]
56
+ end
57
+
58
+ it "imports field types into class" do
59
+ @klass.fields.values.map { |meta| meta[:type] }.should == [:integer, :varchar, :text]
60
+ end
61
+
62
+ it "removes field from :clean data if set to nil and database has a default value" do
63
+ r = @klass.create :title=>'hello', :body=>nil
64
+ r.clean.keys.should == [:title]
65
+ end
66
+
67
+ end # === describe Datoki.db
@@ -0,0 +1,66 @@
1
+
2
+ describe Numeric do
3
+
4
+ before {
5
+ CACHE[:numeric_class] ||= begin
6
+ Class.new {
7
+ include Datoki
8
+ field(:id) { primary_key }
9
+ field(:age) { smallint 1, 150 }
10
+ }
11
+ end
12
+ }
13
+
14
+
15
+ it "fails if number is outside the range" do
16
+ r = catch(:invalid) {
17
+ CACHE[:numeric_class].create :age=>0
18
+ }
19
+ r.error[:msg].should.match /age must be between 1 and 150/i
20
+ end
21
+
22
+ it "throws :invalid if value is a non-numeric varchar." do
23
+ r = catch(:invalid) {
24
+ CACHE[:numeric_class].create :age=>'twenty-two'
25
+ }
26
+ r.error[:msg].should.match /age must be numeric/i
27
+ end
28
+
29
+ it "allows nil" do
30
+ Class.new {
31
+ include Datoki
32
+ field(:id) { primary_key }
33
+ field(:age) { smallint nil, 1, 99 }
34
+ }.create(:age=>nil).
35
+ clean[:age].should == nil
36
+ end
37
+
38
+ it "allows nil in an array" do
39
+ Class.new {
40
+ include Datoki
41
+ field(:id) { primary_key }
42
+ field(:age) { smallint [nil, 1,2,3,4] }
43
+ }.create(:age=>nil).
44
+ clean[:age].should == nil
45
+ end
46
+
47
+ it "allows to specify an Array of possible values" do
48
+ Class.new {
49
+ include Datoki
50
+ field(:id) { primary_key }
51
+ field(:age) { smallint [1,2,3,4] }
52
+ }.create(:age=>2).
53
+ clean[:age].should == 2
54
+ end
55
+
56
+ it "fails if value is not in Array of possible values" do
57
+ catch(:invalid) {
58
+ Class.new {
59
+ include Datoki
60
+ field(:id) { primary_key }
61
+ field(:num) { smallint [1,2,3,4] }
62
+ }.create :num=>0
63
+ }.error[:msg].should.match /Num can only be: 1, 2, 3, 4/
64
+ end
65
+
66
+ end # === describe Numeric
@@ -0,0 +1,28 @@
1
+
2
+ describe 'Datoki.db number' do
3
+
4
+ before {
5
+ CACHE[:datoki_db_number] ||= begin
6
+ reset_db <<-EOF
7
+ CREATE TABLE "datoki_test" (
8
+ id serial NOT NULL PRIMARY KEY,
9
+ parent_id smallint NOT NULL,
10
+ title varchar(123) NOT NULL,
11
+ body text
12
+ );
13
+ EOF
14
+ end
15
+ }
16
+
17
+ it "does not set :min = 1" do
18
+ Class.new {
19
+ include Datoki
20
+ table "datoki_test"
21
+ field(:parent_id) { smallint }
22
+ }.
23
+ fields[:parent_id][:min].should == nil
24
+ end
25
+
26
+ end # === Datoki.db number
27
+
28
+
@@ -0,0 +1,75 @@
1
+
2
+ describe :href do
3
+
4
+ before {
5
+ CACHE[:datoki_db_href] ||= begin
6
+ reset_db <<-EOF
7
+ CREATE TABLE "datoki_test" (
8
+ id serial NOT NULL PRIMARY KEY,
9
+ homepage varchar(255) NOT NULL
10
+ );
11
+ EOF
12
+ end
13
+
14
+ @klass = Class.new {
15
+ include Datoki
16
+ table :datoki_test
17
+ field(:id) { primary_key }
18
+ field(:homepage) { href }
19
+ }
20
+ }
21
+
22
+ it "sets :type to :varchar" do
23
+ @klass.fields[:homepage][:type].should == :varchar
24
+ end
25
+
26
+ it "sets :max to 255" do
27
+ @klass.fields[:homepage][:max].should == 255
28
+ end
29
+
30
+ it "sets :min to 1" do
31
+ @klass.fields[:homepage][:min].should == 1
32
+ end
33
+
34
+ it "sets :html_escape to :href" do
35
+ @klass.fields[:homepage][:html_escape].should == :href
36
+ end
37
+
38
+ it "accepts a :min and :max" do
39
+ CACHE[:datoki_db_href] = nil
40
+ reset_db <<-EOF
41
+ CREATE TABLE "datoki_test" (
42
+ id serial NOT NULL PRIMARY KEY,
43
+ homepage varchar(123) NOT NULL
44
+ );
45
+ EOF
46
+ k = Class.new {
47
+ include Datoki
48
+ table :datoki_test
49
+ field(:id) { primary_key }
50
+ field(:homepage) { href 5, 123 }
51
+ }
52
+ k.fields[:homepage][:min].should == 5
53
+ k.fields[:homepage][:max].should == 123
54
+ end
55
+
56
+ it "sets :min = 1 when null is allowed." do
57
+ CACHE[:datoki_db_href] = nil
58
+ reset_db <<-EOF
59
+ CREATE TABLE "datoki_test" (
60
+ id serial NOT NULL PRIMARY KEY,
61
+ homepage varchar(222)
62
+ );
63
+ EOF
64
+ k = Class.new {
65
+ include Datoki
66
+ table :datoki_test
67
+ field(:id) { primary_key }
68
+ field(:homepage) { href nil }
69
+ }
70
+ k.fields[:homepage][:min].should == 1
71
+ k.fields[:homepage][:max].should == 222
72
+ end
73
+
74
+ end # === describe :href
75
+
@@ -0,0 +1,44 @@
1
+
2
+
3
+
4
+ describe :html_escape do
5
+
6
+ before {
7
+ CACHE[:datoki_db_escape] ||= begin
8
+ reset_db <<-EOF
9
+ CREATE TABLE "datoki_test" (
10
+ id serial NOT NULL PRIMARY KEY,
11
+ parent_id smallint NOT NULL,
12
+ title varchar(123) NOT NULL,
13
+ url varchar(255) NOT NULL,
14
+ body text NOT NULL
15
+ );
16
+ EOF
17
+ end
18
+
19
+ @klass = Class.new {
20
+ include Datoki
21
+ table :datoki_test
22
+ field(:id) { primary_key }
23
+ field(:parent_id) { smallint }
24
+ field(:title) { varchar 1, 123 }
25
+ field(:url) { href }
26
+ field(:body) { text 1, 244 }
27
+ }
28
+ }
29
+
30
+ it "returns a hash of all defined fields" do
31
+ @klass.html_escape.should == {
32
+ :id => :number,
33
+ :parent_id => :number,
34
+ :title => :string,
35
+ :url => :href,
36
+ :body => :string
37
+ }
38
+ end
39
+
40
+ it "sets :href for urls" do
41
+ @klass.html_escape[:url].should == :href
42
+ end
43
+
44
+ end # === describe :html_escape
@@ -0,0 +1,14 @@
1
+
2
+
3
+ describe 'No type' do
4
+
5
+ it "requires type to be specified" do
6
+ should.raise(RuntimeError) {
7
+ Class.new {
8
+ include Datoki
9
+ field(:title) { }
10
+ }
11
+ }.message.should.match /Type not specified/
12
+ end
13
+
14
+ end # === describe 'No type' ========================================
@@ -0,0 +1,38 @@
1
+
2
+ describe "Datoki.db Schema_Conflict" do
3
+
4
+ before {
5
+ CACHE[:schema_conflict] ||= begin
6
+ reset_db <<-EOF
7
+ CREATE TABLE "datoki_test" (
8
+ id serial NOT NULL PRIMARY KEY,
9
+ title varchar(123),
10
+ body varchar(255) NOT NULL,
11
+ created_at timestamp with time zone NOT NULL DEFAULT timezone('UTC'::text, now())
12
+ );
13
+ EOF
14
+ end
15
+ }
16
+
17
+ it "raises Schema_Conflict when specified to allow nil, but db doesn not" do
18
+ should.raise(Datoki::Schema_Conflict) {
19
+ Class.new {
20
+ include Datoki
21
+ table :datoki_test
22
+ field(:body) { varchar nil, 1, 255 }
23
+ }
24
+ }.message.should.match /:allow_null: false != true/i
25
+ end
26
+
27
+ it "raises Schema_Conflict when there is a :max_length conflict" do
28
+ should.raise(Datoki::Schema_Conflict) {
29
+ Class.new {
30
+ include Datoki
31
+ table :datoki_test
32
+ field(:title) { varchar nil, 1, 200 }
33
+ }
34
+ }.message.should.match /:max: 123 != 200/i
35
+ end
36
+
37
+ end # === describe Datoki.db
38
+
@@ -0,0 +1,98 @@
1
+
2
+ describe :varchar do # ================================================
3
+
4
+ it "requires field by default during :create" do
5
+ should.raise(ArgumentError) {
6
+ Class.new {
7
+ include Datoki
8
+ field(:title) { varchar }
9
+ }.create({})
10
+ }.message.should.match /:title is not set/
11
+ end
12
+
13
+ it "raises RuntimeError if allow :null and :min = 0" do
14
+ should.raise(RuntimeError) {
15
+ Class.new {
16
+ include Datoki
17
+ field(:name) { varchar nil, 0, 50 }
18
+ }
19
+ }.message.should.match /varchar can't be both: allow :null && :min = 0/
20
+ end
21
+
22
+ it "fails when varchar is less than min: varchar x, y" do
23
+ catch(:invalid) {
24
+ Class.new {
25
+ include Datoki
26
+ field(:title) { varchar 3, 255 }
27
+ }.create :title => '1'
28
+ }.error[:msg].should.match /Title must be between 3 and 255 characters/i
29
+ end
30
+
31
+ it "fails when varchar is longer than max" do
32
+ catch(:invalid) {
33
+ Class.new {
34
+ include Datoki
35
+ field(:title) { varchar 0, 5 }
36
+ }.create :title => '123456'
37
+ }.error[:msg].should.match /Title must be between 0 and 5 characters/
38
+ end
39
+
40
+ it "fails when varchar does not match pattern: match /../" do
41
+ catch(:invalid) {
42
+ Class.new {
43
+ include Datoki
44
+ field :title do
45
+ varchar
46
+ match /\A[a-zA-Z0-9]+\z/i, "Title must be only: alphanumeric"
47
+ end
48
+ }.create :title => '$! title'
49
+ }.error[:msg].should.match /Title must be only: alphanumeric/
50
+ end
51
+
52
+ it "allows varchar to be nil" do
53
+ r = Class.new {
54
+ include Datoki
55
+ field(:title) {
56
+ varchar nil, 1, 123
57
+ }
58
+ }.create({})
59
+ r.clean.has_key?(:title).should == false
60
+ end
61
+
62
+ it "sets field to return value of :set_to" do
63
+ Class.new {
64
+ include Datoki
65
+ field(:title) {
66
+ varchar
67
+ set_to :custom_error
68
+ def custom_error
69
+ 'Custom title'
70
+ end
71
+ }
72
+ }.
73
+ create(:title => 'My Title').
74
+ clean[:title].should.match /Custom title/
75
+ end
76
+
77
+ it "strips varchars by default" do
78
+ Class.new {
79
+ include Datoki
80
+ field(:title) { varchar }
81
+ }.
82
+ create(:title => ' my title ').
83
+ clean[:title].should == 'my title'
84
+ end
85
+
86
+ it "can prevent varchar from being stripped" do
87
+ Class.new {
88
+ include Datoki
89
+ field(:title) {
90
+ varchar
91
+ disable :strip
92
+ }
93
+ }.
94
+ create(:title => ' my title ').
95
+ clean[:title].should == ' my title '
96
+ end
97
+
98
+ end # === describe varchar ===
@@ -0,0 +1,33 @@
1
+
2
+ describe "Datoki.db :varchar" do
3
+
4
+ before {
5
+ CACHE[:datoki_db_varchar] ||= reset_db <<-EOF
6
+ CREATE TABLE "datoki_test" (
7
+ id serial NOT NULL PRIMARY KEY,
8
+ title varchar(123) NOT NULL,
9
+ body text
10
+ );
11
+ EOF
12
+ @klass = Class.new {
13
+ include Datoki
14
+ table "datoki_test"
15
+ field(:id) { primary_key }
16
+ field(:title) { varchar 1, 123 }
17
+ field(:body) { text nil, 1, 3000 }
18
+ }
19
+ }
20
+
21
+ it "imports max length" do
22
+ @klass.fields[:title][:max].should == 123
23
+ end
24
+
25
+ it "sets :min = 1 (by default, during import, if NOT NULL)" do
26
+ @klass.fields[:title][:min].should == 1
27
+ end
28
+
29
+ it "sets :min = 1 (by default, during import, if :allow_null = true)" do
30
+ @klass.fields[:body][:min].should == 1
31
+ end
32
+
33
+ end # === describe Datoki.db :varchar
@@ -0,0 +1,58 @@
1
+
2
+ describe :clean do
3
+
4
+ it "adds field to @clean" do
5
+ c = Class.new {
6
+ include Datoki
7
+
8
+ field(:nick_name) { varchar 1,50 }
9
+ on(:happy?) { clean :nick_name }
10
+
11
+ def happy?
12
+ true
13
+ end
14
+ }
15
+
16
+ c.create(:state=>:happy, :nick_name=>'Bob').
17
+ clean[:nick_name].should == 'Bob'
18
+ end # === it adds field to @clean
19
+
20
+ it "skips cleaning if field is not defined" do
21
+ c = Class.new {
22
+ include Datoki
23
+
24
+ field(:nick_name) { varchar 3, 255 }
25
+ field(:age) { smallint; allow :null }
26
+
27
+ on :happy? do
28
+ clean :nick_name, :age
29
+ end
30
+
31
+ def happy?
32
+ true
33
+ end
34
+ }
35
+ c.create(:nick_name=>'Wiley').
36
+ clean.should == {:nick_name=>'Wiley'}
37
+ end # === it skips cleaning if field is not defined
38
+
39
+ it "fails w/ArgumentError if field is undefined, but required: :field!" do
40
+ c = Class.new {
41
+ include Datoki
42
+
43
+ field(:name) { varchar }
44
+ on :happy? do
45
+ clean :name!
46
+ end
47
+
48
+ def happy?
49
+ true
50
+ end
51
+ }
52
+
53
+ should.raise(ArgumentError) {
54
+ c.new(:happy=>true, :nick=>'Bob')
55
+ }.message.should.match /:name is not set/
56
+ end # === it fails w/ArgumentError if underfined
57
+
58
+ end # === describe :clean
data/specs/0020-on.rb ADDED
@@ -0,0 +1,64 @@
1
+
2
+ describe :on do
3
+
4
+ it "executes proc if condition is true" do
5
+ c = Class.new {
6
+ include Datoki
7
+
8
+ on :happy? do
9
+ @result = :happy
10
+ end
11
+
12
+ on :sad? do
13
+ @result= :happy
14
+ end
15
+
16
+ attr_reader :result
17
+
18
+ def happy?
19
+ @raw[:state] == :happy
20
+ end
21
+
22
+ def sad?
23
+ @raw[:state] == :sad
24
+ end
25
+ }
26
+
27
+ c.create(:state => :happy).
28
+ result.should == :happy
29
+ end # === it executes proc if condition is true
30
+
31
+ it "executes nested :on if condition matches" do
32
+ c = Class.new {
33
+ include Datoki
34
+
35
+ RESULT = []
36
+
37
+ attr_reader :result
38
+
39
+ on :true? do
40
+ on :filled? do
41
+ @result ||= []
42
+ @result << :found
43
+ end
44
+ on :false? do
45
+ fail
46
+ end
47
+ end
48
+
49
+ def false?
50
+ false
51
+ end
52
+
53
+ def filled?
54
+ true
55
+ end
56
+
57
+ def true?
58
+ true
59
+ end
60
+ }
61
+ c.create({}).result.should == [:found]
62
+ end # === it executes nested :on if condition matches
63
+
64
+ end # === describe :on
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datoki
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - da99
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-22 00:00:00.000000000 Z
11
+ date: 2015-03-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -108,7 +108,18 @@ files:
108
108
  - VERSION
109
109
  - datoki.gemspec
110
110
  - lib/datoki.rb
111
- - specs/datoki.rb
111
+ - specs/0010-Datoki.db.new.rb
112
+ - specs/0010-Datoki.db.rb
113
+ - specs/0010-Numeric.rb
114
+ - specs/0010-Numeric_db.rb
115
+ - specs/0010-href.rb
116
+ - specs/0010-html_escape.rb
117
+ - specs/0010-no_type.rb
118
+ - specs/0010-schema_conflict.rb
119
+ - specs/0010-varchar.rb
120
+ - specs/0010-varchar_db.rb
121
+ - specs/0020-clean.rb
122
+ - specs/0020-on.rb
112
123
  - specs/lib/helpers.rb
113
124
  homepage: https://github.com/da99/datoki
114
125
  licenses: