act_with_bag 0.4.9.1 → 0.5.1
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.
- checksums.yaml +5 -5
- data/.travis.yml +7 -2
- data/.watchr +54 -0
- data/Gemfile +11 -4
- data/README.md +28 -8
- data/lib/act_with_bag/version.rb +1 -1
- data/lib/act_with_bag.rb +52 -45
- data/test/bag_boolean_test.rb +41 -0
- data/test/boolean_test.rb +10 -0
- data/test/string_test.rb +23 -0
- data/test/test_helper.rb +7 -1
- data/test/type_test.rb +41 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: da896ae57908fcd807d126a495328cfbdf346aec
|
4
|
+
data.tar.gz: 50c4ee5b105455155dcfedcb49c92803fe2b048f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9157f4c59e32b6f316243579bb629d0ec24ba76d8bfda696eb4797d1584ba2d63b4862eb158d18b5744ac001a08fccab6a99432079f63069bfaa39342642428
|
7
|
+
data.tar.gz: 85dd0f6fbe79d4d1989e46950d35f92f41428d46b93b6f9b4cb92927de6068555ce9a797a036cb24fe041db0c37c9d4f428fe56ef867e880fc52ff188b9b4973
|
data/.travis.yml
CHANGED
@@ -4,11 +4,16 @@ before_install: rm -f Gemfile.lock
|
|
4
4
|
|
5
5
|
rvm:
|
6
6
|
- 1.9.3
|
7
|
-
- 2.
|
7
|
+
- 2.2.3
|
8
8
|
|
9
9
|
env:
|
10
10
|
- "RAILS_VERSION=3.2.16"
|
11
|
-
- "RAILS_VERSION=4.
|
11
|
+
- "RAILS_VERSION=4.2.4"
|
12
|
+
|
13
|
+
matrix:
|
14
|
+
exclude:
|
15
|
+
- rvm: 2.2.3
|
16
|
+
env: "RAILS_VERSION=3.2.16"
|
12
17
|
|
13
18
|
notifications:
|
14
19
|
email: false
|
data/.watchr
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
HH = '#' * 22 unless defined?(HH)
|
2
|
+
H = '#' * 5 unless defined?(H)
|
3
|
+
|
4
|
+
def usage
|
5
|
+
puts <<-EOS
|
6
|
+
Ctrl-\\ or ctrl-4 Running all tests
|
7
|
+
Ctrl-C Exit
|
8
|
+
EOS
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(cmd)
|
12
|
+
puts "#{HH} #{Time.now} #{HH}"
|
13
|
+
puts "#{H} #{cmd}"
|
14
|
+
system "/usr/bin/time --format '#{HH} Elapsed time %E' #{cmd}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def run_it(type, file)
|
18
|
+
case type
|
19
|
+
when 'test'; run %Q{ruby -I"lib:test" -rubygems #{file}}
|
20
|
+
# when 'spec'; run %Q{spring rspec -X #{file}}
|
21
|
+
else; puts "#{H} unknown type: #{type}, file: #{file}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_all_tests
|
26
|
+
puts "\n#{HH} Running all tests #{HH}\n"
|
27
|
+
# %w{test spec}.each { |dir| run "spring rake #{dir} RAILS_ENV=test" if File.exists?(dir) }
|
28
|
+
# %w{test}.each { |dir| run "spring rake #{dir} RAILS_ENV=test" if File.exists?(dir) }
|
29
|
+
%w{test}.each { |dir| run "rake #{dir} RAILS_ENV=test" if File.exists?(dir) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def run_matching_files(base)
|
33
|
+
base = base.split('_').first
|
34
|
+
%w{test spec}.each { |type|
|
35
|
+
files = Dir["#{type}/**/*.rb"].select { |file| file =~ /#{base}_.*\.rb/ }
|
36
|
+
run_it type, files.join(' ') unless files.empty?
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
%w{test spec}.each { |type|
|
41
|
+
watch("#{type}/#{type}_helper\.rb") { run_all_tests }
|
42
|
+
watch("#{type}/.*/*_#{type}\.rb") { |match| run_it type, match[0] }
|
43
|
+
}
|
44
|
+
%w{rb erb haml slim}.each { |type|
|
45
|
+
watch("app/.*/.*\.#{type}") { |m|
|
46
|
+
run_matching_files("#{m[0].split('/').at(2).split('.').first}")
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
# Ctrl-\ or ctrl-4
|
51
|
+
Signal.trap('QUIT') { run_all_tests }
|
52
|
+
# Ctrl-C
|
53
|
+
Signal.trap('INT') { abort("Interrupted\n") }
|
54
|
+
usage
|
data/Gemfile
CHANGED
@@ -1,12 +1,19 @@
|
|
1
|
-
source "
|
1
|
+
source "https://rubygems.org"
|
2
2
|
gemspec
|
3
3
|
|
4
4
|
version = ENV["RAILS_VERSION"]
|
5
|
-
gem 'rails', version ? "~> #{version}" : ">= 4.0.
|
5
|
+
gem 'rails', version ? "~> #{version}" : ">= 4.0.2"
|
6
6
|
|
7
7
|
group :development, :test do
|
8
8
|
gem 'sqlite3'
|
9
|
-
gem '
|
10
|
-
gem 'spork'
|
9
|
+
gem 'observr'
|
10
|
+
# gem 'spork'
|
11
|
+
# gem 'spring'
|
12
|
+
end
|
13
|
+
|
14
|
+
group :test do
|
15
|
+
# gem 'watchr'
|
16
|
+
gem 'observr'
|
11
17
|
gem 'simplecov', require: false
|
12
18
|
end
|
19
|
+
|
data/README.md
CHANGED
@@ -15,12 +15,19 @@ Additional fields or removal of them are easy.
|
|
15
15
|
No migration is required for new fields.
|
16
16
|
|
17
17
|
Keep in mind that the collection is kept in a YAML bag, i.e.
|
18
|
-
SQL commands can't access the fields.
|
18
|
+
SQL commands can't access the bag fields.
|
19
19
|
|
20
|
-
Boolean and Date fields require explicit typing
|
21
|
-
|
20
|
+
Boolean and Date fields require explicit typing.
|
21
|
+
|
22
|
+
Fields without typing accept any values which YAML can handle
|
23
|
+
(e.g. @order.color = ['red', 'yellow']).
|
24
|
+
|
25
|
+
Types :integer, :float and :string
|
26
|
+
forces a conversion (.to_i, .to_f, .to_s) before storing the value,
|
27
|
+
a convenience similar to ActiveRecord handling due to migration definitions.
|
22
28
|
|
23
29
|
Technical background: getters and putters are injected into models.
|
30
|
+
|
24
31
|
If baggies of type :date are being used then
|
25
32
|
params must be corrected before an update_attributes.
|
26
33
|
Warning: :date fields are not well integrated; avoid them.
|
@@ -36,9 +43,19 @@ Example
|
|
36
43
|
In model:
|
37
44
|
|
38
45
|
class Order < ActiveRecord::Base
|
39
|
-
add_to_bag :name,
|
40
|
-
|
41
|
-
|
46
|
+
add_to_bag :name,
|
47
|
+
:color,
|
48
|
+
:description,
|
49
|
+
{idx: :integer},
|
50
|
+
{price: :float},
|
51
|
+
{active: :boolean},
|
52
|
+
{paused_at: :date},
|
53
|
+
{msg: :string}
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
"Order #{name} #{color} #{price}"
|
57
|
+
end
|
58
|
+
...
|
42
59
|
|
43
60
|
In controller:
|
44
61
|
|
@@ -47,14 +64,17 @@ In controller:
|
|
47
64
|
def create
|
48
65
|
params = Order.merge({}, self.params) # only if type :date is being used
|
49
66
|
@order = Order.new(params[:order])
|
50
|
-
|
67
|
+
@order.price = 1.23
|
68
|
+
logger.info "Order #{@order.to_s} repriced to #{@order.price}"
|
69
|
+
...
|
51
70
|
def update
|
52
71
|
@order = Order.find(params[:id])
|
53
72
|
params = Order.merge(@order.bag, self.params) # only if type :date is being used
|
73
|
+
@order.update_attributes(params[:order])
|
54
74
|
|
55
75
|
Test
|
56
76
|
====
|
57
77
|
|
58
78
|
rake
|
59
79
|
|
60
|
-
Copyright (c) 2009-
|
80
|
+
Copyright (c) 2009-2015 [Dittmar Krall], released under the MIT license
|
data/lib/act_with_bag/version.rb
CHANGED
data/lib/act_with_bag.rb
CHANGED
@@ -17,7 +17,7 @@ class << ActiveRecord::Base
|
|
17
17
|
add_accessor(baggie, type)
|
18
18
|
}
|
19
19
|
else
|
20
|
-
add_accessor(b, :
|
20
|
+
add_accessor(b, :field)
|
21
21
|
end
|
22
22
|
}
|
23
23
|
end
|
@@ -26,8 +26,7 @@ class << ActiveRecord::Base
|
|
26
26
|
#p "delete_from_bag baglets #{baglets.inspect}"
|
27
27
|
|
28
28
|
self.class_eval %{
|
29
|
-
before_save
|
30
|
-
def baggies_delete
|
29
|
+
before_save do
|
31
30
|
#{baglets}.each {|b|
|
32
31
|
if b.is_a?(Hash)
|
33
32
|
b.each {|baggie, type|
|
@@ -37,7 +36,6 @@ class << ActiveRecord::Base
|
|
37
36
|
self.bag.delete(b.to_sym)
|
38
37
|
end
|
39
38
|
}
|
40
|
-
|
41
39
|
end
|
42
40
|
}
|
43
41
|
|
@@ -85,58 +83,67 @@ class << ActiveRecord::Base
|
|
85
83
|
|
86
84
|
def add_accessor(baggie, type)
|
87
85
|
accessor = baggie.to_s
|
86
|
+
return if accessor_present?(accessor)
|
87
|
+
|
88
88
|
type_sym = type.to_sym
|
89
|
+
typing = {integer: '.to_i', float: '.to_f',
|
90
|
+
string: '.to_s'}[type_sym] || ''
|
89
91
|
#p "add_accessor #{self.to_s} #{baggie.inspect} #{type_sym.inspect}"
|
90
92
|
|
91
|
-
|
92
|
-
#MARS patch, new:
|
93
|
-
#
|
94
|
-
# The @baggies field is indispensable. Otherwise mistakes in renaming
|
95
|
-
# or deleting baggies (without renaming/deleting) the value entry from the
|
96
|
-
# bag, e. g. via delete_from_bag) cannot be detected in a clean way.
|
97
|
-
# Detecting the accessor would be not sufficient, as the accessor may be
|
98
|
-
# created by ActiveRecord::Base or the derived model and it may be
|
99
|
-
# doing completely other things (e. g. accessing a database column).
|
100
|
-
#
|
101
|
-
@baggies ||= {}
|
102
|
-
baggies = ( @baggies[self.to_s.underscore.to_sym] ||= {} )
|
103
|
-
baggies[ baggie ] = type
|
104
|
-
#END
|
93
|
+
@baggies_date[baggie] = type if type_sym == :date
|
105
94
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
95
|
+
unless type_sym == :boolean
|
96
|
+
self.class_eval %{
|
97
|
+
def #{accessor}
|
98
|
+
self.bag && self.bag[:#{baggie}]
|
99
|
+
end
|
100
|
+
}
|
101
|
+
|
102
|
+
self.class_eval %{
|
103
|
+
def #{accessor}=(value)
|
104
|
+
@attributes['bag'] = {} unless bag.is_a?(Hash)
|
105
|
+
unless value.nil?
|
106
|
+
self.bag[:#{baggie}] = value#{typing}
|
107
|
+
else
|
108
|
+
self.bag.delete(:#{baggie})
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
}
|
113
|
+
|
114
|
+
else ################ now boolean handling ###################
|
115
|
+
|
116
|
+
self.class_eval %{
|
117
|
+
def #{accessor}
|
118
|
+
res = bag && bag[:#{baggie}]
|
110
119
|
return res if res.class == FalseClass
|
111
120
|
return res if res.class == TrueClass
|
112
121
|
return res.to_i != 0
|
122
|
+
res
|
113
123
|
end
|
114
|
-
|
115
|
-
end
|
116
|
-
}
|
124
|
+
}
|
117
125
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
126
|
+
self.class_eval %{
|
127
|
+
def #{accessor}=(value)
|
128
|
+
@attributes['bag'] = {} unless bag.is_a?(Hash)
|
129
|
+
falsys = [false, "false", 0, "0", nil]
|
130
|
+
unless falsys.include?(value)
|
131
|
+
self.bag[:#{baggie}] = (value == 'true') || value
|
132
|
+
else
|
133
|
+
self.bag.delete(:#{baggie})
|
134
|
+
nil
|
135
|
+
end
|
127
136
|
end
|
128
|
-
|
129
|
-
|
137
|
+
}
|
138
|
+
|
139
|
+
self.class_eval %{
|
140
|
+
def #{accessor}?
|
141
|
+
#{accessor}
|
142
|
+
end
|
143
|
+
}
|
144
|
+
|
145
|
+
end
|
130
146
|
|
131
|
-
return unless type_sym == :boolean
|
132
|
-
self.class_eval %{
|
133
|
-
def #{accessor}?
|
134
|
-
res = bag && bag[:#{baggie}]
|
135
|
-
return res if res.class == FalseClass
|
136
|
-
return res if res.class == TrueClass
|
137
|
-
res.to_i != 0
|
138
|
-
end
|
139
|
-
}
|
140
147
|
end
|
141
148
|
|
142
149
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
|
4
|
+
class Order < ActiveRecord::Base
|
5
|
+
add_to_bag bool: :boolean
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
class BagBooleanTest < ActiveSupport::TestCase
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@order = Order.new
|
13
|
+
end
|
14
|
+
|
15
|
+
test "uninitialized boolean should return false" do
|
16
|
+
assert_equal false, @order.bool
|
17
|
+
assert_equal false, @order.bag.has_key?(:bool)
|
18
|
+
end
|
19
|
+
|
20
|
+
test "optimized storage of boolean" do
|
21
|
+
@order.bool = false
|
22
|
+
assert_equal false, @order.bag.has_key?(:bool)
|
23
|
+
@order.bool = 0
|
24
|
+
assert_equal false, @order.bag.has_key?(:bool)
|
25
|
+
@order.bool = '0'
|
26
|
+
assert_equal false, @order.bag.has_key?(:bool)
|
27
|
+
end
|
28
|
+
|
29
|
+
test "a true value requires storage in the bag" do
|
30
|
+
@order.bool = true
|
31
|
+
assert_equal true, @order.bag.has_key?(:bool)
|
32
|
+
assert_equal true, @order.bool
|
33
|
+
end
|
34
|
+
|
35
|
+
test "reassigning a false value should drop storage in bag" do
|
36
|
+
@order.bool = true
|
37
|
+
@order.bool = false
|
38
|
+
assert_equal false, @order.bag.has_key?(:bool)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/test/boolean_test.rb
CHANGED
@@ -49,4 +49,14 @@ class BooleanTest < ActiveSupport::TestCase
|
|
49
49
|
assert_equal false, @order.flag
|
50
50
|
end
|
51
51
|
|
52
|
+
test "'false' returns a boolean" do
|
53
|
+
@order.flag = 'false'
|
54
|
+
assert_equal false, @order.flag
|
55
|
+
end
|
56
|
+
|
57
|
+
test "'true' returns a boolean" do
|
58
|
+
@order.flag = 'true'
|
59
|
+
assert_equal true, @order.flag
|
60
|
+
end
|
61
|
+
|
52
62
|
end
|
data/test/string_test.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Order < ActiveRecord::Base
|
4
|
+
add_to_bag string: :string
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
class StringTest < ActiveSupport::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@order = Order.new
|
12
|
+
end
|
13
|
+
|
14
|
+
test "assigning boolean to string" do
|
15
|
+
value = false
|
16
|
+
@order.string = value
|
17
|
+
assert_equal 'false', @order.string
|
18
|
+
value = true
|
19
|
+
@order.string = value
|
20
|
+
assert_equal 'true', @order.string
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
+
require 'simplecov'
|
1
2
|
#require 'coveralls'
|
2
3
|
#Coveralls.wear!
|
3
4
|
|
4
5
|
require 'rubygems'
|
5
|
-
require '
|
6
|
+
require 'minitest/autorun'
|
6
7
|
require 'active_record'
|
7
8
|
|
9
|
+
#SimpleCov.start do
|
10
|
+
# add_filter 'test'
|
11
|
+
# command_name 'Minitest'
|
12
|
+
#end
|
13
|
+
|
8
14
|
ActiveRecord::Base.establish_connection({
|
9
15
|
:adapter => 'sqlite3',
|
10
16
|
:database => 'bag_test'
|
data/test/type_test.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Order < ActiveRecord::Base
|
4
|
+
add_to_bag({i: :integer}, {f: :float})
|
5
|
+
end
|
6
|
+
|
7
|
+
|
8
|
+
class TypeTest < ActiveSupport::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@order = Order.new
|
12
|
+
end
|
13
|
+
|
14
|
+
test "miscellaneous values" do
|
15
|
+
time = Time.now
|
16
|
+
[123, 2.3, "abc", nil, {a: 1}, [1,2], time].each { |value|
|
17
|
+
@order.field = value
|
18
|
+
assert_equal value, @order.field
|
19
|
+
|
20
|
+
@order.save
|
21
|
+
id = @order.id
|
22
|
+
order = Order.find(id)
|
23
|
+
assert_equal value, order.field
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
test "integer" do
|
28
|
+
value = "123"
|
29
|
+
@order.i = value
|
30
|
+
assert_equal value.to_i, @order.i
|
31
|
+
assert_kind_of Integer, @order.i
|
32
|
+
end
|
33
|
+
|
34
|
+
test "float" do
|
35
|
+
value = "1.23"
|
36
|
+
@order.f = value
|
37
|
+
assert_equal value.to_f, @order.f
|
38
|
+
assert_kind_of Float, @order.f
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: act_with_bag
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dittmar Krall
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-10-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sqlite3
|
@@ -33,6 +33,7 @@ extra_rdoc_files: []
|
|
33
33
|
files:
|
34
34
|
- ".gitignore"
|
35
35
|
- ".travis.yml"
|
36
|
+
- ".watchr"
|
36
37
|
- Gemfile
|
37
38
|
- README.md
|
38
39
|
- Rakefile
|
@@ -40,12 +41,15 @@ files:
|
|
40
41
|
- lib/act_with_bag.rb
|
41
42
|
- lib/act_with_bag/version.rb
|
42
43
|
- test/accessor_test.rb
|
44
|
+
- test/bag_boolean_test.rb
|
43
45
|
- test/bag_test.rb
|
44
46
|
- test/boolean_test.rb
|
45
47
|
- test/clean_test.rb
|
46
48
|
- test/delete_test.rb
|
47
49
|
- test/sti_test.rb
|
50
|
+
- test/string_test.rb
|
48
51
|
- test/test_helper.rb
|
52
|
+
- test/type_test.rb
|
49
53
|
homepage: http://matique.de
|
50
54
|
licenses:
|
51
55
|
- MIT
|
@@ -66,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
70
|
version: '0'
|
67
71
|
requirements: []
|
68
72
|
rubyforge_project:
|
69
|
-
rubygems_version: 2.
|
73
|
+
rubygems_version: 2.4.8
|
70
74
|
signing_key:
|
71
75
|
specification_version: 4
|
72
76
|
summary: act_with_bag (baggies) gem
|