rails-properties 3.4.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ describe RailsProperties::PropertyObject do
4
+ let(:user) { User.create! :name => 'Mr. Pink' }
5
+
6
+ if RailsProperties.can_protect_attributes?
7
+ let(:new_property_object) { user.property_objects.build({ :var => 'dashboard'}, :without_protection => true) }
8
+ let(:saved_property_object) { user.property_objects.create!({ :var => 'dashboard', :value => { 'theme' => 'pink', 'filter' => false}}, :without_protection => true) }
9
+ else
10
+ let(:new_property_object) { user.property_objects.build({ :var => 'dashboard'}) }
11
+ let(:saved_property_object) { user.property_objects.create!({ :var => 'dashboard', :value => { 'theme' => 'pink', 'filter' => false}}) }
12
+ end
13
+
14
+ describe "serialization" do
15
+ it "should have a hash default" do
16
+ expect(RailsProperties::PropertyObject.new.value).to eq({})
17
+ end
18
+ end
19
+
20
+ describe "Getter and Setter" do
21
+ context "on unsaved properties" do
22
+ it "should respond to setters" do
23
+ expect(new_property_object).to respond_to(:foo=)
24
+ expect(new_property_object).to respond_to(:bar=)
25
+ end
26
+
27
+ it "should not respond to some getters" do
28
+ expect { new_property_object.foo! }.to raise_error(NoMethodError)
29
+ expect { new_property_object.foo? }.to raise_error(NoMethodError)
30
+ end
31
+
32
+ it "should not respond if a block is given" do
33
+ expect {
34
+ new_property_object.foo do
35
+ end
36
+ }.to raise_error(NoMethodError)
37
+ end
38
+
39
+ it "should not respond if params are given" do
40
+ expect { new_property_object.foo(42) }.to raise_error(NoMethodError)
41
+ expect { new_property_object.foo(42,43) }.to raise_error(NoMethodError)
42
+ end
43
+
44
+ it "should return nil for unknown attribute" do
45
+ expect(new_property_object.foo).to eq(nil)
46
+ expect(new_property_object.bar).to eq(nil)
47
+ end
48
+
49
+ it "should return defaults" do
50
+ expect(new_property_object.theme).to eq('blue')
51
+ expect(new_property_object.view).to eq('monthly')
52
+ expect(new_property_object.filter).to eq(true)
53
+ end
54
+
55
+ it "should return defaults when using `try`" do
56
+ expect(new_property_object.try(:theme)).to eq('blue')
57
+ expect(new_property_object.try(:view)).to eq('monthly')
58
+ expect(new_property_object.try(:filter)).to eq(true)
59
+ end
60
+
61
+ it "should store different objects to value hash" do
62
+ new_property_object.integer = 42
63
+ new_property_object.float = 1.234
64
+ new_property_object.string = 'Hello, World!'
65
+ new_property_object.array = [ 1,2,3 ]
66
+ new_property_object.symbol = :foo
67
+
68
+ expect(new_property_object.value).to eq('integer' => 42,
69
+ 'float' => 1.234,
70
+ 'string' => 'Hello, World!',
71
+ 'array' => [ 1,2,3 ],
72
+ 'symbol' => :foo)
73
+ end
74
+
75
+ it "should set and return attributes" do
76
+ new_property_object.theme = 'pink'
77
+ new_property_object.foo = 42
78
+ new_property_object.bar = 'hello'
79
+
80
+ expect(new_property_object.theme).to eq('pink')
81
+ expect(new_property_object.foo).to eq(42)
82
+ expect(new_property_object.bar).to eq('hello')
83
+ end
84
+
85
+ it "should set dirty trackers on change" do
86
+ new_property_object.theme = 'pink'
87
+ expect(new_property_object).to be_value_changed
88
+ expect(new_property_object).to be_changed
89
+ end
90
+ end
91
+
92
+ context "on saved properties" do
93
+ it "should not set dirty trackers on property same value" do
94
+ saved_property_object.theme = 'pink'
95
+ expect(saved_property_object).not_to be_value_changed
96
+ expect(saved_property_object).not_to be_changed
97
+ end
98
+
99
+ it "should delete key on assigning nil" do
100
+ saved_property_object.theme = nil
101
+ expect(saved_property_object.value).to eq({ 'filter' => false })
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "update_attributes" do
107
+ it 'should save' do
108
+ expect(new_property_object.update_attributes(:foo => 42, :bar => 'string')).to be_truthy
109
+ new_property_object.reload
110
+
111
+ expect(new_property_object.foo).to eq(42)
112
+ expect(new_property_object.bar).to eq('string')
113
+ expect(new_property_object).not_to be_new_record
114
+ expect(new_property_object.id).not_to be_zero
115
+ end
116
+
117
+ it 'should not save blank hash' do
118
+ expect(new_property_object.update_attributes({})).to be_truthy
119
+ end
120
+
121
+ if RailsProperties.can_protect_attributes?
122
+ it 'should not allow changing protected attributes' do
123
+ new_property_object.update_attributes!(:var => 'calendar', :foo => 42)
124
+
125
+ expect(new_property_object.var).to eq('dashboard')
126
+ expect(new_property_object.foo).to eq(42)
127
+ end
128
+ end
129
+ end
130
+
131
+ describe "save" do
132
+ it "should save" do
133
+ new_property_object.foo = 42
134
+ new_property_object.bar = 'string'
135
+ expect(new_property_object.save).to be_truthy
136
+ new_property_object.reload
137
+
138
+ expect(new_property_object.foo).to eq(42)
139
+ expect(new_property_object.bar).to eq('string')
140
+ expect(new_property_object).not_to be_new_record
141
+ expect(new_property_object.id).not_to be_zero
142
+ end
143
+ end
144
+
145
+ describe "validation" do
146
+ it "should not validate for unknown var" do
147
+ new_property_object.var = "unknown-var"
148
+
149
+ expect(new_property_object).not_to be_valid
150
+ expect(new_property_object.errors[:var]).to be_present
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Queries performed' do
4
+ context 'New record' do
5
+ let!(:user) { User.new :name => 'Mr. Pink' }
6
+
7
+ it 'should be saved by one SQL query' do
8
+ expect {
9
+ user.save!
10
+ }.to perform_queries(1)
11
+ end
12
+
13
+ it 'should be saved with properties for one key by two SQL queries' do
14
+ expect {
15
+ user.properties(:dashboard).foo = 42
16
+ user.properties(:dashboard).bar = 'string'
17
+ user.save!
18
+ }.to perform_queries(2)
19
+ end
20
+
21
+ it 'should be saved with properties for two keys by three SQL queries' do
22
+ expect {
23
+ user.properties(:dashboard).foo = 42
24
+ user.properties(:dashboard).bar = 'string'
25
+ user.properties(:calendar).bar = 'string'
26
+ user.save!
27
+ }.to perform_queries(3)
28
+ end
29
+ end
30
+
31
+ context 'Existing record without properties' do
32
+ let!(:user) { User.create! :name => 'Mr. Pink' }
33
+
34
+ it 'should be saved without SQL queries' do
35
+ expect {
36
+ user.save!
37
+ }.to perform_queries(0)
38
+ end
39
+
40
+ it 'should be saved with properties for one key by two SQL queries' do
41
+ expect {
42
+ user.properties(:dashboard).foo = 42
43
+ user.properties(:dashboard).bar = 'string'
44
+ user.save!
45
+ }.to perform_queries(2)
46
+ end
47
+
48
+ it 'should be saved with properties for two keys by three SQL queries' do
49
+ expect {
50
+ user.properties(:dashboard).foo = 42
51
+ user.properties(:dashboard).bar = 'string'
52
+ user.properties(:calendar).bar = 'string'
53
+ user.save!
54
+ }.to perform_queries(3)
55
+ end
56
+ end
57
+
58
+ context 'Existing record with properties' do
59
+ let!(:user) do
60
+ User.create! :name => 'Mr. Pink' do |user|
61
+ user.properties(:dashboard).theme = 'pink'
62
+ user.properties(:calendar).scope = 'all'
63
+ end
64
+ end
65
+
66
+ it 'should be saved without SQL queries' do
67
+ expect {
68
+ user.save!
69
+ }.to perform_queries(0)
70
+ end
71
+
72
+ it 'should be saved with properties for one key by one SQL queries' do
73
+ expect {
74
+ user.properties(:dashboard).foo = 42
75
+ user.properties(:dashboard).bar = 'string'
76
+ user.save!
77
+ }.to perform_queries(1)
78
+ end
79
+
80
+ it 'should be saved with properties for two keys by two SQL queries' do
81
+ expect {
82
+ user.properties(:dashboard).foo = 42
83
+ user.properties(:dashboard).bar = 'string'
84
+ user.properties(:calendar).bar = 'string'
85
+ user.save!
86
+ }.to perform_queries(2)
87
+ end
88
+
89
+ it 'should be destroyed by two SQL queries' do
90
+ expect {
91
+ user.destroy
92
+ }.to perform_queries(2)
93
+ end
94
+
95
+ it "should update properties by one SQL query" do
96
+ expect {
97
+ user.properties(:dashboard).update_attributes! :foo => 'bar'
98
+ }.to perform_queries(1)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'scopes' do
4
+ let!(:user1) { User.create! :name => 'Mr. White' do |user| user.properties(:dashboard).theme = 'white' end }
5
+ let!(:user2) { User.create! :name => 'Mr. Blue' }
6
+
7
+ it "should find objects with existing properties" do
8
+ expect(User.with_properties).to eq([user1])
9
+ end
10
+
11
+ it "should find objects with properties for key" do
12
+ expect(User.with_properties_for(:dashboard)).to eq([user1])
13
+ expect(User.with_properties_for(:foo)).to eq([])
14
+ end
15
+
16
+ it "should records without properties" do
17
+ expect(User.without_properties).to eq([user2])
18
+ end
19
+
20
+ it "should records without properties for key" do
21
+ expect(User.without_properties_for(:foo)).to eq([user1, user2])
22
+ expect(User.without_properties_for(:dashboard)).to eq([user2])
23
+ end
24
+
25
+ it "should require symbol as key" do
26
+ [ nil, "string", 42 ].each do |invalid_key|
27
+ expect { User.without_properties_for(invalid_key) }.to raise_error(ArgumentError)
28
+ expect { User.with_properties_for(invalid_key) }.to raise_error(ArgumentError)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Serialization" do
4
+ let!(:user) do
5
+ User.create! :name => 'Mr. White' do |user|
6
+ user.properties(:dashboard).theme = 'white'
7
+ user.properties(:calendar).scope = 'all'
8
+ end
9
+ end
10
+
11
+ describe 'created properties' do
12
+ it 'should be serialized' do
13
+ user.reload
14
+
15
+ dashboard_properties = user.property_objects.where(:var => 'dashboard').first
16
+ calendar_properties = user.property_objects.where(:var => 'calendar').first
17
+
18
+ expect(dashboard_properties.var).to eq('dashboard')
19
+ expect(dashboard_properties.value).to eq({'theme' => 'white'})
20
+
21
+ expect(calendar_properties.var).to eq('calendar')
22
+ expect(calendar_properties.value).to eq({'scope' => 'all'})
23
+ end
24
+ end
25
+
26
+ describe 'updated properties' do
27
+ it 'should be serialized' do
28
+ user.properties(:dashboard).update_attributes! :smart => true
29
+
30
+ dashboard_properties = user.property_objects.where(:var => 'dashboard').first
31
+ calendar_properties = user.property_objects.where(:var => 'calendar').first
32
+
33
+ expect(dashboard_properties.var).to eq('dashboard')
34
+ expect(dashboard_properties.value).to eq({'theme' => 'white', 'smart' => true})
35
+
36
+ expect(calendar_properties.var).to eq('calendar')
37
+ expect(calendar_properties.value).to eq({'scope' => 'all'})
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,111 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ])
8
+ SimpleCov.start do
9
+ add_filter '/spec/'
10
+ end
11
+
12
+ # Requires supporting ruby files with custom matchers and macros, etc,
13
+ # in spec/support/ and its subdirectories.
14
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
15
+
16
+ # This file was generated by the `rspec --init` command. Conventionally, all
17
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
18
+ # Require this file using `require "spec_helper"` to ensure that it is only
19
+ # loaded once.
20
+ #
21
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
22
+ RSpec.configure do |config|
23
+ # Run specs in random order to surface order dependencies. If you find an
24
+ # order dependency and want to debug it, you can fix the order by providing
25
+ # the seed, which is printed after each run.
26
+ # --seed 1234
27
+ # config.order = 'random'
28
+
29
+ config.before(:each) do
30
+ clear_db
31
+ end
32
+
33
+ config.after :suite do
34
+ RailsPropertiesMigration.migrate(:down)
35
+ end
36
+ end
37
+
38
+ require 'active_record'
39
+ require 'protected_attributes' if ENV['PROTECTED_ATTRIBUTES'] == 'true'
40
+ require 'rails-properties'
41
+
42
+ if I18n.respond_to?(:enforce_available_locales=)
43
+ I18n.enforce_available_locales = false
44
+ end
45
+
46
+ class User < ActiveRecord::Base
47
+ has_properties do |s|
48
+ s.key :dashboard, :defaults => { :theme => 'blue', :view => 'monthly', :filter => true }
49
+ s.key :calendar, :defaults => { :scope => 'company'}
50
+ end
51
+ end
52
+
53
+ class GuestUser < User
54
+ has_properties do |s|
55
+ s.key :dashboard, :defaults => { :theme => 'red', :view => 'monthly', :filter => true }
56
+ end
57
+ end
58
+
59
+ class Account < ActiveRecord::Base
60
+ has_properties :portal
61
+ end
62
+
63
+ class Project < ActiveRecord::Base
64
+ has_properties :info, :class_name => 'ProjectPropertyObject'
65
+ end
66
+
67
+ class ProjectPropertyObject < RailsProperties::PropertyObject
68
+ validate do
69
+ unless self.owner_name.present? && self.owner_name.is_a?(String)
70
+ errors.add(:base, "Owner name is missing")
71
+ end
72
+ end
73
+ end
74
+
75
+ def setup_db
76
+ ActiveRecord::Base.configurations = YAML.load_file(File.dirname(__FILE__) + '/database.yml')
77
+ ActiveRecord::Base.establish_connection(:sqlite)
78
+ ActiveRecord::Migration.verbose = false
79
+
80
+ print "Testing with ActiveRecord #{ActiveRecord::VERSION::STRING}"
81
+ if ActiveRecord::VERSION::MAJOR == 4
82
+ print " #{defined?(ProtectedAttributes) ? 'with' : 'without'} gem `protected_attributes`"
83
+ end
84
+ puts
85
+
86
+ require File.expand_path('../../lib/generators/rails_properties/migration/templates/migration.rb', __FILE__)
87
+ RailsPropertiesMigration.migrate(:up)
88
+
89
+ ActiveRecord::Schema.define(:version => 1) do
90
+ create_table :users do |t|
91
+ t.string :type
92
+ t.string :name
93
+ end
94
+
95
+ create_table :accounts do |t|
96
+ t.string :subdomain
97
+ end
98
+
99
+ create_table :projects do |t|
100
+ t.string :name
101
+ end
102
+ end
103
+ end
104
+
105
+ def clear_db
106
+ User.delete_all
107
+ Account.delete_all
108
+ RailsProperties::PropertyObject.delete_all
109
+ end
110
+
111
+ setup_db
@@ -0,0 +1,22 @@
1
+ RSpec::Matchers.define :perform_queries do |expected|
2
+ match do |block|
3
+ query_count(&block) == expected
4
+ end
5
+
6
+ failure_message do |actual|
7
+ "Expected to run #{expected} queries, got #{@counter.query_count}"
8
+ end
9
+
10
+ def query_count(&block)
11
+ @counter = ActiveRecord::QueryCounter.new
12
+ ActiveSupport::Notifications.subscribe('sql.active_record', @counter.to_proc)
13
+ yield
14
+ ActiveSupport::Notifications.unsubscribe(@counter.to_proc)
15
+
16
+ @counter.query_count
17
+ end
18
+
19
+ def supports_block_expectations?
20
+ true
21
+ end
22
+ end