protopack 0.0.4 → 0.0.10
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 +7 -0
- data/LICENSE.txt +2 -2
- data/lib/protopack.rb +5 -4
- data/lib/protopack/exporter.rb +48 -0
- data/lib/protopack/package.rb +19 -19
- data/lib/protopack/package_item.rb +26 -16
- data/lib/protopack/styled_yaml.rb +124 -0
- data/lib/protopack/version.rb +1 -1
- data/protopack.gemspec +9 -6
- data/spec/models.rb +58 -14
- data/spec/protopack/exporter_spec.rb +40 -0
- data/spec/protopack/package_spec.rb +47 -22
- data/spec/protopack/packages/standard-widgets/black-description.html +1 -0
- data/spec/protopack/packages/standard-widgets/black-widget-item.yml +3 -0
- data/spec/protopack/packages/standard-widgets/blue-widget-item.yml +1 -0
- data/spec/protopack/packages/standard-widgets/green-widget-item.yml +2 -0
- data/spec/protopack/packages/standard-widgets/package-config.yml +0 -1
- data/spec/protopack/packages/standard-widgets/red-widget-item.yml +1 -0
- data/spec/protopack/packages/standard-widgets/yellow-widget-item.yml +1 -0
- data/spec/spec_helper.rb +1 -2
- metadata +29 -27
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0cb317f6ebff18ddcfef2fa9f2154020e5fb2e22
|
4
|
+
data.tar.gz: d8ee7909c86427a0d10d23eea8dce5e34a5d9667
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 69d583f898589b222eda2d0f0f9795ec648a107681a491e970d64419e69c365f65990ea106421c0a592934c3cc0da2ce9618c86b0298de1cac3660bbe7bce466
|
7
|
+
data.tar.gz: 1abea23055c7ea068b1bc4caea24c6255594625fb9ffa3e8c575f75b9e483b80dceede994383f33abfa6a53eaa3baf77ad9ac7c7c8b78b4f55c83b5e10d2358a
|
data/LICENSE.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c) 2013
|
1
|
+
Copyright (c) 2013 Conan Dalton
|
2
2
|
|
3
3
|
MIT License
|
4
4
|
|
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
19
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
20
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/protopack.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
require "
|
1
|
+
require "yaml"
|
2
|
+
require "aduki"
|
2
3
|
require "protopack/version"
|
3
4
|
require "protopack/package"
|
4
5
|
require "protopack/package_item"
|
6
|
+
require "protopack/styled_yaml"
|
7
|
+
require "protopack/exporter"
|
5
8
|
|
6
|
-
module Protopack
|
7
|
-
# Your code goes here...
|
8
|
-
end
|
9
|
+
module Protopack ; end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Protopack
|
2
|
+
class Exporter
|
3
|
+
def maybe_name_methods ; %i{ export_name full_name presentation_name name } ; end
|
4
|
+
def name_method obj ; maybe_name_methods.detect { |m| obj.respond_to?(m) && obj.send(m) } ; end
|
5
|
+
def array_assoc list ; list.map { |item| to_attributes item } ; end
|
6
|
+
def clean_yaml hsh ; StyledYAML.dump(clean_attrs hsh) ; end
|
7
|
+
def no_name? obj_id ; raise "no name for object: #{obj_id.inspect}" if obj_id.blank? ; end
|
8
|
+
def default_export_config ; { fields: [], associations: [] } ; end
|
9
|
+
def export_config obj ; default_export_config.merge obj.protopack_export_config ; end
|
10
|
+
def to_attributes obj ; obj.slice(*export_config(obj)[:fields]).merge build_association_table obj ; end
|
11
|
+
def to_yaml obj, meta={} ; clean_yaml to_package obj, meta ; end
|
12
|
+
def remove_blanks attrs ; attrs.recursively_remove_by_value! { |v| (v != false) && v.blank? } ; end
|
13
|
+
def styled_literal str ; str.is_a?(String) ? StyledYAML.literal(str) : str ; end
|
14
|
+
def clean_attrs attrs ; remove_blanks(attrs).recursively_replace_values { |k,v| styled_literal v } ; end
|
15
|
+
|
16
|
+
def build_association_table obj
|
17
|
+
export_config(obj)[:associations].inject({ }) { |table, name|
|
18
|
+
if name.is_a? Hash
|
19
|
+
build_association obj, table, name[:get], name[:set]
|
20
|
+
else
|
21
|
+
build_association obj, table, name, "#{name}_attributes"
|
22
|
+
end
|
23
|
+
table
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_association obj, table, getter, setter
|
28
|
+
assoc = obj.send getter
|
29
|
+
return if assoc.blank? || assoc.empty?
|
30
|
+
attrs = (assoc.respond_to?(:each)) ? array_assoc(assoc) : to_attributes(assoc)
|
31
|
+
table[setter] = attrs
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_package obj, meta={ }
|
35
|
+
obj_name = obj.send(name_method obj)
|
36
|
+
obj_id = obj_name.to_s.gsub(/_/, '-')
|
37
|
+
|
38
|
+
no_name? obj_id
|
39
|
+
|
40
|
+
hsh = {
|
41
|
+
id: obj_id,
|
42
|
+
description: obj_name,
|
43
|
+
type: obj.class.name,
|
44
|
+
attributes: to_attributes(obj),
|
45
|
+
}.deep_merge(meta).recursively_stringify_keys!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/protopack/package.rb
CHANGED
@@ -1,18 +1,14 @@
|
|
1
|
-
class Protopack::Package
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@config = (cfg.is_a?(Hashie::Mash) ? cfg : Hashie::Mash.new(cfg))
|
10
|
-
end
|
1
|
+
class Protopack::Package < Aduki::Initializable
|
2
|
+
attr_accessor :name
|
3
|
+
attr_accessor :title
|
4
|
+
attr_accessor :description
|
5
|
+
attr_accessor :authors
|
6
|
+
attr_accessor :item_files
|
7
|
+
attr_accessor :root
|
8
|
+
aduki updated: Date
|
11
9
|
|
12
10
|
def items
|
13
|
-
|
14
|
-
Protopack::PackageItem.new(Hashie::Mash.new(YAML.load(File.read(item_file))))
|
15
|
-
}
|
11
|
+
item_files.map { |item_file| Protopack::PackageItem.load(item_file) }
|
16
12
|
end
|
17
13
|
|
18
14
|
def item id
|
@@ -22,11 +18,15 @@ class Protopack::Package
|
|
22
18
|
end
|
23
19
|
|
24
20
|
def apply_missing
|
25
|
-
sorted_items.select(&:missing?)
|
21
|
+
items = sorted_items.select(&:missing?)
|
22
|
+
items = items.select { |i| yield i } if block_given?
|
23
|
+
items.each(&:apply!)
|
26
24
|
end
|
27
25
|
|
28
26
|
def apply_all
|
29
|
-
sorted_items
|
27
|
+
items = sorted_items
|
28
|
+
items = items.select { |i| yield i } if block_given?
|
29
|
+
items.each(&:apply!)
|
30
30
|
end
|
31
31
|
|
32
32
|
def sorted_items
|
@@ -46,9 +46,9 @@ class Protopack::Package
|
|
46
46
|
|
47
47
|
def self.all
|
48
48
|
Dir.glob("#{config_root}/*/package-config.yml").map { |pkg_cfg|
|
49
|
-
cfg =
|
49
|
+
cfg = YAML.load(File.read(pkg_cfg))
|
50
50
|
root = File.dirname pkg_cfg
|
51
|
-
cfg["
|
51
|
+
cfg["item_files"] = Dir.glob("#{root}/*item*.yml")
|
52
52
|
cfg["root"] = root
|
53
53
|
new cfg
|
54
54
|
}
|
@@ -56,8 +56,8 @@ class Protopack::Package
|
|
56
56
|
|
57
57
|
def self.find name
|
58
58
|
root = "#{config_root}/#{name}"
|
59
|
-
cfg =
|
60
|
-
cfg["
|
59
|
+
cfg = YAML.load(File.read("#{root}/package-config.yml"))
|
60
|
+
cfg["item_files"] = Dir.glob("#{root}/*item*.yml")
|
61
61
|
cfg["root"] = root
|
62
62
|
new cfg
|
63
63
|
end
|
@@ -1,17 +1,15 @@
|
|
1
|
-
class Protopack::PackageItem
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def name
|
13
|
-
attributes.name
|
14
|
-
end
|
1
|
+
class Protopack::PackageItem < Aduki::Initializable
|
2
|
+
attr_accessor :id
|
3
|
+
attr_accessor :description
|
4
|
+
attr_accessor :locale
|
5
|
+
attr_accessor :default_locale
|
6
|
+
attr_accessor :type
|
7
|
+
attr_accessor :ordinal
|
8
|
+
attr_accessor :attributes
|
9
|
+
attr_accessor :resources
|
10
|
+
attr_accessor :protopack_filename
|
11
|
+
|
12
|
+
def name ; attributes[:name] || attributes["name"] ; end
|
15
13
|
|
16
14
|
def lookup_class base, list
|
17
15
|
base = base.const_get list.shift
|
@@ -31,13 +29,25 @@ class Protopack::PackageItem
|
|
31
29
|
target_class.existence attributes
|
32
30
|
end
|
33
31
|
|
32
|
+
def load_resources hsh, d = File.dirname(protopack_filename)
|
33
|
+
(resources || {}).inject(hsh) { |hsh, (k, v)|
|
34
|
+
hsh[k] = File.read(File.join d, v)
|
35
|
+
hsh
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
34
39
|
def apply!
|
35
40
|
factory = existence
|
36
41
|
if factory.empty?
|
37
|
-
factory.create! attributes
|
42
|
+
factory.create! load_resources(attributes.to_hash)
|
38
43
|
else
|
39
|
-
factory.first.update_attributes attributes
|
44
|
+
factory.first.update_attributes attributes.to_hash
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
48
|
+
def self.load filename
|
49
|
+
Protopack::PackageItem.new(YAML.load(File.read(filename)).merge(protopack_filename: filename))
|
50
|
+
rescue
|
51
|
+
raise "error reading from file #{filename}"
|
52
|
+
end
|
43
53
|
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'psych'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
# Public: A Psych extension to enable choosing output styles for specific
|
5
|
+
# objects.
|
6
|
+
#
|
7
|
+
# Thanks to Tenderlove for help in <http://stackoverflow.com/q/9640277/11687>
|
8
|
+
#
|
9
|
+
# Gist: https://gist.github.com/mislav/2023978
|
10
|
+
#
|
11
|
+
# Examples
|
12
|
+
#
|
13
|
+
# data = {
|
14
|
+
# response: { body: StyledYAML.literal(json_string), status: 200 },
|
15
|
+
# person: StyledYAML.inline({ 'name' => 'Stevie', 'age' => 12 }),
|
16
|
+
# array: StyledYAML.inline(%w[ apples bananas oranges ])
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# StyledYAML.dump data, $stdout
|
20
|
+
#
|
21
|
+
module Protopack::StyledYAML
|
22
|
+
# Tag strings to be output using literal style
|
23
|
+
def self.literal obj
|
24
|
+
obj.extend LiteralScalar
|
25
|
+
return obj
|
26
|
+
end
|
27
|
+
|
28
|
+
# http://www.yaml.org/spec/1.2/spec.html#id2795688
|
29
|
+
module LiteralScalar
|
30
|
+
def yaml_style() Psych::Nodes::Scalar::LITERAL end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Tag Hashes or Arrays to be output all on one line
|
34
|
+
def self.inline obj
|
35
|
+
case obj
|
36
|
+
when Hash then obj.extend FlowMapping
|
37
|
+
when Array then obj.extend FlowSequence
|
38
|
+
else
|
39
|
+
warn "#{self}: unrecognized type to inline (#{obj.class.name})"
|
40
|
+
end
|
41
|
+
return obj
|
42
|
+
end
|
43
|
+
|
44
|
+
# http://www.yaml.org/spec/1.2/spec.html#id2790832
|
45
|
+
module FlowMapping
|
46
|
+
def yaml_style() Psych::Nodes::Mapping::FLOW end
|
47
|
+
end
|
48
|
+
|
49
|
+
# http://www.yaml.org/spec/1.2/spec.html#id2790320
|
50
|
+
module FlowSequence
|
51
|
+
def yaml_style() Psych::Nodes::Sequence::FLOW end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Custom tree builder class to recognize scalars tagged with `yaml_style`
|
55
|
+
class TreeBuilder < Psych::TreeBuilder
|
56
|
+
attr_writer :next_sequence_or_mapping_style
|
57
|
+
|
58
|
+
def initialize(*args)
|
59
|
+
super
|
60
|
+
@next_sequence_or_mapping_style = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def next_sequence_or_mapping_style default_style
|
64
|
+
style = @next_sequence_or_mapping_style || default_style
|
65
|
+
@next_sequence_or_mapping_style = nil
|
66
|
+
style
|
67
|
+
end
|
68
|
+
|
69
|
+
def scalar value, anchor, tag, plain, quoted, style
|
70
|
+
if style_any?(style) and value.respond_to?(:yaml_style) and style = value.yaml_style
|
71
|
+
if style_literal? style
|
72
|
+
plain = false
|
73
|
+
quoted = true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
super
|
77
|
+
end
|
78
|
+
|
79
|
+
def style_any?(style) Psych::Nodes::Scalar::ANY == style end
|
80
|
+
|
81
|
+
def style_literal?(style) Psych::Nodes::Scalar::LITERAL == style end
|
82
|
+
|
83
|
+
%w[sequence mapping].each do |type|
|
84
|
+
class_eval <<-RUBY
|
85
|
+
def start_#{type}(anchor, tag, implicit, style)
|
86
|
+
style = next_sequence_or_mapping_style(style)
|
87
|
+
super
|
88
|
+
end
|
89
|
+
RUBY
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Custom tree class to handle Hashes and Arrays tagged with `yaml_style`
|
94
|
+
class YAMLTree < Psych::Visitors::YAMLTree
|
95
|
+
%w[String Hash Array Psych_Set Psych_Omap].each do |klass|
|
96
|
+
class_eval <<-RUBY
|
97
|
+
def visit_#{klass} o
|
98
|
+
if o.respond_to? :yaml_style
|
99
|
+
@emitter.next_sequence_or_mapping_style = o.yaml_style
|
100
|
+
end
|
101
|
+
super
|
102
|
+
end
|
103
|
+
RUBY
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# A Psych.dump alternative that uses the custom TreeBuilder
|
108
|
+
def self.dump obj, io = nil, options = {}
|
109
|
+
real_io = io || StringIO.new(''.encode('utf-8'))
|
110
|
+
visitor = YAMLTree.new(options, TreeBuilder.new)
|
111
|
+
visitor << obj
|
112
|
+
ast = visitor.tree
|
113
|
+
|
114
|
+
begin
|
115
|
+
ast.yaml real_io
|
116
|
+
rescue
|
117
|
+
# The `yaml` method was introduced in later versions, so fall back to
|
118
|
+
# constructing a visitor
|
119
|
+
Psych::Visitors::Emitter.new(real_io).accept ast
|
120
|
+
end
|
121
|
+
|
122
|
+
io ? io : real_io.string
|
123
|
+
end
|
124
|
+
end
|
data/lib/protopack/version.rb
CHANGED
data/protopack.gemspec
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
1
|
+
# -*- coding: utf-8; mode: ruby -*-
|
2
|
+
|
2
3
|
lib = File.expand_path('../lib', __FILE__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
|
4
6
|
require 'protopack/version'
|
5
7
|
|
6
8
|
Gem::Specification.new do |gem|
|
7
9
|
gem.name = "protopack"
|
8
10
|
gem.version = Protopack::VERSION
|
9
|
-
gem.authors = ["
|
11
|
+
gem.authors = ["Conan Dalton"]
|
12
|
+
gem.license = 'MIT'
|
10
13
|
gem.email = ["conan@conandalton.net"]
|
11
|
-
gem.description = %q{Create objects from object definitions stored as files}
|
12
|
-
gem.summary = %q{Store packages of object prototypes on-disk as YML; this gem allows you scan each package for missing items and apply them to your repository.}
|
14
|
+
gem.description = %q{ Create objects from object definitions stored as files, like test fixtures, only intended for production use. }
|
15
|
+
gem.summary = %q{ Store packages of object prototypes on-disk as YML; this gem allows you scan each package for missing items and apply them to your repository. }
|
13
16
|
gem.homepage = "https://github.com/conanite/protopack"
|
14
17
|
|
15
|
-
gem.add_dependency '
|
16
|
-
gem.add_development_dependency 'rspec'
|
18
|
+
gem.add_dependency 'aduki', '>= 0.2.7'
|
19
|
+
gem.add_development_dependency 'rspec'
|
17
20
|
|
18
21
|
gem.files = `git ls-files`.split($/)
|
19
22
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
data/spec/models.rb
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
require 'aduki'
|
2
|
+
|
3
|
+
class Object
|
4
|
+
def blank?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class String
|
10
|
+
def blank?
|
11
|
+
strip == ''
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class NilClass
|
16
|
+
def blank?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Hash
|
22
|
+
def deep_merge other
|
23
|
+
merge other
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
1
27
|
class Repository
|
2
28
|
def initialize klass, name
|
3
29
|
@klass, @name = klass, name
|
@@ -20,9 +46,11 @@ class Repository
|
|
20
46
|
end
|
21
47
|
end
|
22
48
|
|
23
|
-
class Widget
|
49
|
+
class Widget < Aduki::Initializable
|
24
50
|
@@widgets = []
|
25
51
|
|
52
|
+
attr_accessor :wots, :colour, :height, :density, :name, :description
|
53
|
+
|
26
54
|
def self.all
|
27
55
|
@@widgets
|
28
56
|
end
|
@@ -31,28 +59,41 @@ class Widget
|
|
31
59
|
@@widgets = []
|
32
60
|
end
|
33
61
|
|
34
|
-
def
|
35
|
-
@attrs = attrs.is_a?(Hash) ? Hashie::Mash.new(attrs) : attrs
|
62
|
+
def aduki_after_initialize
|
36
63
|
@@widgets << self
|
37
64
|
end
|
38
65
|
|
39
|
-
def
|
40
|
-
|
66
|
+
def protopack_export_config
|
67
|
+
{ fields: [:colour, :height, :density, :name ], associations: [{ get: :mywots, set: :newwots }]}
|
68
|
+
end
|
69
|
+
|
70
|
+
def slice *names
|
71
|
+
Hash[*(names.zip(names.map { |n| send n }).flatten)]
|
72
|
+
end
|
73
|
+
|
74
|
+
def mywots
|
75
|
+
self.wots
|
76
|
+
end
|
77
|
+
|
78
|
+
def newwots= wots_attrs
|
79
|
+
self.wots = wots_attrs.map { |a| Wot::Zit.new a }
|
41
80
|
end
|
42
81
|
|
43
82
|
def update_attributes attrs
|
44
|
-
|
83
|
+
aduki_apply_attributes attrs
|
45
84
|
end
|
46
85
|
|
47
86
|
def self.existence attrs
|
48
|
-
Repository.new Widget, attrs
|
87
|
+
Repository.new Widget, attrs["colour"]
|
49
88
|
end
|
50
89
|
end
|
51
90
|
|
52
91
|
module Wot
|
53
|
-
class Zit
|
92
|
+
class Zit < Aduki::Initializable
|
54
93
|
@@wotzits = []
|
55
94
|
|
95
|
+
attr_accessor :colour, :height, :density, :name
|
96
|
+
|
56
97
|
def self.all
|
57
98
|
@@wotzits
|
58
99
|
end
|
@@ -61,21 +102,24 @@ module Wot
|
|
61
102
|
@@wotzits = []
|
62
103
|
end
|
63
104
|
|
64
|
-
def
|
65
|
-
@attrs = attrs.is_a?(Hash) ? Hashie::Mash.new(attrs) : attrs
|
105
|
+
def aduki_after_initialize
|
66
106
|
@@wotzits << self
|
67
107
|
end
|
68
108
|
|
69
|
-
def
|
70
|
-
|
109
|
+
def protopack_export_config
|
110
|
+
{ fields: [:colour, :height, :density, :name ], associations: [] }
|
111
|
+
end
|
112
|
+
|
113
|
+
def slice *names
|
114
|
+
Hash[*(names.zip(names.map { |n| send n }).flatten)]
|
71
115
|
end
|
72
116
|
|
73
117
|
def update_attributes attrs
|
74
|
-
|
118
|
+
aduki_apply_attributes attrs
|
75
119
|
end
|
76
120
|
|
77
121
|
def self.existence attrs
|
78
|
-
Repository.new Wot::Zit, attrs
|
122
|
+
Repository.new Wot::Zit, attrs["colour"]
|
79
123
|
end
|
80
124
|
end
|
81
125
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require File.expand_path('../../spec_helper', __FILE__)
|
4
|
+
|
5
|
+
# from aduki
|
6
|
+
require 'core_ext/array'
|
7
|
+
require 'core_ext/hash'
|
8
|
+
|
9
|
+
describe Protopack::Package do
|
10
|
+
|
11
|
+
it "exports a simple widget" do
|
12
|
+
wz0 = { colour: 41, height: 42, density: 43 }
|
13
|
+
wz1 = { colour: 51, height: 52, density: 53 }
|
14
|
+
w = Widget.new colour: 1, height: 2, density: 3, name: "Park Lodge Café", newwots: [ wz0, wz1 ]
|
15
|
+
|
16
|
+
exporter = Protopack::Exporter.new
|
17
|
+
hsh = exporter.to_package(w)
|
18
|
+
expected = <<YML.strip
|
19
|
+
---
|
20
|
+
id: Park Lodge Café
|
21
|
+
description: Park Lodge Café
|
22
|
+
type: Widget
|
23
|
+
attributes:
|
24
|
+
colour: 1
|
25
|
+
height: 2
|
26
|
+
density: 3
|
27
|
+
name: Park Lodge Café
|
28
|
+
newwots:
|
29
|
+
- colour: 41
|
30
|
+
height: 42
|
31
|
+
density: 43
|
32
|
+
- colour: 51
|
33
|
+
height: 52
|
34
|
+
density: 53
|
35
|
+
YML
|
36
|
+
|
37
|
+
expect(exporter.clean_yaml(hsh).strip).to eq expected
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -4,36 +4,41 @@ require File.expand_path('../../spec_helper', __FILE__)
|
|
4
4
|
|
5
5
|
describe Protopack::Package do
|
6
6
|
|
7
|
+
module HasRegion
|
8
|
+
attr_accessor :region
|
9
|
+
end
|
10
|
+
|
7
11
|
before {
|
12
|
+
Protopack::PackageItem.send :include, HasRegion
|
8
13
|
Protopack::Package.config_root = File.expand_path('../packages', __FILE__)
|
9
14
|
Widget.destroy_all
|
10
15
|
Wot::Zit.destroy_all
|
11
16
|
}
|
12
17
|
|
13
18
|
it "should find all the packages" do
|
14
|
-
Protopack::Package.all.map(&:name).join(" ").
|
19
|
+
expect(Protopack::Package.all.map(&:name).join(" ")).to eq "advanced-widgets standard-widgets"
|
15
20
|
end
|
16
21
|
|
17
22
|
it "should find a given package" do
|
18
23
|
p = Protopack::Package.find("standard-widgets")
|
19
|
-
p.name.
|
24
|
+
expect(p.name).to eq "standard-widgets"
|
20
25
|
|
21
|
-
p.title
|
22
|
-
p.title
|
26
|
+
expect(p.title["en"]).to eq "Standard Widgets"
|
27
|
+
expect(p.title["fr"]).to eq "Widgets standards"
|
23
28
|
|
24
|
-
p.description
|
25
|
-
p.description
|
29
|
+
expect(p.description["en"]).to eq "Use these widgets for everyday widgeting"
|
30
|
+
expect(p.description["fr"]).to eq "Ces widgets sont utilisables pour votre widgeting quotidien"
|
26
31
|
|
27
|
-
p.authors.
|
32
|
+
expect(p.authors).to eq %w{ baz titi Z }
|
28
33
|
|
29
|
-
p.updated.
|
34
|
+
expect(p.updated).to eq Date.parse("2013-03-15")
|
30
35
|
end
|
31
36
|
|
32
37
|
it "should install all items from a package" do
|
33
38
|
p = Protopack::Package.find("standard-widgets")
|
34
39
|
p.apply_all
|
35
40
|
|
36
|
-
Widget.all.map(&:colour).
|
41
|
+
expect(Widget.all.map(&:colour)).to eq %w{ red blue yellow black green }
|
37
42
|
end
|
38
43
|
|
39
44
|
it "should install all items from a package, overwriting existing items, respecting #ordinal property" do
|
@@ -43,12 +48,32 @@ describe Protopack::Package do
|
|
43
48
|
p = Protopack::Package.find("standard-widgets")
|
44
49
|
p.apply_all
|
45
50
|
|
46
|
-
Widget.all.map(&:colour).
|
47
|
-
Widget.all[0].height.
|
48
|
-
Widget.all[1].height.
|
49
|
-
Widget.all[2].height.
|
50
|
-
Widget.all[3].height.
|
51
|
-
Widget.all[4].height.
|
51
|
+
expect(Widget.all.map(&:colour)).to eq %w{ blue green red yellow black }
|
52
|
+
expect(Widget.all[0].height).to eq 'elephant'
|
53
|
+
expect(Widget.all[1].height).to eq 'zebra'
|
54
|
+
expect(Widget.all[2].height).to eq 'tiger'
|
55
|
+
expect(Widget.all[3].height).to eq 'hyena'
|
56
|
+
expect(Widget.all[4].height).to eq 'camel'
|
57
|
+
|
58
|
+
green = Widget.all[1]
|
59
|
+
expect(green.name).to eq "The green widget for obtuse African zebras"
|
60
|
+
|
61
|
+
black = Widget.all[4]
|
62
|
+
black_desc = "<html><p>this is what a black widget looks like</p></html>"
|
63
|
+
expect(black.name).to be_nil
|
64
|
+
expect(black.description).to eq black_desc
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should install all items from a package subject to filtering" do
|
68
|
+
Widget.new :colour => "blue"
|
69
|
+
Widget.new :colour => "green"
|
70
|
+
|
71
|
+
Protopack::Package.find("standard-widgets").apply_all { |x| x.region == "Africa" }
|
72
|
+
|
73
|
+
expect(Widget.all.map(&:colour)).to eq %w{ blue green yellow }
|
74
|
+
expect(Widget.all[0].height).to eq 'elephant'
|
75
|
+
expect(Widget.all[1].height).to eq 'zebra'
|
76
|
+
expect(Widget.all[2].height).to eq 'hyena'
|
52
77
|
end
|
53
78
|
|
54
79
|
it "should install only missing items from a package, not overwriting existing items" do
|
@@ -58,18 +83,18 @@ describe Protopack::Package do
|
|
58
83
|
p = Protopack::Package.find("standard-widgets")
|
59
84
|
p.apply_missing
|
60
85
|
|
61
|
-
Widget.all.map(&:colour).
|
62
|
-
Widget.all[0].height.
|
63
|
-
Widget.all[1].height.
|
64
|
-
Widget.all[2].height.
|
65
|
-
Widget.all[3].height.
|
66
|
-
Widget.all[4].height.
|
86
|
+
expect(Widget.all.map(&:colour)).to eq %w{ blue green red yellow black}
|
87
|
+
expect(Widget.all[0].height).to eq "not specified"
|
88
|
+
expect(Widget.all[1].height).to eq "not specified"
|
89
|
+
expect(Widget.all[2].height).to eq 'tiger'
|
90
|
+
expect(Widget.all[3].height).to eq 'hyena'
|
91
|
+
expect(Widget.all[4].height).to eq 'camel'
|
67
92
|
end
|
68
93
|
|
69
94
|
it "looks up namespaced class names" do
|
70
95
|
p = Protopack::Package.find("advanced-widgets")
|
71
96
|
p.apply_missing
|
72
97
|
|
73
|
-
Wot::Zit.all.map(&:colour).
|
98
|
+
expect(Wot::Zit.all.map(&:colour).sort).to eq %w{ lavender magenta }
|
74
99
|
end
|
75
100
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
<html><p>this is what a black widget looks like</p></html>
|
data/spec/spec_helper.rb
CHANGED
@@ -12,7 +12,7 @@ require File.expand_path('../../lib/protopack', __FILE__)
|
|
12
12
|
#
|
13
13
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
14
14
|
RSpec.configure do |config|
|
15
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
15
|
+
# config.treat_symbols_as_metadata_keys_with_true_values = true
|
16
16
|
config.run_all_when_everything_filtered = true
|
17
17
|
config.filter_run :focus
|
18
18
|
|
@@ -24,4 +24,3 @@ RSpec.configure do |config|
|
|
24
24
|
end
|
25
25
|
|
26
26
|
load(File.dirname(__FILE__) + '/models.rb')
|
27
|
-
|
metadata
CHANGED
@@ -1,71 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protopack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.10
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
-
|
7
|
+
- Conan Dalton
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2020-08-09 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
14
|
+
name: aduki
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
19
|
+
version: 0.2.7
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
26
|
+
version: 0.2.7
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rspec
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
|
-
version: '
|
33
|
+
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
|
-
version: '
|
46
|
-
description: Create objects from object definitions stored as files
|
40
|
+
version: '0'
|
41
|
+
description: " Create objects from object definitions stored as files, like test fixtures,
|
42
|
+
only intended for production use. "
|
47
43
|
email:
|
48
44
|
- conan@conandalton.net
|
49
45
|
executables: []
|
50
46
|
extensions: []
|
51
47
|
extra_rdoc_files: []
|
52
48
|
files:
|
53
|
-
- .gitignore
|
54
|
-
- .rspec
|
49
|
+
- ".gitignore"
|
50
|
+
- ".rspec"
|
55
51
|
- Gemfile
|
56
52
|
- LICENSE.txt
|
57
53
|
- README.md
|
58
54
|
- Rakefile
|
59
55
|
- lib/protopack.rb
|
56
|
+
- lib/protopack/exporter.rb
|
60
57
|
- lib/protopack/package.rb
|
61
58
|
- lib/protopack/package_item.rb
|
59
|
+
- lib/protopack/styled_yaml.rb
|
62
60
|
- lib/protopack/version.rb
|
63
61
|
- protopack.gemspec
|
64
62
|
- spec/models.rb
|
63
|
+
- spec/protopack/exporter_spec.rb
|
65
64
|
- spec/protopack/package_spec.rb
|
66
65
|
- spec/protopack/packages/advanced-widgets/lavender-widget-item.yml
|
67
66
|
- spec/protopack/packages/advanced-widgets/magenta-widget-item.yml
|
68
67
|
- spec/protopack/packages/advanced-widgets/package-config.yml
|
68
|
+
- spec/protopack/packages/standard-widgets/black-description.html
|
69
69
|
- spec/protopack/packages/standard-widgets/black-widget-item.yml
|
70
70
|
- spec/protopack/packages/standard-widgets/blue-widget-item.yml
|
71
71
|
- spec/protopack/packages/standard-widgets/green-widget-item.yml
|
@@ -74,36 +74,38 @@ files:
|
|
74
74
|
- spec/protopack/packages/standard-widgets/yellow-widget-item.yml
|
75
75
|
- spec/spec_helper.rb
|
76
76
|
homepage: https://github.com/conanite/protopack
|
77
|
-
licenses:
|
77
|
+
licenses:
|
78
|
+
- MIT
|
79
|
+
metadata: {}
|
78
80
|
post_install_message:
|
79
81
|
rdoc_options: []
|
80
82
|
require_paths:
|
81
83
|
- lib
|
82
84
|
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
85
|
requirements:
|
85
|
-
- -
|
86
|
+
- - ">="
|
86
87
|
- !ruby/object:Gem::Version
|
87
88
|
version: '0'
|
88
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
90
|
requirements:
|
91
|
-
- -
|
91
|
+
- - ">="
|
92
92
|
- !ruby/object:Gem::Version
|
93
93
|
version: '0'
|
94
94
|
requirements: []
|
95
95
|
rubyforge_project:
|
96
|
-
rubygems_version:
|
96
|
+
rubygems_version: 2.5.2.3
|
97
97
|
signing_key:
|
98
|
-
specification_version:
|
98
|
+
specification_version: 4
|
99
99
|
summary: Store packages of object prototypes on-disk as YML; this gem allows you scan
|
100
100
|
each package for missing items and apply them to your repository.
|
101
101
|
test_files:
|
102
102
|
- spec/models.rb
|
103
|
+
- spec/protopack/exporter_spec.rb
|
103
104
|
- spec/protopack/package_spec.rb
|
104
105
|
- spec/protopack/packages/advanced-widgets/lavender-widget-item.yml
|
105
106
|
- spec/protopack/packages/advanced-widgets/magenta-widget-item.yml
|
106
107
|
- spec/protopack/packages/advanced-widgets/package-config.yml
|
108
|
+
- spec/protopack/packages/standard-widgets/black-description.html
|
107
109
|
- spec/protopack/packages/standard-widgets/black-widget-item.yml
|
108
110
|
- spec/protopack/packages/standard-widgets/blue-widget-item.yml
|
109
111
|
- spec/protopack/packages/standard-widgets/green-widget-item.yml
|