preferable 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Preferable::Coder do
4
+
5
+ let :user do
6
+ User.create! do |u|
7
+ u.preferences[:newsletter] = '1'
8
+ end.reload
9
+ end
10
+
11
+ let :legacy do
12
+ User.create!
13
+ end
14
+
15
+ it 'should not dump blank values' do
16
+ subject.dump(nil).should be_nil
17
+ subject.dump("ANY").should be_nil
18
+ subject.dump({}).should be_nil
19
+ end
20
+
21
+ it 'should dump hashes values' do
22
+ subject.dump(user.preferences).should == %({"newsletter":true})
23
+ end
24
+
25
+ it 'should load blank values' do
26
+ subject.load(nil).should == {}
27
+ subject.load(" ").should == {}
28
+ end
29
+
30
+ it 'should load hashes as they are' do
31
+ subject.load({"newsletter" => false}).should == {"newsletter" => false}
32
+ end
33
+
34
+ it 'should not fail over encoding errors' do
35
+ subject.load("SOMETHING WRONG!?").should == {}
36
+ end
37
+
38
+ it 'should raise errors if something other than a hash was loaded' do
39
+ lambda { subject.load("[1, 2]") }.should raise_error(ActiveRecord::SerializationTypeMismatch)
40
+ end
41
+
42
+ it 'should load values' do
43
+ subject.load(subject.dump(user.preferences)).should == {"newsletter" => true}
44
+ end
45
+
46
+ it "should load legacy settings" do
47
+ legacy.update_column :preferences, "---\n:color: \"222222\"\n_: \"::User\"\n"
48
+ legacy.reload.preferences.should == { "color" => "222222" }
49
+
50
+ legacy.update_column :preferences, "--- !map:Preferable::Set \n:color: \"222222\"\n_: \"::User\"\n"
51
+ legacy.reload.preferences.should == { "color" => "222222" }
52
+
53
+ legacy.update_column :preferences, "--- !ruby/object:Preferable::Set \n:color: \"222222\"\n_: \"::User\"\n"
54
+ legacy.reload.preferences.should == { "color" => "222222" }
55
+ end
56
+
57
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe Preferable::Field do
4
+
5
+ def field(type, opts = {})
6
+ described_class.new :any, type, opts
7
+ end
8
+
9
+ def integer(opts = {})
10
+ field :integer, opts
11
+ end
12
+
13
+ subject do
14
+ described_class.new "color", "string", :if => lambda {|v| v =~ /^[A-F0-9]{6}$/ }, :default => '444444'
15
+ end
16
+
17
+ it 'should have a name' do
18
+ subject.name.should == "color"
19
+ end
20
+
21
+ it 'should have a type' do
22
+ subject.type.should == :string
23
+ end
24
+
25
+ it 'should have a default' do
26
+ subject.default.should == '444444'
27
+ end
28
+
29
+ it 'should have options' do
30
+ subject.options.keys.should == [:if]
31
+ end
32
+
33
+ it 'should reject invalid types' do
34
+ lambda { described_class.new :any, :invalid }.should raise_error(ArgumentError)
35
+ end
36
+
37
+ it 'should check if values are assignable' do
38
+ even = lambda {|v| (v % 2).zero? }
39
+ is_2 = lambda {|v| v == 2 }
40
+
41
+ integer(:if => even).valid?(1).should be(false)
42
+ integer(:if => even).valid?(2).should be(true)
43
+ integer(:unless => even).valid?(1).should be(true)
44
+ integer(:unless => even).valid?(2).should be(false)
45
+ integer(:if => even, :unless => is_2).valid?(2).should be(false)
46
+ integer(:if => even, :unless => is_2).valid?(3).should be(false)
47
+ integer(:if => even, :unless => is_2).valid?(4).should be(true)
48
+ end
49
+
50
+ it 'should type-cast strings' do
51
+ field(:string).type_cast(nil).should == nil
52
+ field(:string).type_cast(1).should == '1'
53
+ end
54
+
55
+ it 'should type-cast ints' do
56
+ field(:integer).type_cast(nil).should == nil
57
+ field(:integer).type_cast('1').should == 1
58
+ field(:integer).type_cast(2.5).should == 2
59
+ field(:integer).type_cast("").should == 0
60
+ end
61
+
62
+ it 'should type-cast floats' do
63
+ field(:float).type_cast(nil).should == nil
64
+ field(:float).type_cast('1').should == 1.0
65
+ field(:float).type_cast(2.5).should == 2.5
66
+ field(:float).type_cast("").should == 0
67
+ end
68
+
69
+ it 'should type-cast booleans' do
70
+ field(:boolean).type_cast(nil).should == nil
71
+ field(:boolean).type_cast('1').should == true
72
+ field(:boolean).type_cast(0).should == false
73
+ field(:boolean).type_cast(true).should == true
74
+ end
75
+
76
+ it 'should type-cast dates' do
77
+ field(:date).type_cast('2011-01-01').should == Date.civil(2011, 1, 1)
78
+ field(:date).type_cast(Date.civil(2011, 11, 11)).should == Date.civil(2011, 11, 11)
79
+ field(:date).type_cast(Time.at(1234567890)).should == Date.civil(2009, 2, 13)
80
+ end
81
+
82
+ it 'should type-cast datetimes' do
83
+ field(:datetime).type_cast('2011-01-01 12:10').should == Time.zone.local(2011, 1, 1, 12, 10)
84
+ field(:datetime).type_cast(Time.at(1234567890)).should == Time.at(1234567890)
85
+ field(:datetime).type_cast(Time.at(1234567890)).zone.should == "UTC"
86
+ end
87
+
88
+ it 'should type-cast arrays' do
89
+ field(:array).type_cast('1').should == ['1']
90
+ field(:array, :cast => :integer).type_cast('1').should == [1]
91
+ field(:array, :cast => :integer).type_cast(['1', 2, 'B']).should == [1, 2, 0]
92
+ end
93
+
94
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe Preferable::Model do
4
+
5
+ subject do
6
+ Class.new(ActiveRecord::Base)
7
+ end
8
+
9
+ it 'should be includable' do
10
+ subject.send(:included_modules).should include(described_class)
11
+ end
12
+
13
+ it 'should store a preferable schema' do
14
+ User._preferable.keys.should =~ ["newsletter", "color"]
15
+ end
16
+
17
+ it 'should inherit preferable schema correctly' do
18
+ Admin._preferable.keys.should =~ ["newsletter", "color", "reminder"]
19
+ end
20
+
21
+ it 'should allow to define preferables' do
22
+ res = nil
23
+ subject._preferable.should be_nil
24
+ subject.preferable { res = self.class.name }
25
+ subject._preferable.should be_a(Preferable::Schema)
26
+ res.should == "Preferable::Schema"
27
+ end
28
+
29
+ describe "saving" do
30
+
31
+ it 'should save preferences with new records' do
32
+ user = User.new
33
+ user.preferences.should == {}
34
+ user.preferences[:color] = '222222'
35
+ user.tap(&:save!).tap(&:reload).preferences.should == { "color" => '222222' }
36
+ end
37
+
38
+ it 'should save preferences with existing records' do
39
+ user = User.create!(:name => 'Random', :preferences => { :color => '222222' }).reload
40
+ user.preferences.should == { "color" => '222222' }
41
+ user.preferences[:newsletter] = '1'
42
+ user.tap(&:save!).tap(&:reload).preferences.should == { "color" => '222222', "newsletter" => true }
43
+ end
44
+
45
+ end
46
+
47
+
48
+ describe "instances" do
49
+
50
+ subject do
51
+ User.new
52
+ end
53
+
54
+ it 'should have preferences' do
55
+ subject.preferences.should be_a(Preferable::Set)
56
+ end
57
+
58
+ it 'should allow assigning preferences' do
59
+ subject.preferences = { :color => '222222' }
60
+ subject.preferences.should be_a(Preferable::Set)
61
+ subject.preferences.should == { "color" => '222222' }
62
+ end
63
+
64
+ it 'should serialize preferences' do
65
+ subject.class.serialized_attributes.keys.should include('preferences')
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Preferable::Schema do
4
+
5
+ it { should be_a(Hash) }
6
+ it { should respond_to(:string) }
7
+ it { should respond_to(:integer) }
8
+ it { should respond_to(:float) }
9
+ it { should respond_to(:date) }
10
+ it { should respond_to(:datetime) }
11
+ it { should respond_to(:array) }
12
+ it { should respond_to(:boolean) }
13
+
14
+ it 'should build and store field' do
15
+ field = subject.field :color, :string
16
+ field.should be_a(Preferable::Field)
17
+ subject.should == { "color" => field }
18
+ end
19
+
20
+ it 'should provide shorthand method' do
21
+ subject.integer :client_id
22
+ subject.keys.should == ["client_id"]
23
+ subject.values.first.should be_a(Preferable::Field)
24
+ end
25
+
26
+ it 'should allow to specify options with shorthand method' do
27
+ subject.integer :client_id, :default => 1
28
+ subject.values.first.default.should == 1
29
+ end
30
+
31
+ it 'should allow specifying multiple fields with shorthand method' do
32
+ subject.integer :first, :second
33
+ subject.keys.should =~ ["first", "second"]
34
+ end
35
+
36
+ it 'should allow specifying multiple fields with options with shorthand method' do
37
+ subject.integer :first, :second, :default => 0
38
+ subject.keys.should =~ ["first", "second"]
39
+ subject.values.map(&:default).should == [0, 0]
40
+ end
41
+
42
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe Preferable::Set do
4
+
5
+ let :user do
6
+ User.new
7
+ end
8
+
9
+ let :admin do
10
+ Admin.new
11
+ end
12
+
13
+ subject do
14
+ user.preferences
15
+ end
16
+
17
+ it 'should wrap values' do
18
+ described_class.wrap(user, subject).should_not be(subject)
19
+ described_class.wrap(user, subject).should == subject
20
+ described_class.wrap(user, subject).owner.should be(user)
21
+
22
+ described_class.wrap(admin, subject).should be_instance_of(described_class)
23
+ described_class.wrap(admin, subject).owner.should be(admin)
24
+
25
+ described_class.wrap(user, {}).should be_instance_of(described_class)
26
+ described_class.wrap(user, {}).owner.should be(user)
27
+ end
28
+
29
+ it 'should reference the owner' do
30
+ subject.owner.should == user
31
+ end
32
+
33
+ it 'should be convertable to a simple hash' do
34
+ subject.to_hash.should be_instance_of(Hash)
35
+ end
36
+
37
+ describe "reading" do
38
+
39
+ it 'should return assignments or defaults' do
40
+ subject[:color].should == '444444'
41
+ subject[:color] = '222222'
42
+ subject[:color].should == '222222'
43
+ end
44
+
45
+ it 'should return nil for invalid keys' do
46
+ subject[:invalid].should be_nil
47
+ end
48
+
49
+ end
50
+
51
+ describe "writing" do
52
+
53
+ it 'should ignore invalid keys' do
54
+ subject[:invalid] = '1'
55
+ subject.should == {}
56
+ end
57
+
58
+ it 'should set values' do
59
+ subject[:color] = '222222'
60
+ subject.should == { "color" => '222222' }
61
+ end
62
+
63
+ it 'should notify record about changes' do
64
+ subject[:color] = '222222'
65
+ user.should be_changed
66
+ user.changed_attributes.should == { "preferences"=>{} }
67
+ end
68
+
69
+ it 'should type cast values' do
70
+ subject[:color] = 222222
71
+ subject.should == { "color" => '222222' }
72
+ end
73
+
74
+ it 'should unset key when defaults are assigned' do
75
+ subject[:color] = '222222'
76
+ subject.should == { "color" => '222222' }
77
+ subject[:color] = '444444'
78
+ subject.should == {}
79
+ end
80
+
81
+ it 'should unset key when nil is assigned' do
82
+ subject[:color] = '222222'
83
+ subject.should == { "color" => '222222' }
84
+ subject[:color] = nil
85
+ subject.should == {}
86
+ end
87
+
88
+ it 'should allow mass-update' do
89
+ subject.set 'color' => 222222, :newsletter => '1'
90
+ subject.should == { "color" => '222222', "newsletter" => true }
91
+ subject.set :color => nil, :newsletter => false
92
+ subject.should == {}
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,38 @@
1
+ ENV["RAILS_ENV"] ||= 'test'
2
+
3
+ $: << File.dirname(__FILE__) + '/../lib'
4
+ require 'rubygems'
5
+ require 'bundler/setup'
6
+ Bundler.require :default, :test
7
+
8
+ require 'active_support'
9
+ require 'active_record'
10
+ require 'rspec'
11
+ require 'preferable'
12
+
13
+ Time.zone = 'UTC'
14
+ ActiveRecord::Base.time_zone_aware_attributes = true
15
+ ActiveRecord::Base.default_timezone = :utc
16
+ ActiveRecord::Base.configurations["test"] = { 'adapter' => 'sqlite3', 'database' => ":memory:" }
17
+ ActiveRecord::Base.establish_connection(:test)
18
+ ActiveRecord::Base.connection.create_table :users do |t|
19
+ t.string :name
20
+ t.text :preferences
21
+ end
22
+
23
+ class User < ActiveRecord::Base
24
+
25
+ preferable do
26
+ string :color, :default => '444444'
27
+ boolean :newsletter, :default => false
28
+ end
29
+
30
+ end
31
+
32
+ class Admin < User
33
+
34
+ preferable do
35
+ boolean :reminder, :default => false
36
+ end
37
+
38
+ end
metadata CHANGED
@@ -1,62 +1,89 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: preferable
3
- version: !ruby/object:Gem::Version
4
- hash: 15
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 4
9
- - 0
10
- version: 0.4.0
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Dimitrij Denissenko
14
9
  - Evgeniy Dolzhenko
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2011-09-30 00:00:00 Z
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
13
+ date: 2012-01-24 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
22
16
  name: abstract
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &9804020 !ruby/object:Gem::Requirement
25
18
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
- version: "0"
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
33
23
  type: :runtime
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: activerecord
37
24
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *9804020
26
+ - !ruby/object:Gem::Dependency
27
+ name: activerecord
28
+ requirement: &9735560 !ruby/object:Gem::Requirement
39
29
  none: false
40
- requirements:
41
- - - ~>
42
- - !ruby/object:Gem::Version
43
- hash: 3
44
- segments:
45
- - 3
46
- - 1
47
- - 0
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
48
33
  version: 3.1.0
49
34
  type: :runtime
50
- version_requirements: *id002
35
+ prerelease: false
36
+ version_requirements: *9735560
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ requirement: &9731060 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *9731060
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: &9691900 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *9691900
59
+ - !ruby/object:Gem::Dependency
60
+ name: sqlite3-ruby
61
+ requirement: &9690880 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *9690880
70
+ - !ruby/object:Gem::Dependency
71
+ name: shoulda-matchers
72
+ requirement: &9690140 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *9690140
51
81
  description: Great for storing user preferences
52
82
  email: dimitrij@blacksquaremedia.com
53
83
  executables: []
54
-
55
84
  extensions: []
56
-
57
85
  extra_rdoc_files: []
58
-
59
- files:
86
+ files:
60
87
  - README.markdown
61
88
  - lib/preferable.rb
62
89
  - lib/preferable/field.rb
@@ -64,42 +91,40 @@ files:
64
91
  - lib/preferable/set.rb
65
92
  - lib/preferable/schema.rb
66
93
  - lib/preferable/coder.rb
94
+ - spec/preferable/field_spec.rb
95
+ - spec/preferable/coder_spec.rb
96
+ - spec/preferable/model_spec.rb
97
+ - spec/preferable/schema_spec.rb
98
+ - spec/preferable/set_spec.rb
99
+ - spec/spec_helper.rb
67
100
  homepage: https://github.com/bsm/preferable
68
101
  licenses: []
69
-
70
102
  post_install_message:
71
103
  rdoc_options: []
72
-
73
- require_paths:
104
+ require_paths:
74
105
  - lib
75
- required_ruby_version: !ruby/object:Gem::Requirement
106
+ required_ruby_version: !ruby/object:Gem::Requirement
76
107
  none: false
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- hash: 57
81
- segments:
82
- - 1
83
- - 8
84
- - 7
85
- version: 1.8.7
86
- required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: 1.9.2
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
113
  none: false
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- hash: 23
92
- segments:
93
- - 1
94
- - 3
95
- - 6
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
96
117
  version: 1.3.6
97
118
  requirements: []
98
-
99
119
  rubyforge_project:
100
- rubygems_version: 1.8.5
120
+ rubygems_version: 1.8.10
101
121
  signing_key:
102
122
  specification_version: 3
103
123
  summary: Simple preferences store for ActiveRecord
104
- test_files: []
105
-
124
+ test_files:
125
+ - spec/preferable/field_spec.rb
126
+ - spec/preferable/coder_spec.rb
127
+ - spec/preferable/model_spec.rb
128
+ - spec/preferable/schema_spec.rb
129
+ - spec/preferable/set_spec.rb
130
+ - spec/spec_helper.rb