middleman-data_source 0.6.1 → 0.7.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 +4 -4
- data/changelog.md +8 -0
- data/lib/middleman/data_source/extension.rb +47 -19
- data/lib/middleman/data_source/version.rb +1 -1
- data/readme.md +59 -0
- data/spec/fixtures/collection/config.rb +37 -0
- data/spec/fixtures/nested_alias/config.rb +19 -0
- data/spec/lib/middleman-data_source_spec.rb +1 -3
- data/spec/lib/middleman/data_source/extension_spec.rb +49 -3
- data/spec/lib/middleman/data_source/version_spec.rb +1 -3
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c171a11ee4a3c842ff19e9da42ef88fa4db97efe
|
4
|
+
data.tar.gz: c68e86e0c5b7bd274cd4fb1bf94bd6dd7668b88b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f781063b434454cbe0051dc59e60a49ba52f4e6cabc77dcced2c06c6dde231e9652f0b539fd5e648052880391c483c1d6b657cb5fcdeca5567b81ca1424f17c8
|
7
|
+
data.tar.gz: 4067143433e37ed48fefeb716b44ace151b7ba8efbfb7b82dbde3c605c41421aa15b735db6ecf185398289784a75a69fc523bdc4564432deaec6519f7bb7dfc4
|
data/changelog.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# 0.7.1
|
2
|
+
- allow passing data type to collection
|
3
|
+
- fix access to data object in middleman 3.x code branches
|
4
|
+
|
5
|
+
# 0.7.0 [YANKED]
|
6
|
+
- feat(collection): create a collection type that can generate a collection of resources based off of an index endpoint. [more info](readme.md#creating-a-collection)
|
7
|
+
- stop using `ActiveSupport::JSON` to parse json, this causes dates to no longer be decoded. To restore the original behavior, add a custom decoder for json.
|
8
|
+
|
1
9
|
# 0.6.1
|
2
10
|
- fixes for newer versions of middleman 4 compatability
|
3
11
|
|
@@ -5,12 +5,14 @@ module Middleman
|
|
5
5
|
self.supports_multiple_instances = true
|
6
6
|
|
7
7
|
option :rack_app, nil, 'rack app to use'
|
8
|
-
option :root, nil, 'http(s) host to use'
|
8
|
+
option :root, nil, 'http(s) host or file path to use'
|
9
9
|
option :files, [], 'routes to mount as remote data files'
|
10
10
|
option :sources, [], 'array of sources to mount as data'
|
11
11
|
option :decoders, {}, 'callable functions to decode data sources'
|
12
|
+
option :collection, {}, 'group of recursive resources'
|
12
13
|
|
13
|
-
attr_reader :decoders, :sources
|
14
|
+
attr_reader :decoders, :sources, :collection,
|
15
|
+
:app_inst
|
14
16
|
|
15
17
|
def rack_app
|
16
18
|
@_rack_app ||= ::Rack::Test::Session.new( ::Rack::MockSession.new( options.rack_app ) )
|
@@ -18,19 +20,35 @@ module Middleman
|
|
18
20
|
|
19
21
|
def initialize app, options_hash={}, &block
|
20
22
|
super app, options_hash, &block
|
23
|
+
@app_inst = app.respond_to?(:inst) ? app.inst : app
|
21
24
|
|
22
|
-
|
23
|
-
@
|
24
|
-
@decoders = default_decoders.merge(options.decoders)
|
25
|
+
@sources = options.sources.dup + convert_files_to_sources(options.files)
|
26
|
+
@decoders = default_decoders.merge(options.decoders)
|
25
27
|
|
26
|
-
options.
|
27
|
-
@
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
if options.collection.empty?
|
29
|
+
@collection = false
|
30
|
+
else
|
31
|
+
@collection = options.collection
|
32
|
+
sources.push options.collection.merge alias: File.join( options.collection[:alias], 'all' )
|
31
33
|
end
|
32
34
|
|
33
|
-
|
35
|
+
sources.each do |source|
|
36
|
+
add_data_callback_for_source(source)
|
37
|
+
end
|
38
|
+
|
39
|
+
if collection
|
40
|
+
collection[:items].call( app_inst.data[collection[:alias]]['all'] ).map do |source|
|
41
|
+
source[:alias] = File.join(collection[:alias], source[:alias])
|
42
|
+
source
|
43
|
+
end.each do |source|
|
44
|
+
add_data_callback_for_source(source)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def add_data_callback_for_source source
|
34
52
|
raw_extension = File.extname(source[:path])
|
35
53
|
extension = raw_extension.split('?').first
|
36
54
|
parts = source[:alias].split(File::SEPARATOR)
|
@@ -44,24 +62,34 @@ module Middleman
|
|
44
62
|
else
|
45
63
|
original_callback = app_inst.data.callbacks[parts.first]
|
46
64
|
app_inst.data.callbacks[parts.first] = Proc.new do
|
47
|
-
|
48
|
-
|
49
|
-
|
65
|
+
begin
|
66
|
+
built_data = { basename => decode_data(source, extension) }
|
67
|
+
parts[1..-1].reverse.each do |part|
|
68
|
+
built_data = { part => built_data }
|
69
|
+
end
|
70
|
+
|
71
|
+
attempt_merge_then_enhance built_data, original_callback
|
72
|
+
rescue => e
|
73
|
+
binding.pry
|
50
74
|
end
|
51
|
-
|
52
|
-
attempt_merge_then_enhance built_data, original_callback
|
53
75
|
end
|
54
76
|
end
|
55
77
|
end
|
56
|
-
end
|
57
78
|
|
58
|
-
|
79
|
+
def convert_files_to_sources files={}
|
80
|
+
files.flat_map do |remote_path, local|
|
81
|
+
{
|
82
|
+
alias: (local || remote_path),
|
83
|
+
path: remote_path
|
84
|
+
}
|
85
|
+
end
|
86
|
+
end
|
59
87
|
|
60
88
|
def default_decoders
|
61
89
|
{
|
62
90
|
json: {
|
63
91
|
extensions: ['.json'],
|
64
|
-
decoder: ->(source) {
|
92
|
+
decoder: ->(source) { JSON.parse(source) },
|
65
93
|
},
|
66
94
|
yaml: {
|
67
95
|
extensions: ['.yaml', '.yml'],
|
data/readme.md
CHANGED
@@ -128,6 +128,64 @@ activate :data_source do |c|
|
|
128
128
|
|
129
129
|
In the above example, I can access `app.data.by_extension` w/ the file contents decoded by `CustomType`, because it's extension `.ctype` matches the one defined by the `:my_type` decoder. Similarly, `app.data.foo_bar` is also run through `CustomType` because it's `:type` attribute is set to `:my_type`.
|
130
130
|
|
131
|
+
|
132
|
+
### Creating a collection
|
133
|
+
|
134
|
+
Collections allow you to collection sources that have belong together in an array and have distinct urls. This would loosely follow the Rails index/show convension. For example, lets say we have an endpoint that tells us about some Game of Thrones characters, and then includes a single endpoint for each with expanded information:
|
135
|
+
|
136
|
+
```json
|
137
|
+
# /got/index.json
|
138
|
+
[
|
139
|
+
{ "name": "Eddard Stark", "url": "/got/eddard-stark.json" },
|
140
|
+
{ "name": "Hodor", "url": "/got/hodor.json" }
|
141
|
+
]
|
142
|
+
```
|
143
|
+
|
144
|
+
```json
|
145
|
+
# /got/eddard-stark.json
|
146
|
+
{
|
147
|
+
"name": "Eddard Stark",
|
148
|
+
"quote": "Winter is coming"
|
149
|
+
}
|
150
|
+
|
151
|
+
#/got/hodor.json
|
152
|
+
{
|
153
|
+
"name": "Hodor",
|
154
|
+
"quote": "Hodor!"
|
155
|
+
}
|
156
|
+
```
|
157
|
+
|
158
|
+
Then set up a collection to access them through Middleman. A collection requires 3 keys, an `alias`, `path`, and `items`. The alias & path act just like a source, except that data will be available at `#{all}.all`. Items should be an object that responds to `#call` and returns an array of sources when given the data from the collection index. A collection for our example API:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
activate :data_source do |c|
|
162
|
+
c.root = 'http://winteriscoming.com'
|
163
|
+
c.collection = {
|
164
|
+
alias: 'got_chars',
|
165
|
+
path: '/got/index.json',
|
166
|
+
items: Proc.new { |data|
|
167
|
+
data.map do |char|
|
168
|
+
{
|
169
|
+
alias: char['name'].to_slug,
|
170
|
+
path: char['url']
|
171
|
+
}
|
172
|
+
end
|
173
|
+
}
|
174
|
+
}
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
You'll see I've used a proc to map our index into sources. The information is then accessible via the data object:
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
data.got_chars.all.map(&:name)
|
182
|
+
# => ['Eddard Stark', 'Hodor']
|
183
|
+
|
184
|
+
data.got_chars['eddard-stark'].quote
|
185
|
+
# => Winter is coming
|
186
|
+
```
|
187
|
+
|
188
|
+
|
131
189
|
# Testing
|
132
190
|
|
133
191
|
```bash
|
@@ -135,6 +193,7 @@ $ rspec
|
|
135
193
|
```
|
136
194
|
|
137
195
|
|
196
|
+
|
138
197
|
# Contributing
|
139
198
|
|
140
199
|
If there is any thing you'd like to contribute or fix, please:
|
@@ -0,0 +1,37 @@
|
|
1
|
+
set :environment, :test
|
2
|
+
set :show_exceptions, false
|
3
|
+
|
4
|
+
|
5
|
+
activate :data_source do |c|
|
6
|
+
|
7
|
+
c.root = File.join( Dir.pwd, 'remote_data' )
|
8
|
+
|
9
|
+
c.collection = {
|
10
|
+
alias: 'root',
|
11
|
+
path: 'root.json',
|
12
|
+
items: Proc.new { |data|
|
13
|
+
data.map do |d|
|
14
|
+
{
|
15
|
+
alias: d['slug'],
|
16
|
+
path: File.join('root', "#{d['slug']}.json")
|
17
|
+
}
|
18
|
+
end
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
activate :data_source do |c|
|
26
|
+
|
27
|
+
c.root = File.join( Dir.pwd, 'remote_data' )
|
28
|
+
|
29
|
+
c.collection = {
|
30
|
+
alias: 'extensionless',
|
31
|
+
path: 'extensionless/foo',
|
32
|
+
type: :json,
|
33
|
+
items: Proc.new { |d| [] }
|
34
|
+
}
|
35
|
+
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
set :environment, :test
|
2
|
+
set :show_exceptions, false
|
3
|
+
|
4
|
+
activate :data_source do |c|
|
5
|
+
|
6
|
+
c.root = File.join( Dir.pwd, 'remote_data' )
|
7
|
+
|
8
|
+
c.files = {
|
9
|
+
'nested.json' => 'mounted/remote'
|
10
|
+
}
|
11
|
+
|
12
|
+
c.sources = [
|
13
|
+
{
|
14
|
+
alias: 'mounted',
|
15
|
+
path: 'nested.json'
|
16
|
+
}
|
17
|
+
]
|
18
|
+
|
19
|
+
end
|
@@ -1,6 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
describe Middleman::DataSource::Extension do
|
1
|
+
RSpec.describe Middleman::DataSource::Extension do
|
4
2
|
|
5
3
|
it "is registered as an extension" do
|
6
4
|
expect( Middleman::Extensions.registered[:data_source] ).to eq Middleman::DataSource::Extension
|
@@ -130,4 +128,52 @@ describe Middleman::DataSource::Extension do
|
|
130
128
|
expect( remote_data ).to match_array [{"item"=>"one"},{"item"=>"two"}]
|
131
129
|
end
|
132
130
|
|
131
|
+
context "with nested alias locations" do
|
132
|
+
before :each do
|
133
|
+
Given.fixture 'nested_alias'
|
134
|
+
@mm = Middleman::Fixture.app
|
135
|
+
end
|
136
|
+
|
137
|
+
after :each do
|
138
|
+
Given.cleanup!
|
139
|
+
end
|
140
|
+
|
141
|
+
it "puts data into the nested data location as though alias was a path" do
|
142
|
+
expect( @mm.data.mounted.remote.data ).to eq 'remote'
|
143
|
+
end
|
144
|
+
|
145
|
+
it "allows for overlapping paths" do
|
146
|
+
expect( @mm.data.mounted.data ).to eq 'remote'
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
context "with collection app" do
|
153
|
+
before :each do
|
154
|
+
Given.fixture 'collection'
|
155
|
+
@mm = Middleman::Fixture.app
|
156
|
+
end
|
157
|
+
|
158
|
+
after :each do
|
159
|
+
Given.cleanup!
|
160
|
+
end
|
161
|
+
|
162
|
+
it "makes collection items available at aliases" do
|
163
|
+
expect( @mm.data.root.john.title ).to eq "John"
|
164
|
+
expect( @mm.data.root.hodor.title ).to eq "Hodor"
|
165
|
+
end
|
166
|
+
|
167
|
+
it "makes collection index available at #all" do
|
168
|
+
expect( @mm.data.root.all.map(&:to_h) ).to match_array [{ "extra" => "info",
|
169
|
+
"slug" => "hodor" },
|
170
|
+
{ "extra" => "info",
|
171
|
+
"slug" => "john" }]
|
172
|
+
end
|
173
|
+
|
174
|
+
it "allows passing an extension type" do
|
175
|
+
expect( @mm.data.extensionless.all.foo ).to eq "bar"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
133
179
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: middleman-data_source
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Sloan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: middleman
|
@@ -67,9 +67,11 @@ files:
|
|
67
67
|
- readme.md
|
68
68
|
- spec/fixtures/base/config.rb
|
69
69
|
- spec/fixtures/borrower/config.rb
|
70
|
+
- spec/fixtures/collection/config.rb
|
70
71
|
- spec/fixtures/files_as_hash/config.rb
|
71
72
|
- spec/fixtures/imediate_use/config.rb
|
72
73
|
- spec/fixtures/multiple_instances/config.rb
|
74
|
+
- spec/fixtures/nested_alias/config.rb
|
73
75
|
- spec/fixtures/unsupported_extension/config.rb
|
74
76
|
- spec/lib/middleman-data_source_spec.rb
|
75
77
|
- spec/lib/middleman/data_source/extension_spec.rb
|
@@ -98,16 +100,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
98
100
|
version: '0'
|
99
101
|
requirements: []
|
100
102
|
rubyforge_project:
|
101
|
-
rubygems_version: 2.4.
|
103
|
+
rubygems_version: 2.4.8
|
102
104
|
signing_key:
|
103
105
|
specification_version: 4
|
104
106
|
summary: Allow for loading data in middleman from remote sources
|
105
107
|
test_files:
|
106
108
|
- spec/fixtures/base/config.rb
|
107
109
|
- spec/fixtures/borrower/config.rb
|
110
|
+
- spec/fixtures/collection/config.rb
|
108
111
|
- spec/fixtures/files_as_hash/config.rb
|
109
112
|
- spec/fixtures/imediate_use/config.rb
|
110
113
|
- spec/fixtures/multiple_instances/config.rb
|
114
|
+
- spec/fixtures/nested_alias/config.rb
|
111
115
|
- spec/fixtures/unsupported_extension/config.rb
|
112
116
|
- spec/lib/middleman/data_source/extension_spec.rb
|
113
117
|
- spec/lib/middleman/data_source/version_spec.rb
|