middleman-data_source 0.6.1 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|