rails-properties 3.4.3

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,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