act_with_bag 0.4.9.1 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|