betterdocs 0.2.0
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/.codeclimate.yml +5 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/COPYING +202 -0
- data/Gemfile +8 -0
- data/LICENSE +202 -0
- data/README.md +124 -0
- data/Rakefile +25 -0
- data/VERSION +1 -0
- data/betterdocs.gemspec +48 -0
- data/lib/betterdocs.rb +27 -0
- data/lib/betterdocs/controller_collector.rb +50 -0
- data/lib/betterdocs/dsl.rb +9 -0
- data/lib/betterdocs/dsl/common.rb +26 -0
- data/lib/betterdocs/dsl/controller.rb +9 -0
- data/lib/betterdocs/dsl/controller/action.rb +126 -0
- data/lib/betterdocs/dsl/controller/action/param.rb +25 -0
- data/lib/betterdocs/dsl/controller/action/response.rb +47 -0
- data/lib/betterdocs/dsl/controller/controller.rb +31 -0
- data/lib/betterdocs/dsl/controller/controller_base.rb +21 -0
- data/lib/betterdocs/dsl/json_params.rb +8 -0
- data/lib/betterdocs/dsl/json_params/param.rb +31 -0
- data/lib/betterdocs/dsl/json_type_mapper.rb +27 -0
- data/lib/betterdocs/dsl/naming.rb +32 -0
- data/lib/betterdocs/dsl/representer.rb +29 -0
- data/lib/betterdocs/dsl/result.rb +10 -0
- data/lib/betterdocs/dsl/result/collection_property.rb +9 -0
- data/lib/betterdocs/dsl/result/link.rb +37 -0
- data/lib/betterdocs/dsl/result/property.rb +53 -0
- data/lib/betterdocs/generator/config_shortcuts.rb +28 -0
- data/lib/betterdocs/generator/markdown.rb +151 -0
- data/lib/betterdocs/generator/markdown/templates/README.md.erb +9 -0
- data/lib/betterdocs/generator/markdown/templates/section.md.erb +132 -0
- data/lib/betterdocs/global.rb +143 -0
- data/lib/betterdocs/json_params_representer.rb +37 -0
- data/lib/betterdocs/json_params_representer_collector.rb +48 -0
- data/lib/betterdocs/mix_into_controller.rb +19 -0
- data/lib/betterdocs/rake_tasks.rb +5 -0
- data/lib/betterdocs/representer.rb +42 -0
- data/lib/betterdocs/result_representer.rb +68 -0
- data/lib/betterdocs/result_representer_collector.rb +82 -0
- data/lib/betterdocs/section.rb +6 -0
- data/lib/betterdocs/tasks/doc.rake +55 -0
- data/lib/betterdocs/version.rb +8 -0
- data/spec/controller_dsl_spec.rb +143 -0
- data/spec/generator/markdown_spec.rb +5 -0
- data/spec/json_params_representer_spec.rb +79 -0
- data/spec/json_type_mapper_spec.rb +33 -0
- data/spec/result_representer_dsl_spec.rb +183 -0
- data/spec/result_representer_spec.rb +182 -0
- data/spec/spec_helper.rb +19 -0
- metadata +234 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
module Betterdocs
|
2
|
+
class ResultRepresenterCollector
|
3
|
+
def initialize
|
4
|
+
@properties = {}
|
5
|
+
@links = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :properties
|
9
|
+
|
10
|
+
attr_reader :links
|
11
|
+
|
12
|
+
def property(property_name)
|
13
|
+
property_name = property_name.to_sym
|
14
|
+
@properties[property_name]
|
15
|
+
end
|
16
|
+
|
17
|
+
def link(link_name)
|
18
|
+
link_name = link_name.to_sym
|
19
|
+
@links[link_name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_element(representer, type, name, **options, &block)
|
23
|
+
element = build_element(representer, type, name, options, &block)
|
24
|
+
element.add_to_collector(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def representer
|
28
|
+
(@properties.values + @links.values).find { |v|
|
29
|
+
v.representer and break v.representer
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def nested_properties(path = [])
|
34
|
+
properties.values.each_with_object([]) do |property, result|
|
35
|
+
result << property.below_path(path)
|
36
|
+
if sr = property.sub_representer?
|
37
|
+
result.concat sr.docs.nested_properties(path + property.path)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def nested_links(path = [])
|
43
|
+
result = links.values.map { |l| l.below_path(path) }
|
44
|
+
properties.values.each_with_object(result) do |property, result|
|
45
|
+
if sr = property.sub_representer?
|
46
|
+
nested_property = property.below_path(path)
|
47
|
+
links = sr.docs.nested_links(nested_property.path)
|
48
|
+
result.concat links
|
49
|
+
end
|
50
|
+
end
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
result = "*** #{representer} ***\n"
|
56
|
+
if properties = @properties.values.full?
|
57
|
+
result << "\nProperties:"
|
58
|
+
nested_properties.each_with_object(result) do |property, r|
|
59
|
+
r << "\n#{property.full_name}: (#{property.types * '|'}): #{property.description}\n"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
if links = @links.values.full?
|
63
|
+
result << "\nLinks:"
|
64
|
+
links.each_with_object(result) do |link, r|
|
65
|
+
r << "\n#{link.full_name}: #{link.description}\n" # TODO resolve link.url in some useful way
|
66
|
+
end
|
67
|
+
end
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def build_element(representer, type, *args, &block)
|
74
|
+
begin
|
75
|
+
element = Dsl::Result.const_get(type.to_s.camelcase)
|
76
|
+
rescue NameError => e
|
77
|
+
raise ArgumentError, "unknown documentation element type #{type.inspect}"
|
78
|
+
end
|
79
|
+
element.new(representer, *args, &block)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
namespace :doc do
|
2
|
+
desc "Create the API documentation"
|
3
|
+
task :api => :'doc:api:sandbox' do
|
4
|
+
Betterdocs::Global.config do |config|
|
5
|
+
Betterdocs::Generator::Markdown.new(only: ENV['ONLY']).generate
|
6
|
+
cd config.output_directory do
|
7
|
+
File.open('.gitignore', 'w') { |ignore| ignore.puts config.ignore }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
task :set_betterdocs_env do
|
13
|
+
ENV['BETTERDOCS'] = '1'
|
14
|
+
end
|
15
|
+
|
16
|
+
namespace :api do
|
17
|
+
desc 'Let database transactions run in a sandboxed environment'
|
18
|
+
task :sandbox => [:'doc:set_betterdocs_env', :environment] do
|
19
|
+
|
20
|
+
ActiveRecord::Base.connection.begin_db_transaction
|
21
|
+
at_exit do
|
22
|
+
ActiveRecord::Base.connection.rollback_db_transaction
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Push the newly created API documentation to the remote git repo"
|
27
|
+
task :push => :api do
|
28
|
+
Betterdocs::Global.config do |config|
|
29
|
+
config.publish_git or fail "Configure a git repo as publish_git to publish to"
|
30
|
+
cd config.output_directory do
|
31
|
+
File.directory?('.git') or sh "git init"
|
32
|
+
sh "git remote rm publish_git || true"
|
33
|
+
sh "git remote add publish_git #{config.publish_git}"
|
34
|
+
sh "git add -A"
|
35
|
+
sh 'git commit -m "Add some more changes to API documentation" || true'
|
36
|
+
sh 'git push -f publish_git master'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc "Publish the newly created API documentation"
|
42
|
+
task :publish => [ :push ]
|
43
|
+
|
44
|
+
desc "Publish and view the newly created API documentation"
|
45
|
+
task :view => :publish do
|
46
|
+
Betterdocs::Global.config do |config|
|
47
|
+
url = config.publish_git
|
48
|
+
if url !~ /\Ahttps?:/
|
49
|
+
url.sub!(/.*?([^@]*):/, 'http://\1/')
|
50
|
+
end
|
51
|
+
sh "open #{url.inspect}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'controller dsl' do
|
4
|
+
let :docs do
|
5
|
+
Betterdocs::ControllerCollector.new
|
6
|
+
end
|
7
|
+
|
8
|
+
let :rails do
|
9
|
+
double(application: double(routes: double(url_for: 'http://foo/bar')))
|
10
|
+
end
|
11
|
+
|
12
|
+
let :controller do
|
13
|
+
Module.new do
|
14
|
+
class << self
|
15
|
+
def name
|
16
|
+
'MyTestController'
|
17
|
+
end
|
18
|
+
|
19
|
+
alias to_s name
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def foo
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "cannot add unknown element types" do
|
29
|
+
expect {
|
30
|
+
docs.add_element controller, :foobar, 'my_foobar' do
|
31
|
+
end
|
32
|
+
}.to raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'controller' do
|
36
|
+
it "can add a new controller" do
|
37
|
+
docs.add_element controller, :controller do
|
38
|
+
description 'my description'
|
39
|
+
section :test_section
|
40
|
+
end
|
41
|
+
allow(Betterdocs).to receive(:rails).and_return rails
|
42
|
+
my_controller = docs.controller
|
43
|
+
expect(my_controller).to be_present
|
44
|
+
expect(my_controller.name).to eq :my_test
|
45
|
+
expect(my_controller.section).to eq :test_section
|
46
|
+
expect(my_controller.controller).to eq controller
|
47
|
+
expect(my_controller.description).to eq 'my description'
|
48
|
+
expect(my_controller.url).to eq 'http://foo/bar'
|
49
|
+
expect(docs.to_s).to eq(<<EOT)
|
50
|
+
MyTestController
|
51
|
+
|
52
|
+
url: http://foo/bar
|
53
|
+
|
54
|
+
my description
|
55
|
+
|
56
|
+
===============================================================================
|
57
|
+
|
58
|
+
EOT
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'can be represented as a string if empty' do
|
62
|
+
expect(docs.to_s).to eq(
|
63
|
+
"\n===============================================================================\n\n"
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
module MyActionJsonParams
|
69
|
+
include Betterdocs::JsonParamsRepresenter
|
70
|
+
|
71
|
+
param :baz do
|
72
|
+
description 'Some string'
|
73
|
+
types String
|
74
|
+
value 'baz'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
SomeParamsTrait = Betterdocs.trait do
|
79
|
+
param :quux do
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'action' do
|
84
|
+
it "can add a new action" do
|
85
|
+
docs.add_element controller, :controller do
|
86
|
+
description 'my controller description'
|
87
|
+
section :test_section
|
88
|
+
end
|
89
|
+
docs.add_element controller, :action do
|
90
|
+
description 'my description'
|
91
|
+
section :test_section2
|
92
|
+
http_method :GET
|
93
|
+
|
94
|
+
param :bar do
|
95
|
+
end
|
96
|
+
|
97
|
+
param :baz do
|
98
|
+
use_in_url no
|
99
|
+
end
|
100
|
+
|
101
|
+
include_params SomeParamsTrait
|
102
|
+
|
103
|
+
json_params_like MyActionJsonParams
|
104
|
+
end
|
105
|
+
allow(Betterdocs).to receive(:rails).and_return rails
|
106
|
+
expect(docs.actions).to be_empty
|
107
|
+
docs.configure_current_element(:foo)
|
108
|
+
expect(docs.actions.size).to eq 1
|
109
|
+
expect(action = docs.action(:foo)).to be_present
|
110
|
+
expect(action.controller).to eq controller
|
111
|
+
expect(action.name).to eq :foo
|
112
|
+
expect(action.section).to eq :test_section2
|
113
|
+
expect(docs.section).to eq :test_section
|
114
|
+
expect(action.action_method).to eq controller.instance_method(:foo)
|
115
|
+
expect(action.http_method).to eq :GET
|
116
|
+
expect(action.params).to have_key :bar
|
117
|
+
expect(action.params).to have_key :quux
|
118
|
+
expect(action.json_params).to have_key :baz
|
119
|
+
expect(action.url).to eq 'http://foo/bar'
|
120
|
+
expect(docs.to_s.sub(%r(.*(betterdocs/.*)), '\1')).to eq(<<EOT)
|
121
|
+
MyTestController
|
122
|
+
|
123
|
+
url: http://foo/bar
|
124
|
+
|
125
|
+
my controller description
|
126
|
+
|
127
|
+
===============================================================================
|
128
|
+
GET http://foo/bar
|
129
|
+
|
130
|
+
MyTestController#foo(bar, baz, quux)
|
131
|
+
|
132
|
+
bar(=1): TODO
|
133
|
+
baz(=2): TODO
|
134
|
+
quux(=3): TODO
|
135
|
+
|
136
|
+
my description
|
137
|
+
|
138
|
+
betterdocs/spec/controller_dsl_spec.rb:23
|
139
|
+
|
140
|
+
EOT
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Betterdocs::JsonParamsRepresenter do
|
4
|
+
module MyJsonParams
|
5
|
+
include Betterdocs::JsonParamsRepresenter
|
6
|
+
|
7
|
+
param :string do
|
8
|
+
description 'Some string'
|
9
|
+
types String
|
10
|
+
value 'peter.paul@betterplace.org'
|
11
|
+
end
|
12
|
+
|
13
|
+
param :number do
|
14
|
+
description 'some integer number'
|
15
|
+
types Integer
|
16
|
+
value 666
|
17
|
+
required yes
|
18
|
+
end
|
19
|
+
|
20
|
+
param :flag do
|
21
|
+
description 'some boolean flag'
|
22
|
+
types [ true, false ]
|
23
|
+
value true
|
24
|
+
required no
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
let :object do
|
29
|
+
OpenStruct.new.tap do |o|
|
30
|
+
o.string = 'some string'
|
31
|
+
o.number = 666
|
32
|
+
o.flag = true
|
33
|
+
MyJsonParams.apply(o)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
let :docs do
|
38
|
+
MyJsonParams.docs
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'can be converted into a ActionController::Parameters instance' do
|
42
|
+
expect(object.as_json).to be_a ActionController::Parameters
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'it can be turned into a hash' do
|
46
|
+
expect(object.as_json).to eq("string" => "some string", "number" => 666, "flag" => true)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'it can be turned into json' do
|
50
|
+
expect(object.to_json).to eq '{"string":"some string","number":666,"flag":true}'
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'can check a parameter hash' do
|
54
|
+
skip
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'can return all the documented parameters as a hash' do
|
58
|
+
expect(docs.params.keys).to eq %i[ string number flag ]
|
59
|
+
end
|
60
|
+
|
61
|
+
context '#param' do
|
62
|
+
let :param do
|
63
|
+
docs.param(:string)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'can return a single documented parameter' do
|
67
|
+
expect(param).to be_a Betterdocs::Dsl::JsonParams::Param
|
68
|
+
expect(param.description).to eq 'Some string'
|
69
|
+
expect(param.value).to eq 'peter.paul@betterplace.org'
|
70
|
+
expect(param.types).to eq %w[ string ]
|
71
|
+
expect(param.required).to eq true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'foos' do
|
76
|
+
puts docs.to_s
|
77
|
+
skip
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe Betterdocs::Dsl::JsonTypeMapper do
|
4
|
+
let :jtm do Betterdocs::Dsl::JsonTypeMapper end
|
5
|
+
|
6
|
+
it "derives json types" do
|
7
|
+
expect(jtm.derive_json_type_from(true)).to eq 'boolean'
|
8
|
+
expect(jtm.derive_json_type_from(TrueClass)).to eq 'boolean'
|
9
|
+
expect(jtm.derive_json_type_from(false)).to eq 'boolean'
|
10
|
+
expect(jtm.derive_json_type_from(FalseClass)).to eq 'boolean'
|
11
|
+
expect(jtm.derive_json_type_from(nil)).to eq 'null'
|
12
|
+
expect(jtm.derive_json_type_from(NilClass)).to eq 'null'
|
13
|
+
expect(jtm.derive_json_type_from(42)).to eq 'number'
|
14
|
+
expect(jtm.derive_json_type_from(Fixnum)).to eq 'number'
|
15
|
+
expect(jtm.derive_json_type_from(42)).to eq 'number'
|
16
|
+
expect(jtm.derive_json_type_from(Fixnum)).to eq 'number'
|
17
|
+
expect(jtm.derive_json_type_from(Math::PI)).to eq 'number'
|
18
|
+
expect(jtm.derive_json_type_from(Float)).to eq 'number'
|
19
|
+
expect(jtm.derive_json_type_from([])).to eq 'array'
|
20
|
+
expect(jtm.derive_json_type_from(Array)).to eq 'array'
|
21
|
+
expect(jtm.derive_json_type_from({})).to eq 'object'
|
22
|
+
expect(jtm.derive_json_type_from(Hash)).to eq 'object'
|
23
|
+
expect(jtm.derive_json_type_from('foo')).to eq 'string'
|
24
|
+
expect(jtm.derive_json_type_from(String)).to eq 'string'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "maps arrays of ruby types correctly" do
|
28
|
+
expect(jtm.map_types([])).to eq %w[ array ]
|
29
|
+
expect(jtm.map_types([ [] ])).to eq %w[ array ]
|
30
|
+
expect(jtm.map_types([ [], {}, Array, nil, Hash ])).to eq %w[ array null object ]
|
31
|
+
expect(jtm.map_types("foo")).to eq %w[ string ]
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'representer dsl' do
|
4
|
+
let :docs do
|
5
|
+
Betterdocs::ResultRepresenterCollector.new
|
6
|
+
end
|
7
|
+
|
8
|
+
let :representer do
|
9
|
+
Module.new do
|
10
|
+
def self.property(*)
|
11
|
+
@property_set = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.has_property_set?
|
15
|
+
@property_set
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.link(*)
|
19
|
+
@link_set = true
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.has_link_set?
|
23
|
+
@link_set
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.to_s
|
27
|
+
'MyRepresenter'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "cannot add unknown element types" do
|
33
|
+
expect {
|
34
|
+
docs.add_element representer, :foobar, 'my_foobar' do
|
35
|
+
end
|
36
|
+
}.to raise_error(ArgumentError)
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'property' do
|
40
|
+
it "can add a new property" do
|
41
|
+
docs.add_element representer, :property, 'my_property' do
|
42
|
+
# XXX as :foo_bar
|
43
|
+
description 'my description'
|
44
|
+
types [ String, nil ]
|
45
|
+
end
|
46
|
+
property = docs.property(:my_property)
|
47
|
+
expect(property).to be_present
|
48
|
+
expect(property.name).to eq :my_property
|
49
|
+
expect(property.representer).to eq representer
|
50
|
+
expect(property.description).to eq 'my description'
|
51
|
+
expect(property.types).to eq %w[ null string ]
|
52
|
+
expect(property.example).to eq 'TODO' # TODO
|
53
|
+
end
|
54
|
+
|
55
|
+
it "can define a property on representer" do
|
56
|
+
docs.add_element representer, :property, 'my_property' do
|
57
|
+
end
|
58
|
+
property = docs.property(:my_property)
|
59
|
+
expect(property).to be_present
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'link' do
|
64
|
+
it "cannot add a new link without url" do
|
65
|
+
docs.add_element representer, :link, 'my_link' do
|
66
|
+
end
|
67
|
+
link = docs.link(:my_link)
|
68
|
+
expect { link.url }.to raise_error(ArgumentError)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "can add a new link" do
|
72
|
+
docs.add_element representer, :link, 'my_link' do
|
73
|
+
description 'my URL description'
|
74
|
+
url { 'http://foo.bar' }
|
75
|
+
end
|
76
|
+
link = docs.link(:my_link)
|
77
|
+
expect(link).to be_present
|
78
|
+
expect(link.name).to eq :my_link
|
79
|
+
expect(link.representer).to eq representer
|
80
|
+
expect(link.description).to eq 'my URL description'
|
81
|
+
end
|
82
|
+
|
83
|
+
it "can define a templated link" do
|
84
|
+
docs.add_element representer, :link, 'my_link' do
|
85
|
+
description 'my URL description'
|
86
|
+
url { 'http://foo.bar' }
|
87
|
+
templated yes
|
88
|
+
end
|
89
|
+
link = docs.link(:my_link)
|
90
|
+
expect(link).to be_present
|
91
|
+
expect(link.templated).to eq true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'can return a string representation of all its links/properties' do
|
96
|
+
docs.add_element representer, :property, 'my_property' do
|
97
|
+
# XXX as :foo_bar
|
98
|
+
description 'my description'
|
99
|
+
types [ String, nil ]
|
100
|
+
end
|
101
|
+
docs.add_element representer, :property, 'my_property2' do
|
102
|
+
description 'my description2'
|
103
|
+
types [ true, false ]
|
104
|
+
end
|
105
|
+
docs.add_element representer, :link, 'my_link' do
|
106
|
+
description 'my URL description'
|
107
|
+
url { 'http://foo.bar' }
|
108
|
+
end
|
109
|
+
docs.add_element representer, :link, 'my_link2' do
|
110
|
+
description 'my URL description2'
|
111
|
+
url { 'http://foo.baz' }
|
112
|
+
end
|
113
|
+
expect(docs.to_s).to eq <<EOT
|
114
|
+
*** MyRepresenter ***
|
115
|
+
|
116
|
+
Properties:
|
117
|
+
my_property: (null|string): my description
|
118
|
+
|
119
|
+
my_property2: (boolean): my description2
|
120
|
+
|
121
|
+
Links:
|
122
|
+
my_link: my URL description
|
123
|
+
|
124
|
+
my_link2: my URL description2
|
125
|
+
EOT
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'nesting representers' do
|
129
|
+
module Location
|
130
|
+
include Betterdocs::ResultRepresenter
|
131
|
+
|
132
|
+
property :latitude
|
133
|
+
|
134
|
+
property :longitude
|
135
|
+
|
136
|
+
link :dot do
|
137
|
+
url { 'http://foo.bar/dot' }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
module Address
|
142
|
+
include Betterdocs::ResultRepresenter
|
143
|
+
|
144
|
+
property :city
|
145
|
+
|
146
|
+
property :location do
|
147
|
+
represent_with Location
|
148
|
+
end
|
149
|
+
|
150
|
+
link :map do
|
151
|
+
url { 'http://foo.bar/map' }
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
module Person
|
157
|
+
include Betterdocs::ResultRepresenter
|
158
|
+
|
159
|
+
property :name
|
160
|
+
|
161
|
+
property :address do
|
162
|
+
represent_with Address
|
163
|
+
end
|
164
|
+
|
165
|
+
link :self do
|
166
|
+
url { 'http://foo.bar' }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'can return an array of its nested properties' do
|
171
|
+
expect(Person.docs.nested_properties.size).to eq 6
|
172
|
+
expect(Person.docs.nested_properties.map(&:full_name)).to eq [ "name",
|
173
|
+
"address", "address.city", "address.location",
|
174
|
+
"address.location.latitude", "address.location.longitude" ]
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'can return an array of its nested links' do
|
178
|
+
expect(Person.docs.nested_links.size).to eq 3
|
179
|
+
expect(Person.docs.nested_links.map(&:full_name)).to eq [
|
180
|
+
"self", "address.map", "address.location.dot" ]
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|