noumenon 0.1.7 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +19 -0
- data/README.md +7 -4
- data/features/asset_serving/{from_content_repositories.feature → from_a_repository.feature} +2 -14
- data/features/step_definitions/asset_steps.rb +2 -2
- data/features/step_definitions/generator_steps.rb +3 -1
- data/features/support/env.rb +8 -3
- data/generators/repository/assets/.gitkeep +0 -0
- data/generators/repository/{index.yml → pages/index.yml} +0 -0
- data/generators/site/config.ru +2 -2
- data/generators/theme/layouts/default.nou.html +1 -1
- data/lib/noumenon.rb +2 -1
- data/lib/noumenon/asset_repository.rb +49 -0
- data/lib/noumenon/asset_repository/file_system.rb +64 -0
- data/lib/noumenon/{repository.rb → content_repository.rb} +2 -2
- data/lib/noumenon/{repository → content_repository}/file_system.rb +9 -4
- data/lib/noumenon/core.rb +13 -2
- data/lib/noumenon/spec/theme_helpers.rb +1 -1
- data/lib/noumenon/template/core_tags.rb +1 -1
- data/lib/noumenon/version.rb +1 -1
- data/spec/noumenon/asset_repository/file_system_spec.rb +63 -0
- data/spec/noumenon/asset_repository_spec.rb +16 -0
- data/spec/noumenon/{repository → content_repository}/file_system_spec.rb +5 -37
- data/spec/noumenon/{repository_spec.rb → content_repository_spec.rb} +2 -9
- data/spec/noumenon_spec.rb +5 -5
- metadata +18 -11
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# 0.2.0
|
2
|
+
|
3
|
+
## Backwards Compatiability Broken
|
4
|
+
|
5
|
+
This version is incompatiable with the 0.1 series due to content and asset repositories being split.
|
6
|
+
|
7
|
+
## New Features
|
8
|
+
|
9
|
+
* Content and asset repositories are now two different things, largely to avoid special casing the assets
|
10
|
+
directory for file system repositories, but it should also allow more flexibility going forward.
|
11
|
+
|
12
|
+
## Bug Fixes
|
13
|
+
|
14
|
+
* Use send_file to serve assets from the content repository so that the correct metadata is provided
|
15
|
+
to allow it to be loaded in a browser.
|
16
|
+
|
17
|
+
* Use the {% theme_asset %} tag in generated themes to load the stylesheet so that changing the theme name
|
18
|
+
doesn't break the link.
|
19
|
+
|
1
20
|
# 0.1.7
|
2
21
|
|
3
22
|
## New Features
|
data/README.md
CHANGED
@@ -42,8 +42,6 @@ Assets such as images, stylesheets, and javascripts are placed in the "assets" d
|
|
42
42
|
application at http://example.org/themes/Theme Name/asset.png. The URL structure directly matches the directory structure
|
43
43
|
of your assets directory.
|
44
44
|
|
45
|
-
In the future some asset types will be served from the content repository instead, such as images embedded within a page.
|
46
|
-
|
47
45
|
#### Templates
|
48
46
|
|
49
47
|
The core of a theme is the templates it provides. Each template can list the fields that it supports, and mark some or all
|
@@ -130,8 +128,13 @@ Currently the only available content repository uses YAML files to store your co
|
|
130
128
|
and the API for content repositories is simple enough that just about any datastore could be used if you want to implement an
|
131
129
|
adapater for it.
|
132
130
|
|
133
|
-
|
134
|
-
|
131
|
+
### An Asset Repository
|
132
|
+
|
133
|
+
The asset repository is used to store arbitrary files, such as images to embed within pages.
|
134
|
+
|
135
|
+
Any uploaded assets can usually be accessed from /assets/path/to/image.jpg, although in some cases it may be quicker to access them
|
136
|
+
directly. To get the correct URL for an asset use the `{% asset /path/to/image.jpg %}` template tag, which will return the correct
|
137
|
+
URL.
|
135
138
|
|
136
139
|
### Applications
|
137
140
|
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Feature: Serving assets from the
|
1
|
+
Feature: Serving assets from the asset repository
|
2
2
|
As a user
|
3
|
-
I want to
|
3
|
+
I want to be able to upload assets to my site
|
4
4
|
So that I can attach my own images to pages
|
5
5
|
|
6
6
|
Scenario: The asset has been added
|
@@ -18,15 +18,3 @@ Feature: Serving assets from the content repository
|
|
18
18
|
Given there is no asset called "example.txt" in the asset repository
|
19
19
|
When I view "/assets/example.txt"
|
20
20
|
Then the page should return a 404 error
|
21
|
-
|
22
|
-
Scenario: Using an alternative asset repository
|
23
|
-
Given I have chosen to use a seperate asset repository
|
24
|
-
And I have uploaded this asset as "example.txt" to the asset repository
|
25
|
-
"""
|
26
|
-
Alternative repos FTW
|
27
|
-
"""
|
28
|
-
When I view "/assets/example.txt"
|
29
|
-
Then the page content should be:
|
30
|
-
"""
|
31
|
-
Alternative repos FTW
|
32
|
-
"""
|
@@ -8,11 +8,11 @@ end
|
|
8
8
|
|
9
9
|
Given /^I have chosen to use a seperate asset repository$/ do
|
10
10
|
FileUtils.mkdir_p File.join(tmp_path, "assets")
|
11
|
-
Noumenon.asset_repository = Noumenon::
|
11
|
+
Noumenon.asset_repository = Noumenon::ContentRepository::FileSystem.new(path: File.join(tmp_path, "assets"))
|
12
12
|
end
|
13
13
|
|
14
14
|
Given /^I have uploaded this asset as "([^"]*)" to the asset repository$/ do |path, string|
|
15
|
-
Noumenon.asset_repository.
|
15
|
+
Noumenon.asset_repository.put(path, string)
|
16
16
|
end
|
17
17
|
|
18
18
|
Given /^there is no asset called "([^"]*)" in the asset repository$/ do |path|
|
@@ -18,5 +18,7 @@ Then /^the directory "([^"]*)" should contain a theme$/ do |path|
|
|
18
18
|
end
|
19
19
|
|
20
20
|
Then /^the directory "([^"]*)" should contain a repository$/ do |path|
|
21
|
-
|
21
|
+
Then %Q{a directory named "#{path}/pages" should exist}
|
22
|
+
check_exact_file_content "#{path}/pages/index.yml", generator_file("repository/pages", "index.yml")
|
23
|
+
And %Q{a directory named "#{path}/assets" should exist}
|
22
24
|
end
|
data/features/support/env.rb
CHANGED
@@ -19,13 +19,17 @@ World do
|
|
19
19
|
include RSpec::Matchers
|
20
20
|
|
21
21
|
def tmp_path
|
22
|
-
File.expand_path('
|
22
|
+
File.expand_path('../../../tmp', __FILE__)
|
23
23
|
end
|
24
24
|
|
25
25
|
def content_path
|
26
26
|
File.join(tmp_path, "content")
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
|
+
def asset_path
|
30
|
+
File.join(tmp_path, "assets")
|
31
|
+
end
|
32
|
+
|
29
33
|
true
|
30
34
|
end
|
31
35
|
|
@@ -33,7 +37,8 @@ Before do
|
|
33
37
|
Noumenon.theme = create_theme(name: "Example Theme")
|
34
38
|
|
35
39
|
FileUtils.mkdir_p content_path
|
36
|
-
Noumenon.content_repository = Noumenon::
|
40
|
+
Noumenon.content_repository = Noumenon::ContentRepository::FileSystem.new(path: content_path)
|
41
|
+
Noumenon.asset_repository = Noumenon::AssetRepository::FileSystem.new(path: asset_path)
|
37
42
|
end
|
38
43
|
|
39
44
|
After do
|
File without changes
|
File without changes
|
data/generators/site/config.ru
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'bundler/setup'
|
2
1
|
require 'noumenon'
|
3
2
|
|
4
3
|
Noumenon.theme = Noumenon::Theme.load("./theme")
|
5
|
-
Noumenon.content_repository = Noumenon::
|
4
|
+
Noumenon.content_repository = Noumenon::ContentRepository::FileSystem.new(path: "./content/pages")
|
5
|
+
Noumenon.content_repository = Noumenon::AssetRepository::FileSystem.new(path: "./content/assets")
|
6
6
|
|
7
7
|
run Noumenon.server
|
data/lib/noumenon.rb
CHANGED
@@ -5,8 +5,9 @@ require 'rack/builder'
|
|
5
5
|
|
6
6
|
# @api public
|
7
7
|
module Noumenon
|
8
|
+
autoload :AssetRepository, 'noumenon/asset_repository'
|
8
9
|
autoload :Core, 'noumenon/core'
|
9
|
-
autoload :
|
10
|
+
autoload :ContentRepository, 'noumenon/content_repository'
|
10
11
|
autoload :Template, 'noumenon/template'
|
11
12
|
autoload :Theme, 'noumenon/theme'
|
12
13
|
autoload :Spec, 'noumenon/spec'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class Noumenon::AssetRepository
|
2
|
+
autoload :FileSystem, 'noumenon/asset_repository/file_system'
|
3
|
+
|
4
|
+
# Provides access to options set on initialization.
|
5
|
+
# @api public
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
# Create a new Repository instance.
|
9
|
+
#
|
10
|
+
# @param [ Hash, #each ] options A hash of options to use when configuring the repository.
|
11
|
+
# @api public
|
12
|
+
def initialize(options = {})
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
# Saves a static asset to the repository. To be saved the asset must have a file extension, to prevent
|
17
|
+
# problems with an entire directory being overridden by a single asset.
|
18
|
+
#
|
19
|
+
# @param [ String ] path The path to save the asset at.
|
20
|
+
# @param [ String ] content The contents of the asset.
|
21
|
+
# @raises [ ArgumentError ] The path did not have a file extension.
|
22
|
+
def put(path, content)
|
23
|
+
not_supported "saving assets"
|
24
|
+
end
|
25
|
+
|
26
|
+
# Retrieves a static asset from the repository. If the asset does not exist nil is returned.
|
27
|
+
#
|
28
|
+
# @param [ String ] path The path to load from.
|
29
|
+
# @return [ String, nil ] The asset's content, or nil if it does not exist.
|
30
|
+
def get(path)
|
31
|
+
not_supported "loading assets"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns a URL for the specified asset, without checking for it's existence.
|
35
|
+
#
|
36
|
+
# This is most useful for repositories that save their assets to a CDN such as S3, and allows them to be
|
37
|
+
# directly accessed from there, instead of downloaded and then retransmitted.
|
38
|
+
#
|
39
|
+
# @param [ String ] path The asset path within the repository.
|
40
|
+
# @return [ String ] The URL to use when requesting the asset.
|
41
|
+
def url_for(path)
|
42
|
+
File.join("/assets", path)
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def not_supported(action)
|
47
|
+
raise NotImplementedError.new("This repository type does not support #{action}.")
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'noumenon/asset_repository'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
# A content repository which uses YAML files within the filesystem for storage.
|
5
|
+
#
|
6
|
+
# @example The structure of a filesystem repository
|
7
|
+
# index.yml
|
8
|
+
# |- about
|
9
|
+
# |- index.yml
|
10
|
+
# |- team.yml
|
11
|
+
# |- company.yml
|
12
|
+
# contact.yml
|
13
|
+
#
|
14
|
+
# @example A piece of content
|
15
|
+
# template: team_member
|
16
|
+
# name: Jon Wood
|
17
|
+
# position: Head Honcho of Awesomeness
|
18
|
+
# bio: Jon's just awesome, we'll leave it at that.
|
19
|
+
#
|
20
|
+
# @api public
|
21
|
+
class Noumenon::AssetRepository::FileSystem < Noumenon::AssetRepository
|
22
|
+
# @param [ Hash ] options A hash of options.
|
23
|
+
# @option options [ String ] :path The path to access the repository at.
|
24
|
+
# @api public
|
25
|
+
def initialize(options = {})
|
26
|
+
unless options.key? :path
|
27
|
+
raise ArgumentError.new("You must provide a path to the asset repository: Noumenon::AssetRepository::FileSystem.new(path: '/tmp')")
|
28
|
+
end
|
29
|
+
|
30
|
+
super options
|
31
|
+
end
|
32
|
+
|
33
|
+
# Save a static asset to the repository.
|
34
|
+
#
|
35
|
+
# @see Noumenon::Repository#save_asset
|
36
|
+
# @api public
|
37
|
+
def put(path, content)
|
38
|
+
raise ArgumentError.new("Assets must have a file extension.") unless File.extname(path).size > 0
|
39
|
+
|
40
|
+
full_path = filesystem_path_for(path)
|
41
|
+
directory = File.dirname(full_path)
|
42
|
+
FileUtils.mkdir_p(directory) unless File.exist?(directory)
|
43
|
+
File.open(full_path, "w") { |f| f.write content }
|
44
|
+
end
|
45
|
+
|
46
|
+
# Retreive a static asset to the repository.
|
47
|
+
#
|
48
|
+
# @see Noumenon::Repository#get_asset
|
49
|
+
# @api public
|
50
|
+
def get(path)
|
51
|
+
return nil unless File.exist?(filesystem_path_for(path))
|
52
|
+
return nil unless File.extname(path).size > 0
|
53
|
+
File.read filesystem_path_for(path)
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_asset_path(path)
|
57
|
+
return nil unless File.extname(path).size > 0
|
58
|
+
filesystem_path_for path
|
59
|
+
end
|
60
|
+
|
61
|
+
def filesystem_path_for(path)
|
62
|
+
File.join options[:path], path
|
63
|
+
end
|
64
|
+
end
|
@@ -4,8 +4,8 @@ require 'noumenon'
|
|
4
4
|
# expected API for a repository.
|
5
5
|
#
|
6
6
|
# @api public
|
7
|
-
class Noumenon::
|
8
|
-
autoload :FileSystem, 'noumenon/
|
7
|
+
class Noumenon::ContentRepository
|
8
|
+
autoload :FileSystem, 'noumenon/content_repository/file_system'
|
9
9
|
|
10
10
|
# Provides access to options set on initialization.
|
11
11
|
# @api public
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'noumenon/
|
1
|
+
require 'noumenon/content_repository'
|
2
2
|
require 'yaml'
|
3
3
|
require 'fileutils'
|
4
4
|
|
@@ -19,13 +19,13 @@ require 'fileutils'
|
|
19
19
|
# bio: Jon's just awesome, we'll leave it at that.
|
20
20
|
#
|
21
21
|
# @api public
|
22
|
-
class Noumenon::
|
22
|
+
class Noumenon::ContentRepository::FileSystem < Noumenon::ContentRepository
|
23
23
|
# @param [ Hash ] options A hash of options.
|
24
24
|
# @option options [ String ] :path The path to access the repository at.
|
25
25
|
# @api public
|
26
26
|
def initialize(options = {})
|
27
27
|
unless options.key? :path
|
28
|
-
raise ArgumentError.new("You must provide a path to the content repository: Noumenon::
|
28
|
+
raise ArgumentError.new("You must provide a path to the content repository: Noumenon::ContentRepository::FileSystem.new(path: '/tmp')")
|
29
29
|
end
|
30
30
|
|
31
31
|
super options
|
@@ -75,7 +75,7 @@ class Noumenon::Repository::FileSystem < Noumenon::Repository
|
|
75
75
|
items.reject { |i| i.gsub(root, "").split("/").size > depth + 1 }.collect do |item|
|
76
76
|
path = item == "" ? "/" : item
|
77
77
|
|
78
|
-
# Loading
|
78
|
+
# Loading every item probably isn't scalable, but it'll do for now. We can add caching
|
79
79
|
# at a later date if needed.
|
80
80
|
page = get(path).merge({ path: path })
|
81
81
|
page[:children] = children(page[:path], depth - 1) if depth - 1 > 0
|
@@ -100,6 +100,11 @@ class Noumenon::Repository::FileSystem < Noumenon::Repository
|
|
100
100
|
return nil unless File.extname(path).size > 0
|
101
101
|
read_file File.join("assets", path)
|
102
102
|
end
|
103
|
+
|
104
|
+
def get_asset_path(path)
|
105
|
+
return nil unless File.extname(path).size > 0
|
106
|
+
repository_path "assets/#{path}"
|
107
|
+
end
|
103
108
|
|
104
109
|
private
|
105
110
|
# Return the on-disk path to a repository item.
|
data/lib/noumenon/core.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'noumenon'
|
2
2
|
require 'sinatra'
|
3
|
+
require 'rack/mime'
|
3
4
|
|
4
5
|
# The core Noumenon web application, responsible for loading content from the repository,
|
5
6
|
# and then either rendering it with the appropriate template, or passing it to the specified
|
@@ -41,11 +42,21 @@ class Noumenon::Core < Sinatra::Base
|
|
41
42
|
Noumenon.content_repository
|
42
43
|
end
|
43
44
|
|
45
|
+
# The default assets handler is incredibly naive, loading the entire asset into memory, and then
|
46
|
+
# sending it back out again. In the future asset repositories will be able to implement more sensible
|
47
|
+
# methods of sending content, such as redirecting to an S3 URL.
|
48
|
+
#
|
49
|
+
# TODO: Abstract /assets/ out to a middleware which can be implemented by repositories which
|
50
|
+
# can't just provide a URL straight up (such as MongoDB).
|
44
51
|
get "/assets/*" do |path|
|
45
|
-
asset = Noumenon.asset_repository.
|
52
|
+
asset = Noumenon.asset_repository.get(path)
|
46
53
|
halt 404, "Asset not found" unless asset
|
47
54
|
|
48
|
-
|
55
|
+
status 200
|
56
|
+
headers \
|
57
|
+
"Content-Type" => Rack::Mime.mime_type(File.extname(path)),
|
58
|
+
"Length" => asset.bytesize.to_s
|
59
|
+
body asset
|
49
60
|
end
|
50
61
|
|
51
62
|
get "*" do |path|
|
@@ -11,7 +11,7 @@ module Noumenon
|
|
11
11
|
# @return [ String ]
|
12
12
|
# @api public
|
13
13
|
def theme_path
|
14
|
-
File.
|
14
|
+
File.expand_path("../../../../tmp/example_theme", __FILE__)
|
15
15
|
end
|
16
16
|
|
17
17
|
# Create a new theme directory at #theme_path.
|
data/lib/noumenon/version.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Noumenon::AssetRepository::FileSystem do
|
4
|
+
let(:assets_path) { File.join(File.dirname(__FILE__), "..", "..", "..", "..", "tmp", "assets") }
|
5
|
+
|
6
|
+
around do |example|
|
7
|
+
FileUtils.mkdir_p assets_path
|
8
|
+
example.run
|
9
|
+
FileUtils.rm_r assets_path
|
10
|
+
end
|
11
|
+
|
12
|
+
subject do
|
13
|
+
Noumenon::AssetRepository::FileSystem.new path: assets_path
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "initialization" do
|
17
|
+
context "when no path option is provided" do
|
18
|
+
it "should raise an ArgumentError" do
|
19
|
+
lambda { Noumenon::AssetRepository::FileSystem.new }.should raise_error ArgumentError
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should provide details of the error of how to resolve the error" do
|
23
|
+
begin
|
24
|
+
Noumenon::AssetRepository::FileSystem.new
|
25
|
+
rescue ArgumentError => e
|
26
|
+
e.to_s.should == "You must provide a path to the asset repository: Noumenon::AssetRepository::FileSystem.new(path: '/tmp')"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it { should implement(:put, "/foo.txt", "foo") }
|
33
|
+
describe "saving assets" do
|
34
|
+
it "raises an ArgumentError when the path has no extension" do
|
35
|
+
lambda { subject.put("/foo", "Content") }.should raise_error(ArgumentError, "Assets must have a file extension.")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "saves the asset to the filesystem" do
|
39
|
+
lambda { subject.put("/foo.txt", "Content") }.should create_file(File.join(assets_path, "foo.txt")).with_content("Content")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "creates any neccesary parent directories" do
|
43
|
+
lambda { subject.put("/bar/foo.txt", "Content") }.should create_file(File.join(assets_path, "bar", "foo.txt"))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it { should implement(:get, "/foo.txt") }
|
48
|
+
describe "retrieving assets" do
|
49
|
+
it "returns nil if the path provided is not a file with an extension" do
|
50
|
+
subject.get("/foo").should be_nil
|
51
|
+
subject.get("/foo/").should be_nil
|
52
|
+
end
|
53
|
+
|
54
|
+
it "returns nil if the asset did not exist" do
|
55
|
+
subject.get("/foo.txt").should be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns the file's contents if ithe asset does exist" do
|
59
|
+
subject.put("/foo.txt", "Content")
|
60
|
+
subject.get("/foo.txt").should == "Content"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Noumenon::AssetRepository do
|
4
|
+
it "saves any provided on initialization" do
|
5
|
+
repo = Noumenon::AssetRepository.new(option: "set")
|
6
|
+
repo.options[:option].should == "set"
|
7
|
+
end
|
8
|
+
|
9
|
+
it { should_not implement(:put, "/example.txt", "Content").with_message("This repository type does not support saving assets.") }
|
10
|
+
it { should_not implement(:get, "/example.txt").with_message("This repository type does not support loading assets.") }
|
11
|
+
|
12
|
+
it { should implement(:url_for, "/example.txt") }
|
13
|
+
it "returns the default URL below /assets/ when requested" do
|
14
|
+
subject.url_for("/example.txt").should == "/assets/example.txt"
|
15
|
+
end
|
16
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Noumenon::
|
3
|
+
describe Noumenon::ContentRepository::FileSystem do
|
4
4
|
let(:content_path) { File.join(File.dirname(__FILE__), "..", "..", "..", "..", "tmp", "content") }
|
5
5
|
|
6
6
|
around do |example|
|
@@ -10,20 +10,20 @@ describe Noumenon::Repository::FileSystem do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
subject do
|
13
|
-
Noumenon::
|
13
|
+
Noumenon::ContentRepository::FileSystem.new path: content_path
|
14
14
|
end
|
15
15
|
|
16
16
|
describe "initialization" do
|
17
17
|
context "when no path option is provided" do
|
18
18
|
it "should raise an ArgumentError" do
|
19
|
-
lambda { Noumenon::
|
19
|
+
lambda { Noumenon::ContentRepository::FileSystem.new }.should raise_error ArgumentError
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should provide details of the error of how to resolve the error" do
|
23
23
|
begin
|
24
|
-
Noumenon::
|
24
|
+
Noumenon::ContentRepository::FileSystem.new
|
25
25
|
rescue ArgumentError => e
|
26
|
-
e.to_s.should == "You must provide a path to the content repository: Noumenon::
|
26
|
+
e.to_s.should == "You must provide a path to the content repository: Noumenon::ContentRepository::FileSystem.new(path: '/tmp')"
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -173,36 +173,4 @@ describe Noumenon::Repository::FileSystem do
|
|
173
173
|
end
|
174
174
|
end
|
175
175
|
end
|
176
|
-
|
177
|
-
it { should implement(:save_asset, "/foo.txt", "foo") }
|
178
|
-
describe "saving assets" do
|
179
|
-
it "raises an ArgumentError when the path has no extension" do
|
180
|
-
lambda { subject.save_asset("/foo", "Content") }.should raise_error(ArgumentError, "Assets must have a file extension.")
|
181
|
-
end
|
182
|
-
|
183
|
-
it "saves the asset to the filesystem" do
|
184
|
-
lambda { subject.save_asset("/foo.txt", "Content") }.should create_file(File.join(content_path, "assets", "foo.txt")).with_content("Content")
|
185
|
-
end
|
186
|
-
|
187
|
-
it "creates any neccesary parent directories" do
|
188
|
-
lambda { subject.save_asset("/bar/foo.txt", "Content") }.should create_file(File.join(content_path, "assets", "bar", "foo.txt"))
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
it { should implement(:get_asset, "/foo.txt") }
|
193
|
-
describe "retrieving assets" do
|
194
|
-
it "returns nil if the path provided is not a file with an extension" do
|
195
|
-
subject.get_asset("/foo").should be_nil
|
196
|
-
subject.get_asset("/foo/").should be_nil
|
197
|
-
end
|
198
|
-
|
199
|
-
it "returns nil if the asset did not exist" do
|
200
|
-
subject.get_asset("/foo.txt").should be_nil
|
201
|
-
end
|
202
|
-
|
203
|
-
it "returns the file's contents if ithe asset does exist" do
|
204
|
-
subject.save_asset("/foo.txt", "Content")
|
205
|
-
subject.get_asset("/foo.txt").should == "Content"
|
206
|
-
end
|
207
|
-
end
|
208
176
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Noumenon::
|
3
|
+
describe Noumenon::ContentRepository do
|
4
4
|
describe "initialization" do
|
5
5
|
it "allows access to any provided options in #options" do
|
6
|
-
repo = Noumenon::
|
6
|
+
repo = Noumenon::ContentRepository.new(foo: "bar")
|
7
7
|
repo.options[:foo].should == "bar"
|
8
8
|
end
|
9
9
|
end
|
@@ -11,11 +11,4 @@ describe Noumenon::Repository do
|
|
11
11
|
it { should_not implement(:put, "/", foo: "bar").with_message("This repository type does not support updating it's contents.") }
|
12
12
|
it { should_not implement(:get, "/").with_message("This repository type does not support reading it's contents.") }
|
13
13
|
it { should_not implement(:children).with_message("This repository type does not support listing children from a path.") }
|
14
|
-
it { should_not implement(:save_asset, "/example.txt", "Content").with_message("This repository type does not support saving assets.") }
|
15
|
-
it { should_not implement(:get_asset, "/example.txt").with_message("This repository type does not support loading assets.") }
|
16
|
-
|
17
|
-
it { should implement(:asset_url, "/example.txt") }
|
18
|
-
it "returns the default URL below /assets/ when requested" do
|
19
|
-
subject.asset_url("/example.txt").should == "/assets/example.txt"
|
20
|
-
end
|
21
14
|
end
|
data/spec/noumenon_spec.rb
CHANGED
@@ -3,11 +3,11 @@ require 'spec_helper'
|
|
3
3
|
describe Noumenon do
|
4
4
|
describe "accessing the content repository" do
|
5
5
|
it "can be set" do
|
6
|
-
Noumenon.content_repository = Noumenon::
|
6
|
+
Noumenon.content_repository = Noumenon::ContentRepository.new
|
7
7
|
end
|
8
8
|
|
9
9
|
it "can be retrieved" do
|
10
|
-
repo = Noumenon::
|
10
|
+
repo = Noumenon::ContentRepository.new
|
11
11
|
Noumenon.content_repository = repo
|
12
12
|
Noumenon.content_repository.should == repo
|
13
13
|
end
|
@@ -15,13 +15,13 @@ describe Noumenon do
|
|
15
15
|
|
16
16
|
describe "accessing the asset repository" do
|
17
17
|
it "returns the content repository if it has not been set" do
|
18
|
-
Noumenon.content_repository = Noumenon::
|
18
|
+
Noumenon.content_repository = Noumenon::ContentRepository.new
|
19
19
|
Noumenon.asset_repository.should === Noumenon.content_repository
|
20
20
|
end
|
21
21
|
|
22
22
|
it "returns the set asset repository if one has been set" do
|
23
|
-
content = Noumenon::
|
24
|
-
assets = Noumenon::
|
23
|
+
content = Noumenon::ContentRepository.new
|
24
|
+
assets = Noumenon::ContentRepository.new
|
25
25
|
|
26
26
|
Noumenon.content_repository = content
|
27
27
|
Noumenon.asset_repository = assets
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: noumenon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.2.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Jon Wood
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-06-
|
13
|
+
date: 2011-06-08 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -176,7 +176,7 @@ files:
|
|
176
176
|
- README.md
|
177
177
|
- Rakefile
|
178
178
|
- bin/noumenon
|
179
|
-
- features/asset_serving/
|
179
|
+
- features/asset_serving/from_a_repository.feature
|
180
180
|
- features/asset_serving/from_themes.feature
|
181
181
|
- features/generator/site_generator.feature
|
182
182
|
- features/mounted_applications.feature
|
@@ -197,7 +197,8 @@ files:
|
|
197
197
|
- features/template_tags/content_from.feature
|
198
198
|
- features/template_tags/nav_menu.feature
|
199
199
|
- features/template_tags/textilize.feature
|
200
|
-
- generators/repository/
|
200
|
+
- generators/repository/assets/.gitkeep
|
201
|
+
- generators/repository/pages/index.yml
|
201
202
|
- generators/site/Gemfile
|
202
203
|
- generators/site/config.ru
|
203
204
|
- generators/theme/assets/style.css
|
@@ -205,10 +206,12 @@ files:
|
|
205
206
|
- generators/theme/templates/default.nou.html
|
206
207
|
- generators/theme/theme.yml
|
207
208
|
- lib/noumenon.rb
|
209
|
+
- lib/noumenon/asset_repository.rb
|
210
|
+
- lib/noumenon/asset_repository/file_system.rb
|
208
211
|
- lib/noumenon/cli.rb
|
212
|
+
- lib/noumenon/content_repository.rb
|
213
|
+
- lib/noumenon/content_repository/file_system.rb
|
209
214
|
- lib/noumenon/core.rb
|
210
|
-
- lib/noumenon/repository.rb
|
211
|
-
- lib/noumenon/repository/file_system.rb
|
212
215
|
- lib/noumenon/spec.rb
|
213
216
|
- lib/noumenon/spec/example_app.rb
|
214
217
|
- lib/noumenon/spec/example_tags.rb
|
@@ -220,8 +223,10 @@ files:
|
|
220
223
|
- lib/noumenon/theme/assets_middleware.rb
|
221
224
|
- lib/noumenon/version.rb
|
222
225
|
- noumenon.gemspec
|
223
|
-
- spec/noumenon/
|
224
|
-
- spec/noumenon/
|
226
|
+
- spec/noumenon/asset_repository/file_system_spec.rb
|
227
|
+
- spec/noumenon/asset_repository_spec.rb
|
228
|
+
- spec/noumenon/content_repository/file_system_spec.rb
|
229
|
+
- spec/noumenon/content_repository_spec.rb
|
225
230
|
- spec/noumenon/template_spec.rb
|
226
231
|
- spec/noumenon/theme_spec.rb
|
227
232
|
- spec/noumenon_spec.rb
|
@@ -259,7 +264,7 @@ signing_key:
|
|
259
264
|
specification_version: 3
|
260
265
|
summary: A flexible content management system.
|
261
266
|
test_files:
|
262
|
-
- features/asset_serving/
|
267
|
+
- features/asset_serving/from_a_repository.feature
|
263
268
|
- features/asset_serving/from_themes.feature
|
264
269
|
- features/generator/site_generator.feature
|
265
270
|
- features/mounted_applications.feature
|
@@ -280,8 +285,10 @@ test_files:
|
|
280
285
|
- features/template_tags/content_from.feature
|
281
286
|
- features/template_tags/nav_menu.feature
|
282
287
|
- features/template_tags/textilize.feature
|
283
|
-
- spec/noumenon/
|
284
|
-
- spec/noumenon/
|
288
|
+
- spec/noumenon/asset_repository/file_system_spec.rb
|
289
|
+
- spec/noumenon/asset_repository_spec.rb
|
290
|
+
- spec/noumenon/content_repository/file_system_spec.rb
|
291
|
+
- spec/noumenon/content_repository_spec.rb
|
285
292
|
- spec/noumenon/template_spec.rb
|
286
293
|
- spec/noumenon/theme_spec.rb
|
287
294
|
- spec/noumenon_spec.rb
|