brief 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/README.md +66 -127
- data/TUTORIAL.md +146 -0
- data/examples/blog/brief.rb +2 -28
- data/lib/brief.rb +8 -0
- data/lib/brief/document_mapper.rb +1 -0
- data/lib/brief/model.rb +29 -28
- data/lib/brief/model/definition.rb +22 -9
- data/lib/brief/model/persistence.rb +7 -0
- data/lib/brief/util.rb +36 -0
- data/lib/brief/version.rb +1 -1
- data/spec/fixtures/example/brief.rb +5 -5
- data/spec/fixtures/example/models/epic.rb +7 -1
- data/spec/lib/brief/model_spec.rb +21 -0
- data/spec/lib/brief/persistence_spec.rb +9 -0
- metadata +7 -2
- data/lib/brief/cli/publish.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ea25b279da5166d726a9463be10836ab9b6d7bb
|
4
|
+
data.tar.gz: e52d0270a01c924196c8ab59250df0973320589d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 250b23f611f467ec9731114557f84d8bf24e498642849eab59dcb79f7a7c1790ea33b8f734a3017f515ad025caf5353625b0ec972c7e016eb7682eafe9aa063a
|
7
|
+
data.tar.gz: 88a4250edb54523fdb51f18700a149831a5835d031cf67fbc49c142bb6d3abeccec9eff48c32df99f9ded979330c9223b7f7934819b87e4f79f33a67292b2e3e
|
data/.gitignore
ADDED
data/README.md
CHANGED
@@ -2,171 +2,110 @@
|
|
2
2
|
|
3
3
|
An ActiveRecord style layer on top of a folder of markdown files.
|
4
4
|
|
5
|
-
|
5
|
+
Treat your markdown documents as active models, run actions on them,
|
6
|
+
convert them into HTML, extract fragments of HTML, combine it all in
|
7
|
+
whatever interesting way you can think of.
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
which contains folders with different document types.
|
9
|
+
The end result is a really neat way of being able to use the words that you write
|
10
|
+
to power all sorts of applications.
|
10
11
|
|
11
|
-
|
12
|
-
which can be specified in a YAML frontmatter preamble at the very top of
|
13
|
-
each document.
|
12
|
+
**No more writing dead documents!**
|
14
13
|
|
15
|
-
|
16
|
-
attributes as CSS selectors. For example, the very first h1 heading
|
17
|
-
could be the title for your document, and the corresponding model for
|
18
|
-
that document would have a `title` method which returned its value.
|
14
|
+
### Documents as Models
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
**Think of it as an ActiveRecord like layer on top of a folder of
|
25
|
-
Markdown files**. Brief turns static text into a 'living' data object.
|
26
|
-
|
27
|
-
## Getting started
|
28
|
-
|
29
|
-
```bash
|
30
|
-
gem install brief
|
31
|
-
mkdir blog
|
32
|
-
cd blog
|
33
|
-
brief init
|
34
|
-
```
|
35
|
-
|
36
|
-
This will create a new folder for your briefcase, along with the
|
37
|
-
following config file and structure.
|
38
|
-
|
39
|
-
```
|
40
|
-
- docs/
|
41
|
-
- an-introduction-to-brief.html.md
|
42
|
-
- models/
|
43
|
-
- brief.rb
|
44
|
-
```
|
45
|
-
|
46
|
-
The config file will look like:
|
16
|
+
Brief lets you treat an individual markdown file as if it were a model,
|
17
|
+
complete with validations, callbacks, and methods you can run. You can
|
18
|
+
define a `Post` model for all of the files in a 'posts' folder and
|
19
|
+
define actions like 'publish' on them.
|
47
20
|
|
48
21
|
```ruby
|
49
|
-
|
50
|
-
# configuration options for this briefcase
|
51
|
-
config do
|
52
|
-
set(:models_path => Pathname(__FILE__).parent.join("models"))
|
53
|
-
end
|
54
|
-
|
55
|
-
# define a Post model
|
56
|
-
define("Post") do
|
57
|
-
|
58
|
-
# the post model will have YAML frontmatter
|
59
|
-
# with values for 'status' and 'date'
|
22
|
+
define "Post" do
|
60
23
|
meta do
|
61
24
|
status
|
62
|
-
|
25
|
+
tags Array
|
63
26
|
end
|
64
|
-
|
65
|
-
# the post model will have a 'title' method which returns the text
|
66
|
-
# from the first h1 heading
|
27
|
+
|
67
28
|
content do
|
68
|
-
title "h1"
|
29
|
+
has_one :title, "h1"
|
69
30
|
has_many :subheadings, "h2"
|
70
31
|
end
|
71
32
|
|
72
|
-
|
73
|
-
def publish
|
74
|
-
|
33
|
+
actions do
|
34
|
+
def publish
|
35
|
+
update_attributes(:status => "published")
|
75
36
|
end
|
76
37
|
end
|
77
|
-
|
78
|
-
# Whenever we call post.save() and the status attribute changes
|
79
|
-
# from draft to published, do something with the model
|
80
|
-
on_status_change(:from => "draft", :to => "published") do |model|
|
81
|
-
# Do Something
|
82
|
-
# mail_service.send_html_email_campaign(model.to_html)
|
83
|
-
end
|
84
38
|
end
|
39
|
+
```
|
85
40
|
|
86
|
-
# this creates a custom command in the brief CLI tool
|
87
|
-
#
|
88
|
-
# so when you run:
|
89
|
-
#
|
90
|
-
# brief publish posts /path/to/*.html.md.
|
91
|
-
#
|
92
|
-
# the brief CLI will find models for the post files you reference,
|
93
|
-
# and call whatever methods you want.
|
94
41
|
|
95
|
-
|
42
|
+
### Model attributes derived from YAML frontmatter
|
96
43
|
|
97
|
-
|
44
|
+
Models can get their attributes from headers on the document, aka YAML frontmatter.
|
98
45
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
46
|
+
```markdown
|
47
|
+
---
|
48
|
+
status: draft
|
49
|
+
tags:
|
50
|
+
- demo
|
51
|
+
- sample
|
52
|
+
---
|
53
|
+
|
54
|
+
# Title
|
55
|
+
|
56
|
+
## Section One
|
57
|
+
## Section Two
|
103
58
|
```
|
104
59
|
|
105
|
-
|
60
|
+
which will let you use it like such:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
post = Brief::Document.new(/path/to/doc.html.md)
|
64
|
+
|
65
|
+
post.status #=> "draft"
|
66
|
+
post.title #=> "Title"
|
67
|
+
post.tags #=> ['demo','sample']
|
68
|
+
```
|
106
69
|
|
107
|
-
|
108
|
-
software. A Blueprint is a collection of related documents that are
|
109
|
-
used in the software architecture and design process, as well as in the
|
110
|
-
day to day writing that takes place while building the software itself.
|
70
|
+
#### Model attributes derived from the document structure
|
111
71
|
|
112
|
-
|
72
|
+
Models can also get their attributes from the structure itself.
|
113
73
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
- user stories
|
119
|
-
- integration tests
|
120
|
-
- release notes
|
121
|
-
- wireframe annotations
|
74
|
+
```ruby
|
75
|
+
post.title #=> "Title"
|
76
|
+
post.subheadings #=> ["Section One", "Section Two"]
|
77
|
+
```
|
122
78
|
|
123
|
-
|
124
|
-
projects we are working on, and by treating our writing as a structured
|
125
|
-
exercise we are able to do a lot more things with it than just read it.
|
79
|
+
### Querying Documents
|
126
80
|
|
127
|
-
|
81
|
+
Given a big folder of markdown files with attributes, we can query them:
|
128
82
|
|
129
83
|
```
|
130
|
-
|
84
|
+
posts = briefcase.posts.where(:status => "published")
|
85
|
+
posts.map(&:title) #=> ['Title']
|
131
86
|
```
|
132
87
|
|
133
|
-
|
88
|
+
This functionality is based on https://github.com/ralph/document_mapper,
|
89
|
+
and similar to middleman.
|
134
90
|
|
135
|
-
|
136
|
-
# brief.rb
|
91
|
+
### Document Actions
|
137
92
|
|
138
|
-
|
139
|
-
meta do
|
140
|
-
status
|
141
|
-
end
|
93
|
+
By defining actions on documents like so:
|
142
94
|
|
143
|
-
|
144
|
-
title "h1"
|
145
|
-
paragraph "p:first-child"
|
146
|
-
persona "p:first-child strong:1st-child"
|
147
|
-
behavior "p:first-child strong:2nd-child"
|
148
|
-
goal "p:first-child strong:3rd-child"
|
149
|
-
end
|
95
|
+
```ruby
|
150
96
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
97
|
+
define "Post" do
|
98
|
+
actions do
|
99
|
+
def publish
|
100
|
+
# DO Something
|
155
101
|
end
|
156
102
|
end
|
157
103
|
end
|
104
|
+
```
|
158
105
|
|
159
|
-
|
160
|
-
|
106
|
+
you can either call that method as you normally would, or you can run
|
107
|
+
that action from the command line:
|
161
108
|
|
162
|
-
|
163
|
-
|
164
|
-
user_story.status = "published"
|
165
|
-
user_story.save
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
109
|
+
```bash
|
110
|
+
brief publish posts ./posts/*.html.md
|
169
111
|
```
|
170
|
-
|
171
|
-
As you can see, Brief can be a way to make your Markdown writing efforts
|
172
|
-
much more productive.
|
data/TUTORIAL.md
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
## Tutorial
|
2
|
+
|
3
|
+
```bash
|
4
|
+
gem install brief
|
5
|
+
mkdir blog
|
6
|
+
cd blog
|
7
|
+
brief init
|
8
|
+
```
|
9
|
+
|
10
|
+
This will create a new folder for your briefcase, along with the
|
11
|
+
following config file and structure.
|
12
|
+
|
13
|
+
```
|
14
|
+
- docs/
|
15
|
+
- an-introduction-to-brief.html.md
|
16
|
+
- models/
|
17
|
+
- brief.rb
|
18
|
+
```
|
19
|
+
|
20
|
+
The config file will look like:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
|
24
|
+
# configuration options for this briefcase
|
25
|
+
config do
|
26
|
+
set(:models_path => Pathname(__FILE__).parent.join("models"))
|
27
|
+
end
|
28
|
+
|
29
|
+
# define a Post model
|
30
|
+
define("Post") do
|
31
|
+
|
32
|
+
# the post model will have YAML frontmatter
|
33
|
+
# with values for 'status' and 'date'
|
34
|
+
meta do
|
35
|
+
status
|
36
|
+
date DateTime, :default => lambda {|post, attr| post.document.created_at }
|
37
|
+
end
|
38
|
+
|
39
|
+
# the post model will have a 'title' method which returns the text
|
40
|
+
# from the first h1 heading
|
41
|
+
content do
|
42
|
+
title "h1"
|
43
|
+
has_many :subheadings, "h2"
|
44
|
+
end
|
45
|
+
|
46
|
+
helpers do
|
47
|
+
def publish(options={})
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Whenever we call post.save() and the status attribute changes
|
53
|
+
# from draft to published, do something with the model
|
54
|
+
on_status_change(:from => "draft", :to => "published") do |model|
|
55
|
+
# Do Something
|
56
|
+
# mail_service.send_html_email_campaign(model.to_html)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# this creates a custom command in the brief CLI tool
|
61
|
+
#
|
62
|
+
# so when you run:
|
63
|
+
#
|
64
|
+
# brief publish posts /path/to/*.html.md.
|
65
|
+
#
|
66
|
+
# the brief CLI will find models for the post files you reference,
|
67
|
+
# and call whatever methods you want.
|
68
|
+
|
69
|
+
action "publish posts" do |briefcase, models, options|
|
70
|
+
|
71
|
+
say "== Publishing #{ models.length } posts"
|
72
|
+
|
73
|
+
Array(models).each do |post|
|
74
|
+
post.publish()
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
### Real World Application
|
80
|
+
|
81
|
+
My company Architects.io, Inc. uses brief to power our Blueprint
|
82
|
+
software. A Blueprint is a collection of related documents that are
|
83
|
+
used in the software architecture and design process, as well as in the
|
84
|
+
day to day writing that takes place while building the software itself.
|
85
|
+
|
86
|
+
This includes things like:
|
87
|
+
|
88
|
+
- daily standups
|
89
|
+
- bug reports
|
90
|
+
- code reviews
|
91
|
+
- feature epics
|
92
|
+
- user stories
|
93
|
+
- integration tests
|
94
|
+
- release notes
|
95
|
+
- wireframe annotations
|
96
|
+
|
97
|
+
All of these things are simple markdown files. They live in the
|
98
|
+
projects we are working on, and by treating our writing as a structured
|
99
|
+
exercise we are able to do a lot more things with it than just read it.
|
100
|
+
|
101
|
+
For example we can do:
|
102
|
+
|
103
|
+
```
|
104
|
+
brief publish user stories /path/to/user-stories/*.html.md
|
105
|
+
```
|
106
|
+
|
107
|
+
which is implemented by:
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
# brief.rb
|
111
|
+
|
112
|
+
define "User Story" do
|
113
|
+
meta do
|
114
|
+
status
|
115
|
+
end
|
116
|
+
|
117
|
+
content do
|
118
|
+
title "h1"
|
119
|
+
paragraph "p:first-child"
|
120
|
+
persona "p:first-child strong:1st-child"
|
121
|
+
behavior "p:first-child strong:2nd-child"
|
122
|
+
goal "p:first-child strong:3rd-child"
|
123
|
+
end
|
124
|
+
|
125
|
+
helpers do
|
126
|
+
def create_github_issue
|
127
|
+
issue = github.create_issue(title: title, body: document.content)
|
128
|
+
set(issue_number: issue.number)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
action "publish user stories" do |briefcase, models, options|
|
134
|
+
user_stories = models
|
135
|
+
|
136
|
+
user_stories.each do |user_story|
|
137
|
+
if user_story.create_github_issue()
|
138
|
+
user_story.status = "published"
|
139
|
+
user_story.save
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
```
|
144
|
+
|
145
|
+
As you can see, Brief can be a way to make your Markdown writing efforts
|
146
|
+
much more productive.
|
data/examples/blog/brief.rb
CHANGED
@@ -20,35 +20,9 @@ define("Post") do
|
|
20
20
|
has_many :subheadings, "h2"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
actions do
|
24
24
|
def publish(options={})
|
25
|
-
|
25
|
+
puts "The publish action"
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
29
|
-
# Whenever we call post.save() and the status attribute changes
|
30
|
-
# from draft to published, do something with the model
|
31
|
-
on_status_change(:from => "draft", :to => "published") do |model|
|
32
|
-
# Do Something
|
33
|
-
# mail_service.send_html_email_campaign(model.to_html)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# this creates a custom command in the brief CLI tool
|
38
|
-
#
|
39
|
-
# so when you run:
|
40
|
-
#
|
41
|
-
# brief publish posts /path/to/*.html.md.
|
42
|
-
#
|
43
|
-
# the brief CLI will find models for the post files you reference,
|
44
|
-
# and call whatever methods you want.
|
45
|
-
|
46
|
-
action "publish posts" do |briefcase, models, options|
|
47
|
-
|
48
|
-
say "== Publishing #{ models.length } posts"
|
49
|
-
|
50
|
-
Array(models).each do |post|
|
51
|
-
post.publish()
|
52
|
-
end
|
53
28
|
end
|
54
|
-
|
data/lib/brief.rb
CHANGED
@@ -28,6 +28,13 @@ module Brief
|
|
28
28
|
|
29
29
|
def self.load_commands
|
30
30
|
Dir[gem_root.join("brief","cli","**/*.rb")].each {|f| require(f) }
|
31
|
+
|
32
|
+
# the instance methods which get defined with the helper
|
33
|
+
Brief::Model.classes.each do |klass|
|
34
|
+
Array(klass.defined_actions).uniq.each do |action|
|
35
|
+
Brief::Util.create_method_dispatcher_command_for(action, klass)
|
36
|
+
end
|
37
|
+
end
|
31
38
|
end
|
32
39
|
|
33
40
|
def self.load_models(from_folder=nil)
|
@@ -37,6 +44,7 @@ end
|
|
37
44
|
|
38
45
|
require "brief/core_ext"
|
39
46
|
require "brief/version"
|
47
|
+
require "brief/util"
|
40
48
|
require "brief/configuration"
|
41
49
|
require "brief/document/rendering"
|
42
50
|
require "brief/document/front_matter"
|
data/lib/brief/model.rb
CHANGED
@@ -13,9 +13,10 @@ module Brief
|
|
13
13
|
include AccessorMethods
|
14
14
|
include Persistence
|
15
15
|
|
16
|
-
class_attribute :models, :after_initialization_hooks, :
|
16
|
+
class_attribute :models, :after_initialization_hooks, :defined_actions
|
17
17
|
|
18
18
|
self.models = Array(self.models).to_set
|
19
|
+
self.defined_actions = Array(self.defined_actions).to_set
|
19
20
|
|
20
21
|
class << self
|
21
22
|
include Enumerable
|
@@ -69,21 +70,7 @@ module Brief
|
|
69
70
|
|
70
71
|
def self.finalize
|
71
72
|
Virtus.finalize
|
72
|
-
|
73
|
-
classes.each do |klass|
|
74
|
-
klass.name ||= klass.to_s.split('::').last.humanize
|
75
|
-
klass.type_alias ||= klass.name.parameterize.gsub(/-/,'_')
|
76
|
-
|
77
|
-
klass.attribute_set.map(&:name).each do |attr|
|
78
|
-
klass.define_singleton_method("find_by_#{ attr }") do |value|
|
79
|
-
where(attr => value).first
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
klass.definition.apply_config
|
84
|
-
end
|
85
|
-
|
86
|
-
Brief::Repository.define_document_finder_methods
|
73
|
+
classes.each(&:finalize)
|
87
74
|
end
|
88
75
|
|
89
76
|
def ==(other)
|
@@ -95,24 +82,35 @@ module Brief
|
|
95
82
|
end
|
96
83
|
|
97
84
|
module ClassMethods
|
98
|
-
def
|
99
|
-
|
85
|
+
def has_actions?
|
86
|
+
definition.has_actions?
|
100
87
|
end
|
101
88
|
|
102
|
-
def
|
103
|
-
|
104
|
-
|
89
|
+
def finalize
|
90
|
+
klass = self
|
91
|
+
|
92
|
+
klass.name ||= klass.to_s.split('::').last.humanize
|
93
|
+
klass.type_alias ||= klass.name.parameterize.gsub(/-/,'_')
|
94
|
+
|
95
|
+
klass.attribute_set.map(&:name).each do |attr|
|
96
|
+
unless klass.method_defined?("find_by_#{ attr }")
|
97
|
+
klass.define_singleton_method("find_by_#{ attr }") do |value|
|
98
|
+
where(attr => value).first
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
klass.definition.apply_config
|
105
104
|
|
106
|
-
|
107
|
-
definition.send(:meta, options, &block)
|
105
|
+
Brief::Repository.define_document_finder_methods
|
108
106
|
end
|
109
107
|
|
110
|
-
def
|
111
|
-
|
108
|
+
def where(*args, &block)
|
109
|
+
Brief::DocumentMapper::Query.new(self).send(:where, *args)
|
112
110
|
end
|
113
111
|
|
114
|
-
def
|
115
|
-
|
112
|
+
def each(*args, &block)
|
113
|
+
Array(self.models).send(:each, *args, &block)
|
116
114
|
end
|
117
115
|
|
118
116
|
def after_initialize(&block)
|
@@ -144,7 +142,10 @@ module Brief
|
|
144
142
|
end
|
145
143
|
|
146
144
|
def method_missing(meth, *args, &block)
|
147
|
-
if meth.to_s
|
145
|
+
if %w(meta content actions helpers).include?(meth.to_s)
|
146
|
+
definition.send(meth, &block)
|
147
|
+
finalize
|
148
|
+
elsif meth.to_s.match(/^on_(.*)_change$/)
|
148
149
|
create_change_handler($1, *args, &block)
|
149
150
|
else
|
150
151
|
super
|
@@ -27,7 +27,7 @@ module Brief
|
|
27
27
|
create_model_class.tap do |k|
|
28
28
|
k.send(:include, Brief::Model)
|
29
29
|
|
30
|
-
k.definition
|
30
|
+
k.definition ||= definition
|
31
31
|
|
32
32
|
k.name ||= name
|
33
33
|
k.type_alias ||= type_alias
|
@@ -40,21 +40,22 @@ module Brief
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def apply_config
|
43
|
+
# define a virtus attribute mapping
|
43
44
|
metadata_schema.values.each do |settings|
|
44
|
-
if model_class.nil?
|
45
|
-
binding.pry
|
46
|
-
end
|
47
|
-
|
48
45
|
model_class.send(:attribute, *(settings[:args]))
|
49
46
|
end
|
50
47
|
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
# defined helpers adds an anonymous module include
|
49
|
+
Array(self.defined_helpers).each {|mod| model_class.send(:include, mod) }
|
50
|
+
|
51
|
+
model_class.defined_actions += Array(self.defined_actions)
|
52
|
+
true
|
54
53
|
end
|
55
54
|
|
56
55
|
def create_model_class
|
57
|
-
model_namespace.
|
56
|
+
unless (model_namespace.const_get(type_alias.camelize) rescue nil)
|
57
|
+
model_namespace.const_set(type_alias.camelize, Class.new)
|
58
|
+
end
|
58
59
|
end
|
59
60
|
|
60
61
|
def model_class
|
@@ -75,6 +76,18 @@ module Brief
|
|
75
76
|
instance_eval(&block)
|
76
77
|
end
|
77
78
|
|
79
|
+
def has_actions?
|
80
|
+
!@defined_actions.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
def actions(&block)
|
84
|
+
helpers(&block)
|
85
|
+
end
|
86
|
+
|
87
|
+
def defined_actions
|
88
|
+
Array(defined_helpers).map(&:instance_methods).flatten
|
89
|
+
end
|
90
|
+
|
78
91
|
def helpers(&block)
|
79
92
|
self.defined_helpers ||= []
|
80
93
|
|
data/lib/brief/util.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Brief::Util
|
2
|
+
def self.create_method_dispatcher_command_for(action, klass)
|
3
|
+
identifier = "#{ action } #{ klass.type_alias.to_s.pluralize }"
|
4
|
+
|
5
|
+
Object.class.class_eval do
|
6
|
+
command "#{identifier}" do |c|
|
7
|
+
c.syntax = "brief #{identifier}"
|
8
|
+
c.description = "run the #{identifier} command"
|
9
|
+
|
10
|
+
c.action do |args, opts|
|
11
|
+
briefcase = Brief.case
|
12
|
+
|
13
|
+
path_args = args.select {|arg| arg.is_a?(String) && arg.match(/\.md$/) }
|
14
|
+
|
15
|
+
path_args.select! do |arg|
|
16
|
+
path = briefcase.repository.root.join(arg)
|
17
|
+
path.exist?
|
18
|
+
end
|
19
|
+
|
20
|
+
path_args.map! {|p| briefcase.repository.root.join(p) }
|
21
|
+
|
22
|
+
models = path_args.map {|path| Brief::Document.new(path) }.map(&:to_model)
|
23
|
+
|
24
|
+
if models.empty?
|
25
|
+
model_finder = c.name.to_s.split(' ').last
|
26
|
+
models = briefcase.send(model_finder)
|
27
|
+
end
|
28
|
+
|
29
|
+
models.each do |model|
|
30
|
+
model.send(action)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end rescue nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/brief/version.rb
CHANGED
@@ -15,13 +15,13 @@ define "User Story" do
|
|
15
15
|
goal "p strong:third-child"
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
actions do
|
19
19
|
def defined_helper_method
|
20
20
|
true
|
21
21
|
end
|
22
|
-
end
|
23
|
-
end
|
24
22
|
|
25
|
-
|
26
|
-
|
23
|
+
def custom_action
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
27
|
end
|
@@ -2,7 +2,8 @@ class Brief::Epic
|
|
2
2
|
include Brief::Model
|
3
3
|
|
4
4
|
meta do
|
5
|
-
title
|
5
|
+
title
|
6
|
+
subheading
|
6
7
|
status String, :in => %w(draft published)
|
7
8
|
end
|
8
9
|
|
@@ -13,4 +14,9 @@ class Brief::Epic
|
|
13
14
|
has_many :user_stories, "h2" => "title", "p:first-child" => "paragraph"
|
14
15
|
end
|
15
16
|
end
|
17
|
+
|
18
|
+
actions do
|
19
|
+
def custom_action
|
20
|
+
end
|
21
|
+
end
|
16
22
|
end
|
@@ -31,6 +31,11 @@ describe "The Brief Model" do
|
|
31
31
|
set = Brief::Model::UserStory.attribute_set.map(&:name)
|
32
32
|
expect(set).to include(:title, :status, :epic_title)
|
33
33
|
end
|
34
|
+
|
35
|
+
it "has attribute setters" do
|
36
|
+
story = Brief::Model::UserStory.new
|
37
|
+
expect(story).to respond_to(:title=)
|
38
|
+
end
|
34
39
|
end
|
35
40
|
|
36
41
|
context "Class Definitions" do
|
@@ -55,6 +60,12 @@ describe "The Brief Model" do
|
|
55
60
|
set = Brief::Epic.attribute_set.map(&:name)
|
56
61
|
expect(set).to include(:path, :document, :title, :status)
|
57
62
|
end
|
63
|
+
|
64
|
+
it "has attribute setters" do
|
65
|
+
epic = Brief::Epic.new
|
66
|
+
expect(epic).to respond_to(:title=)
|
67
|
+
expect(epic).to respond_to(:subheading=)
|
68
|
+
end
|
58
69
|
end
|
59
70
|
|
60
71
|
context "Briefcase Finders" do
|
@@ -81,4 +92,14 @@ describe "The Brief Model" do
|
|
81
92
|
expect(epic.extracted.title).to eq("Blueprint Epic Example")
|
82
93
|
end
|
83
94
|
end
|
95
|
+
|
96
|
+
context "Actions and Helpers" do
|
97
|
+
it "uses the actions block to define CLI dispatchers" do
|
98
|
+
expect(epic.class.defined_actions).to include(:custom_action)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "users the actions block to define CLI dispatchers (dsl)" do
|
102
|
+
expect(user_story.class.defined_actions).to include(:custom_action)
|
103
|
+
end
|
104
|
+
end
|
84
105
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brief
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Soeder
|
@@ -215,11 +215,13 @@ executables:
|
|
215
215
|
extensions: []
|
216
216
|
extra_rdoc_files: []
|
217
217
|
files:
|
218
|
+
- ".gitignore"
|
218
219
|
- Gemfile
|
219
220
|
- Gemfile.lock
|
220
221
|
- LICENSE.txt
|
221
222
|
- README.md
|
222
223
|
- Rakefile
|
224
|
+
- TUTORIAL.md
|
223
225
|
- bin/brief
|
224
226
|
- brief.gemspec
|
225
227
|
- examples/blog/brief.rb
|
@@ -229,7 +231,6 @@ files:
|
|
229
231
|
- lib/brief/briefcase.rb
|
230
232
|
- lib/brief/cli/change.rb
|
231
233
|
- lib/brief/cli/init.rb
|
232
|
-
- lib/brief/cli/publish.rb
|
233
234
|
- lib/brief/cli/write.rb
|
234
235
|
- lib/brief/configuration.rb
|
235
236
|
- lib/brief/core_ext.rb
|
@@ -241,7 +242,9 @@ files:
|
|
241
242
|
- lib/brief/dsl.rb
|
242
243
|
- lib/brief/model.rb
|
243
244
|
- lib/brief/model/definition.rb
|
245
|
+
- lib/brief/model/persistence.rb
|
244
246
|
- lib/brief/repository.rb
|
247
|
+
- lib/brief/util.rb
|
245
248
|
- lib/brief/version.rb
|
246
249
|
- spec/fixtures/example/brief.rb
|
247
250
|
- spec/fixtures/example/docs/concept.html.md
|
@@ -256,6 +259,7 @@ files:
|
|
256
259
|
- spec/lib/brief/document_spec.rb
|
257
260
|
- spec/lib/brief/dsl_spec.rb
|
258
261
|
- spec/lib/brief/model_spec.rb
|
262
|
+
- spec/lib/brief/persistence_spec.rb
|
259
263
|
- spec/lib/brief/repository_spec.rb
|
260
264
|
- spec/spec_helper.rb
|
261
265
|
- spec/support/test_helpers.rb
|
@@ -298,6 +302,7 @@ test_files:
|
|
298
302
|
- spec/lib/brief/document_spec.rb
|
299
303
|
- spec/lib/brief/dsl_spec.rb
|
300
304
|
- spec/lib/brief/model_spec.rb
|
305
|
+
- spec/lib/brief/persistence_spec.rb
|
301
306
|
- spec/lib/brief/repository_spec.rb
|
302
307
|
- spec/spec_helper.rb
|
303
308
|
- spec/support/test_helpers.rb
|
data/lib/brief/cli/publish.rb
DELETED
File without changes
|