seory 0.0.4 → 0.1.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 +4 -4
- data/.travis.yml +2 -0
- data/Gemfile +1 -0
- data/README.md +20 -17
- data/lib/seory.rb +25 -4
- data/lib/seory/condition.rb +29 -0
- data/lib/seory/{page_condition/block_condition.rb → condition/block.rb} +2 -2
- data/lib/seory/condition/build_dsl.rb +19 -0
- data/lib/seory/{page_condition/params_condition.rb → condition/params.rb} +2 -2
- data/lib/seory/{page_condition/path_condition.rb → condition/path.rb} +2 -2
- data/lib/seory/{page_condition/slug_condition.rb → condition/slug.rb} +5 -3
- data/lib/seory/dsl.rb +12 -49
- data/lib/seory/dsl/descriptor.rb +29 -0
- data/lib/seory/dsl/page_builder.rb +35 -0
- data/lib/seory/page.rb +53 -0
- data/lib/seory/page_group.rb +15 -0
- data/lib/seory/rails_helper.rb +7 -0
- data/lib/seory/railtie.rb +11 -0
- data/lib/seory/repository.rb +40 -6
- data/lib/seory/runtime.rb +13 -6
- data/lib/seory/version.rb +1 -1
- data/seory.gemspec +1 -0
- data/spec/seory/{page_condition/path_condition_spec.rb → condition/path_spec.rb} +3 -3
- data/spec/seory/condition/slug_spec.rb +18 -0
- data/spec/seory/dsl_spec.rb +23 -5
- data/spec/seory/{page_contents_spec.rb → page_spec.rb} +12 -12
- data/spec/seory/rails_helper_spec.rb +62 -0
- data/spec/seory/repository_spec.rb +103 -0
- data/spec/seory/runtime_spec.rb +25 -6
- data/spec/spec_helper.rb +8 -0
- data/spec/support/controller_double.rb +37 -0
- data/spec/support/testing_dsl.rb +7 -0
- data/spec/support/view_context_double.rb +13 -0
- metadata +44 -14
- data/lib/seory/page_condition.rb +0 -32
- data/lib/seory/page_condition/build_dsl.rb +0 -19
- data/lib/seory/page_condition/default_condition.rb +0 -10
- data/lib/seory/page_contents.rb +0 -41
@@ -0,0 +1,11 @@
|
|
1
|
+
module Seory
|
2
|
+
autoload :RailsHelper, 'seory/rails_helper'
|
3
|
+
|
4
|
+
class Railtie < ::Rails::Railtie
|
5
|
+
initializer 'seory' do |app|
|
6
|
+
config_dir = (Rails.root + Seory.config_dir)
|
7
|
+
|
8
|
+
app.config.to_prepare { config_dir.each_child {|src| src.extname == '.rb' && load(src) } }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/seory/repository.rb
CHANGED
@@ -1,23 +1,57 @@
|
|
1
1
|
require 'seory/runtime'
|
2
2
|
|
3
3
|
module Seory
|
4
|
+
class DuplicateDefault < Seory::Error; end
|
5
|
+
|
4
6
|
class Repository
|
7
|
+
class << self
|
8
|
+
def extract_label_from_trace(trace)
|
9
|
+
trace.first.split(':').first
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :helper
|
14
|
+
|
5
15
|
def initialize
|
6
|
-
@
|
16
|
+
@page_groups = []
|
7
17
|
end
|
8
18
|
|
9
|
-
def <<(
|
10
|
-
|
19
|
+
def <<(page_group)
|
20
|
+
remove_old_group!(page_group.name)
|
21
|
+
|
22
|
+
@page_groups << page_group
|
23
|
+
|
24
|
+
clear_page_order_pre_calculation!
|
11
25
|
end
|
12
26
|
|
13
27
|
def lookup(controller)
|
14
|
-
|
28
|
+
page = pre_orderd_pages.detect {|pg| pg.match?(controller) } || default
|
15
29
|
|
16
|
-
Seory::Runtime.new(
|
30
|
+
Seory::Runtime.new(page, controller, default).tap do |runtime|
|
31
|
+
runtime.extend helper if helper
|
32
|
+
end
|
17
33
|
end
|
18
34
|
|
19
35
|
def default
|
20
|
-
@
|
36
|
+
@default ||=
|
37
|
+
@page_groups.map(&:default).compact.tap {|defaults|
|
38
|
+
raise DuplicateDefault if defaults.size > 1
|
39
|
+
}.first
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def pre_orderd_pages
|
45
|
+
@pre_orderd_pages ||= @page_groups.sort_by(&:name).flat_map(&:pages)
|
46
|
+
end
|
47
|
+
|
48
|
+
def remove_old_group!(page_group_name)
|
49
|
+
@page_groups.reject! {|pg| pg.name == page_group_name }
|
50
|
+
end
|
51
|
+
|
52
|
+
def clear_page_order_pre_calculation!
|
53
|
+
@pre_orderd_pages = nil
|
54
|
+
@default = nil
|
21
55
|
end
|
22
56
|
end
|
23
57
|
end
|
data/lib/seory/runtime.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
|
-
# TODO move somewhere
|
2
|
-
require 'active_support/all'
|
3
1
|
require 'seory'
|
4
2
|
|
5
3
|
module Seory
|
6
4
|
class Runtime
|
7
5
|
delegate :action_name, to: :controller
|
8
6
|
|
9
|
-
attr_reader :controller
|
7
|
+
attr_reader :page_contents, :controller
|
10
8
|
|
11
9
|
def initialize(page_contents, controller, fallback = nil)
|
12
10
|
@page_contents = page_contents
|
13
11
|
@controller = controller
|
14
12
|
@fallback = fallback
|
13
|
+
|
14
|
+
extend build_assign_accessor_module(@page_contents.assign_name_accessors)
|
15
15
|
end
|
16
16
|
|
17
17
|
def assigns(name)
|
@@ -30,14 +30,12 @@ module Seory
|
|
30
30
|
|
31
31
|
def calculate_content_for(name)
|
32
32
|
case page_content = lookup_content_for(name)
|
33
|
-
when String
|
34
|
-
page_content
|
35
33
|
when Symbol
|
36
34
|
calculate_content_for(page_content)
|
37
35
|
when ->(o) { o.respond_to?(:call) }
|
38
36
|
instance_exec(&page_content)
|
39
37
|
else
|
40
|
-
|
38
|
+
page_content.to_s
|
41
39
|
end
|
42
40
|
end
|
43
41
|
|
@@ -45,5 +43,14 @@ module Seory
|
|
45
43
|
@page_contents.content_for(name) || \
|
46
44
|
@fallback.try {|fb| fb.content_for(name) }
|
47
45
|
end
|
46
|
+
|
47
|
+
def build_assign_accessor_module(names)
|
48
|
+
Module.new do
|
49
|
+
Array(names).each do |name|
|
50
|
+
define_method(name) { assigns(name) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
48
55
|
end
|
49
56
|
end
|
data/lib/seory/version.rb
CHANGED
data/seory.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'seory/
|
2
|
+
require 'seory/condition/path'
|
3
3
|
|
4
|
-
describe Seory::
|
4
|
+
describe Seory::Condition::Path do
|
5
5
|
let(:controller) { double('controller') }
|
6
6
|
let(:path_condition) do
|
7
|
-
Seory::
|
7
|
+
Seory::Condition::Path.new('/users/alice')
|
8
8
|
end
|
9
9
|
|
10
10
|
context 'Accessed to /users/alice (controller: users, action: show, id: alice)' do
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'seory/condition/slug'
|
3
|
+
|
4
|
+
describe Seory::Condition::Slug do
|
5
|
+
context 'with nested controller slug' do
|
6
|
+
let(:controller) do
|
7
|
+
double('controller', {
|
8
|
+
controller_name: 'products',
|
9
|
+
controller_path: 'contents/products',
|
10
|
+
action_name: 'index'
|
11
|
+
})
|
12
|
+
end
|
13
|
+
let(:slug_condition) { Seory::Condition::Slug.new('contents/products#index') }
|
14
|
+
|
15
|
+
specify { expect(slug_condition.match?(controller)).to be_truthy }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
data/spec/seory/dsl_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe Seory::Dsl do
|
|
7
7
|
context 'with traditional syntax' do
|
8
8
|
let(:seory_class) { Object.new.extend(Seory::Dsl) }
|
9
9
|
before do
|
10
|
-
seory_class.describe do
|
10
|
+
seory_class.describe('Group A') do
|
11
11
|
match ->(c) { c.controller_name == 'reports' } do
|
12
12
|
title 'Useful reports'
|
13
13
|
end
|
@@ -30,13 +30,13 @@ describe Seory::Dsl do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
context 'at reports#index / match with proc' do
|
33
|
-
let(:controller) { double('controller', controller_name: 'reports', action_name: 'index') }
|
33
|
+
let(:controller) { double('controller', controller_name: 'reports', controller_path: 'reports', action_name: 'index') }
|
34
34
|
|
35
35
|
specify { expect(seory.title).to eq 'Useful reports' }
|
36
36
|
end
|
37
37
|
|
38
38
|
context 'at products#index' do
|
39
|
-
let(:controller) { double('controller', controller_name: 'products', action_name: 'index') }
|
39
|
+
let(:controller) { double('controller', controller_name: 'products', controller_path: 'products', action_name: 'index') }
|
40
40
|
|
41
41
|
specify { expect(seory.title).to eq 'My Great Product' }
|
42
42
|
specify { expect(seory.h1).to eq 'Great Product Name' }
|
@@ -46,13 +46,31 @@ describe Seory::Dsl do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
context 'at misc#show' do
|
49
|
-
let(:controller) { double('controller', controller_name: 'misc', action_name: 'show') }
|
49
|
+
let(:controller) { double('controller', controller_name: 'misc', controller_path: 'misc', action_name: 'show') }
|
50
50
|
|
51
51
|
specify { expect(seory.h1).to eq 'MISC' }
|
52
52
|
specify { expect(seory.misc(:option)).to eq 'dynamic option name at misc' }
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
+
context 'accessor to assign' do
|
57
|
+
let(:seory_class) { Object.new.extend(Seory::Dsl) }
|
58
|
+
let(:controller) do
|
59
|
+
controller_double('products#show') { @product = OpenStruct.new(name: 'seory') }
|
60
|
+
end
|
61
|
+
|
62
|
+
before do
|
63
|
+
seory_class.describe do
|
64
|
+
match slug('products#show') do
|
65
|
+
assign_reader :product
|
66
|
+
title { product.name }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
specify { expect(seory.title).to eq 'seory' }
|
72
|
+
end
|
73
|
+
|
56
74
|
context 'with matcher build dsl syntax' do
|
57
75
|
let(:seory_class) { Object.new.extend(Seory::Dsl) }
|
58
76
|
before do
|
@@ -69,7 +87,7 @@ describe Seory::Dsl do
|
|
69
87
|
|
70
88
|
context 'at products#show' do
|
71
89
|
let(:controller) do
|
72
|
-
double('controller', controller_name: 'products', action_name: 'show', params: {id: 42}).tap do |c|
|
90
|
+
double('controller', controller_name: 'products', controller_path: 'products', action_name: 'show', params: {id: 42}).tap do |c|
|
73
91
|
allow(c).to receive_message_chain(:request, :fullpath) { '/products/42' }
|
74
92
|
end
|
75
93
|
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'seory/
|
2
|
+
require 'seory/page'
|
3
3
|
|
4
|
-
describe Seory::
|
4
|
+
describe Seory::Page do
|
5
5
|
specify 'cant define without condition' do
|
6
|
-
expect { Seory::
|
6
|
+
expect { Seory::Page.new }.to raise_error(Seory::EmptyCondition)
|
7
7
|
end
|
8
8
|
|
9
|
-
context 'content
|
9
|
+
context 'content Page' do
|
10
10
|
let(:seory_def) do
|
11
|
-
Seory::
|
11
|
+
Seory::Page.new(:default)
|
12
12
|
end
|
13
13
|
|
14
14
|
context 'define static content' do
|
@@ -40,16 +40,16 @@ describe Seory::PageContents do
|
|
40
40
|
|
41
41
|
describe 'condition and #match?' do
|
42
42
|
def init_with(*args, &block)
|
43
|
-
Seory::
|
43
|
+
Seory::Page.new(*args, &block)
|
44
44
|
end
|
45
45
|
|
46
|
-
let(:controller) { double('controller',
|
46
|
+
let(:controller) { double('controller', controller_path: 'people', action_name: 'index') }
|
47
47
|
|
48
48
|
specify '`:default` matches everything (stacked in bottom)' do
|
49
49
|
expect(init_with(:default)).to be_match(double('something'))
|
50
50
|
end
|
51
51
|
|
52
|
-
describe '
|
52
|
+
describe 'controller_path#action_name' do
|
53
53
|
specify do
|
54
54
|
expect(init_with('people#index').match?(controller)).to be_truthy
|
55
55
|
end
|
@@ -63,7 +63,7 @@ describe Seory::PageContents do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
specify do
|
66
|
-
page_contents = init_with {|c| c.
|
66
|
+
page_contents = init_with {|c| c.controller_path == 'people' }
|
67
67
|
|
68
68
|
expect(page_contents.match?(controller)).to be_truthy
|
69
69
|
end
|
@@ -102,17 +102,17 @@ describe Seory::PageContents do
|
|
102
102
|
|
103
103
|
describe 'proc conditions' do
|
104
104
|
let(:page_content) do
|
105
|
-
init_with {|c| c.
|
105
|
+
init_with {|c| c.controller_path == 'users' }
|
106
106
|
end
|
107
107
|
|
108
108
|
specify 'match UsersController' do
|
109
|
-
allow(controller).to receive(:
|
109
|
+
allow(controller).to receive(:controller_path) { 'users' }
|
110
110
|
|
111
111
|
expect(page_content.match?(controller)).to be_truthy
|
112
112
|
end
|
113
113
|
|
114
114
|
specify 'not match GoodsController' do
|
115
|
-
allow(controller).to receive(:
|
115
|
+
allow(controller).to receive(:controller_path) { 'goods' }
|
116
116
|
|
117
117
|
expect(page_content.match?(controller)).to be_falsy
|
118
118
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'seory'
|
3
|
+
|
4
|
+
describe Seory::RailsHelper do
|
5
|
+
before do
|
6
|
+
Seory.seo_content 'products' do
|
7
|
+
match slug('products#index') do
|
8
|
+
title 'Product index'
|
9
|
+
end
|
10
|
+
|
11
|
+
default do
|
12
|
+
title 'Default title'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Seory.seo_content 'Review for products' do
|
17
|
+
match slug('products/reviews#index') do
|
18
|
+
assign_reader :product
|
19
|
+
|
20
|
+
title { "Reviews for #{bang(product.name)}" }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Seory.helper do
|
25
|
+
def bang(string); string + ' !!!'; end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'GET /products' do
|
30
|
+
let(:context) do
|
31
|
+
Seory::ViewContextDouble.new(controller_double('products#index'))
|
32
|
+
end
|
33
|
+
|
34
|
+
specify do
|
35
|
+
expect(context.seory.title).to eq 'Product index'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'GET /products/a-computer/reviews' do
|
40
|
+
let(:context) do
|
41
|
+
controller = controller_double('products/reviews#index') do
|
42
|
+
@product = OpenStruct.new(name: 'a-computer')
|
43
|
+
end
|
44
|
+
|
45
|
+
Seory::ViewContextDouble.new(controller)
|
46
|
+
end
|
47
|
+
|
48
|
+
specify do
|
49
|
+
expect(context.seory.title).to eq "Reviews for a-computer !!!"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'GET /users' do
|
54
|
+
let(:context) do
|
55
|
+
Seory::ViewContextDouble.new(controller_double('users#index'))
|
56
|
+
end
|
57
|
+
|
58
|
+
specify do
|
59
|
+
expect(context.seory.title).to eq 'Default title'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'seory/repository'
|
3
|
+
require 'seory/dsl/descriptor'
|
4
|
+
|
5
|
+
describe Seory::Repository do
|
6
|
+
let(:repository) { Seory::Repository.new }
|
7
|
+
|
8
|
+
describe '.extract_label_from_trace' do
|
9
|
+
let(:label) do
|
10
|
+
begin
|
11
|
+
raise
|
12
|
+
rescue => ex
|
13
|
+
Seory::Repository.extract_label_from_trace(ex.backtrace)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
specify { expect(label).to eq __FILE__ }
|
18
|
+
end
|
19
|
+
|
20
|
+
def title_for(*args)
|
21
|
+
repository.lookup(controller_double(*args)).title
|
22
|
+
end
|
23
|
+
|
24
|
+
def page_group(name, title = name)
|
25
|
+
describe_page_group(name) do
|
26
|
+
match(slug("#{name}#show")) { title title }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def describe_page_group(name, &block)
|
31
|
+
Seory::Dsl::Descriptor.new(name, repository).describe(&block)
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'has 2 page groups: users & products' do
|
35
|
+
before do
|
36
|
+
repository << page_group('users')
|
37
|
+
repository << page_group('products')
|
38
|
+
end
|
39
|
+
|
40
|
+
specify 'lookup valid page over page_groups' do
|
41
|
+
expect(title_for('users#show', id: 42)).to eq 'users'
|
42
|
+
expect(title_for('products#show', id: 42)).to eq 'products'
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'overrides same name group' do
|
46
|
+
before do
|
47
|
+
repository << page_group('users', 'other users')
|
48
|
+
end
|
49
|
+
|
50
|
+
specify 'after one should be used' do
|
51
|
+
expect(title_for('users#show', id: 42)).to eq 'other users'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'match controller by PageGroup#name sorted' do
|
56
|
+
before do
|
57
|
+
repository << (
|
58
|
+
Seory::Dsl::Descriptor.new('aaa', repository).describe do
|
59
|
+
match(params(controller: 'users')) { title 'defined after, match ahead' }
|
60
|
+
end
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
specify do
|
65
|
+
expect(title_for('users#show', id: 42)).to eq 'defined after, match ahead'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'helper integration' do
|
71
|
+
before do
|
72
|
+
repository << describe_page_group('default') { default { title { upcase('title') }} }
|
73
|
+
repository.helper = Module.new do
|
74
|
+
def upcase(string); string.upcase; end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
specify do
|
79
|
+
expect(title_for('hoge#foo')).to eq 'TITLE'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'default fallback' do
|
84
|
+
context 'default is used from any page group' do
|
85
|
+
before do
|
86
|
+
repository << page_group('users')
|
87
|
+
repository << describe_page_group('default') { default { title 'default title' } }
|
88
|
+
end
|
89
|
+
|
90
|
+
specify do
|
91
|
+
expect(title_for('hoge#foo')).to eq 'default title'
|
92
|
+
end
|
93
|
+
|
94
|
+
specify 'default can be specified from only one page group or raise DuplicateDefault' do
|
95
|
+
expect {
|
96
|
+
repository << describe_page_group('duplicate default') { default { title 'duplicate default' } }
|
97
|
+
|
98
|
+
repository.lookup(controller_double('hi#index'))
|
99
|
+
}.to raise_error(Seory::DuplicateDefault)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|