datoki 1.0.1 → 2.0.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.
@@ -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: