seory 0.0.3 → 0.0.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 31a71be5bea7d32b2895e6b280c50db69074f284
4
- data.tar.gz: e313695b9b65b658367267bcc5c9a89d82b151d9
3
+ metadata.gz: e4ad5a6d00f1d68662b39cb9716d1146b182688c
4
+ data.tar.gz: 847f039ab50d26b966e03b1f1175554d77ee6cb2
5
5
  SHA512:
6
- metadata.gz: 92c72d830486a8487178f108e7d9459c7aad9ebab926668263f1f9460f0846212f17fe2115b88fbeca780fb89a989d3307ce7c93edf97598994381148f701e5c
7
- data.tar.gz: efd6daee3a8d918db5c596adf39f9da80fb4e6ad75825b195e99ca4069e04055bbbec103e20728030ecba3bb7d0cb32e0b5969e62f1f2289f8630ab7b6c78533
6
+ metadata.gz: 912cc7524283289708d5d852510c9a077dd60093521521a3eff1bb759891404abdf405b10e55fdb6e06255124047dcf1a622b00b5fcf50b440acb41e5f85810b
7
+ data.tar.gz: 8f64f9624cc492e8537d2e75b69c77595e4050c44c10d870cef44ac17134b2123a1f78a48467606c0524d2d6466399e802e72089a355592dbb1770013c995a4a
data/.travis.yml ADDED
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1
6
+ notifications:
7
+ webhooks:
8
+ - https://idobata.io/hook/061179f9-4f3c-4c8c-bdf9-4efa9821c5c5
9
+
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Seory
1
+ # seory
2
2
 
3
- Manage SEO contets in Rails app. based on controller, action and more complex context.
3
+ Manage SEO contents in Rails app. based on controller, action and more complex context.
4
4
 
5
5
  ## Installation
6
6
 
@@ -22,7 +22,7 @@ Specify SEO content as ruby code. For example, `config/initializers/seory.rb`
22
22
 
23
23
  ```ruby
24
24
  # Specify SEO content based on `controller#action` rule
25
- match %w[products#popular products#new_release], {
25
+ match *%w[products#popular products#new_release] {
26
26
  title: 'Great products | My Great Site[MGS]'
27
27
  desc: 'A lot of greate products'
28
28
 
@@ -32,22 +32,27 @@ match %w[products#popular products#new_release], {
32
32
  }
33
33
 
34
34
  # Can contain dynamic content based on controller using assigned ivar
35
- match 'brands#show' {
35
+ match slug('brands#show') {
36
36
  title { assign(:brand).name }
37
37
  }
38
38
 
39
+ # Match with request fullpath
40
+ match path('/products/special-product') do
41
+ title 'Special Product Detail'
42
+ end
43
+
39
44
  # Custom lookup rule with controller
40
- match ->(controller) { controller.params[:page].to_i == 1 }, {
45
+ match(->(controller) { controller.params[:page].to_i == 1 }) do
41
46
  keywords do
42
47
  search = assign(:search_object)
43
48
 
44
49
  # do something
45
50
  end
46
- }
51
+ end
47
52
 
48
- # [TODO] Use custom word part
49
- match %w[products#index] do
50
- page_name { "#{page_part} Good products") }
53
+ # Use custom word part
54
+ match slug(products#index) do
55
+ misc(:page_name) { "#{controller.params[:page].to_i} page | Good products") }
51
56
 
52
57
  title :page_name
53
58
  h1 :page_name
@@ -69,6 +74,7 @@ module ApplicationHelper
69
74
  # which returns Seory::Runtime object with configured
70
75
  include Seory::Helper
71
76
  end
77
+ ```
72
78
 
73
79
  ```haml
74
80
  %html
data/lib/seory/dsl.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'seory'
2
2
  require 'seory/page_contents'
3
+ require 'seory/page_condition/build_dsl'
3
4
  require 'seory/repository'
4
5
 
5
6
  module Seory
@@ -16,7 +17,12 @@ module Seory
16
17
 
17
18
  class PageContentsBuilder
18
19
  def initialize(*conditions)
19
- @page_contents = PageContents.new(*conditions)
20
+ @page_contents =
21
+ if conditions.size == 1 && (block = conditions.first).is_a?(Proc)
22
+ PageContents.new(&block)
23
+ else
24
+ PageContents.new(*conditions)
25
+ end
20
26
  end
21
27
 
22
28
  def build!(&block)
@@ -35,6 +41,8 @@ module Seory
35
41
  end
36
42
 
37
43
  class Descriptor
44
+ include Seory::PageCondition::BuildDsl
45
+
38
46
  def initialize(repository)
39
47
  @repository = repository
40
48
  end
@@ -0,0 +1,13 @@
1
+ module Seory
2
+ module PageCondition
3
+ class BlockCondition
4
+ def initialize(block)
5
+ @block = block
6
+ end
7
+
8
+ def match?(controller)
9
+ @block.call(controller)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ require 'seory/page_condition'
2
+
3
+ module Seory
4
+ module PageCondition
5
+ module BuildDsl
6
+ def slug(slug)
7
+ SlugCondition.new(slug)
8
+ end
9
+
10
+ def path(path)
11
+ PathCondition.new(path)
12
+ end
13
+
14
+ def params(params)
15
+ ParamsCondition.new(params)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ module Seory
2
+ module PageCondition
3
+ class DefaultCondition
4
+ def match?(controller)
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,17 @@
1
+ module Seory
2
+ module PageCondition
3
+ class ParamsCondition
4
+ def self.supposable?(condition_object)
5
+ condition_object.is_a?(Hash)
6
+ end
7
+
8
+ def initialize(params)
9
+ @params = params
10
+ end
11
+
12
+ def match?(controller)
13
+ @params.all? {|k, v| controller.params[k] == v }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,14 @@
1
+ module Seory
2
+ module PageCondition
3
+ class PathCondition
4
+ def initialize(path, exact_match = false)
5
+ @path = path
6
+ @exact_match = exact_match
7
+ end
8
+
9
+ def match?(controller)
10
+ controller.request.fullpath.start_with?(@path)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module Seory
2
+ module PageCondition
3
+ class SlugCondition
4
+ def self.supposable?(condition_object)
5
+ controller, action = condition_object.to_s.split('#')
6
+ controller && action
7
+ end
8
+
9
+ def initialize(slug)
10
+ @slug = slug
11
+ end
12
+
13
+ def match?(controller)
14
+ action_slug(controller) == @slug
15
+ end
16
+
17
+ def action_slug(controller)
18
+ [controller.controller_name, controller.action_name].join('#')
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,32 @@
1
+ require 'seory'
2
+ require 'seory/page_condition/block_condition'
3
+ require 'seory/page_condition/default_condition'
4
+ require 'seory/page_condition/params_condition'
5
+ require 'seory/page_condition/path_condition'
6
+ require 'seory/page_condition/slug_condition'
7
+
8
+ module Seory
9
+ module PageCondition
10
+ class SupposionFailed < Seory::Error; end
11
+ extend self
12
+
13
+ def [](condition)
14
+ if condition == :default
15
+ DefaultCondition.new
16
+ elsif condition.respond_to?(:match?)
17
+ condition
18
+ else
19
+ suppose(condition)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def suppose(condition)
26
+ klass = [ParamsCondition, SlugCondition].detect {|klass| klass.supposable?(condition) }
27
+ raise SupposionFailed.new(condition.inspect) unless klass
28
+
29
+ klass.new(condition)
30
+ end
31
+ end
32
+ end
@@ -1,4 +1,6 @@
1
1
  require 'seory'
2
+ require 'seory/page_condition'
3
+
2
4
  require 'active_support/all'
3
5
 
4
6
  module Seory
@@ -6,7 +8,13 @@ module Seory
6
8
 
7
9
  class PageContents
8
10
  def initialize(*conditions, &block)
9
- @conditions = block_given? ? block : conditions
11
+ @conditions =
12
+ if block_given?
13
+ [PageCondition::BlockCondition.new(block)]
14
+ else
15
+ conditions.map {|condition| Seory::PageCondition[condition] }
16
+ end
17
+
10
18
  raise EmptyCondition if @conditions.blank?
11
19
 
12
20
  @contents = {}
@@ -21,19 +29,13 @@ module Seory
21
29
  end
22
30
 
23
31
  def match?(controller)
24
- return true if @conditions == [:default]
32
+ return true if default?
25
33
 
26
- if @conditions.respond_to?(:call)
27
- @conditions.call(controller)
28
- else
29
- @conditions.include?(action_slug(controller))
30
- end
34
+ @conditions.any? {|condition| condition.match?(controller) }
31
35
  end
32
36
 
33
- private
34
-
35
- def action_slug(controller)
36
- [controller.controller_name, controller.action_name].join('#')
37
+ def default?
38
+ @conditions.all? {|c| c.is_a?(Seory::PageCondition::DefaultCondition) }
37
39
  end
38
40
  end
39
41
  end
@@ -12,7 +12,12 @@ module Seory
12
12
 
13
13
  def lookup(controller)
14
14
  page_contents = @store.detect {|page| page.match?(controller) }
15
- Seory::Runtime.new(page_contents, controller)
15
+
16
+ Seory::Runtime.new(page_contents, controller, default)
17
+ end
18
+
19
+ def default
20
+ @store.detect(&:default?)
16
21
  end
17
22
  end
18
23
  end
data/lib/seory/runtime.rb CHANGED
@@ -8,9 +8,10 @@ module Seory
8
8
 
9
9
  attr_reader :controller
10
10
 
11
- def initialize(page_contents, controller)
11
+ def initialize(page_contents, controller, fallback = nil)
12
12
  @page_contents = page_contents
13
13
  @controller = controller
14
+ @fallback = fallback
14
15
  end
15
16
 
16
17
  def assigns(name)
@@ -28,14 +29,21 @@ module Seory
28
29
  private
29
30
 
30
31
  def calculate_content_for(name)
31
- case page_content = @page_contents.content_for(name)
32
+ case page_content = lookup_content_for(name)
32
33
  when String
33
34
  page_content
35
+ when Symbol
36
+ calculate_content_for(page_content)
34
37
  when ->(o) { o.respond_to?(:call) }
35
38
  instance_exec(&page_content)
36
39
  else
37
40
  raise 'BUG'
38
41
  end
39
42
  end
43
+
44
+ def lookup_content_for(name)
45
+ @page_contents.content_for(name) || \
46
+ @fallback.try {|fb| fb.content_for(name) }
47
+ end
40
48
  end
41
49
  end
data/lib/seory/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Seory
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -2,39 +2,90 @@ require 'spec_helper'
2
2
  require 'seory/dsl'
3
3
 
4
4
  describe Seory::Dsl do
5
- let(:seory_class) { Object.new.extend(Seory::Dsl) }
6
- before do
7
- seory_class.describe do
8
- match 'products#index' do
9
- title 'My Great Product'
10
- h1 'Great Product Name'
11
-
12
- misc :option, 'static optional val'
13
- end
5
+ subject(:seory) { seory_class.lookup(controller) }
6
+
7
+ context 'with traditional syntax' do
8
+ let(:seory_class) { Object.new.extend(Seory::Dsl) }
9
+ before do
10
+ seory_class.describe do
11
+ match ->(c) { c.controller_name == 'reports' } do
12
+ title 'Useful reports'
13
+ end
14
+
15
+ match 'products#index' do
16
+ title 'My Great Product'
17
+ h1 'Great Product Name'
14
18
 
15
- default do
16
- title 'Misc site'
17
- h1 { controller.controller_name.upcase }
19
+ misc :option, 'static optional val'
20
+ end
18
21
 
19
- misc(:option) { "dynamic option name at #{controller.controller_name}" }
22
+ default do
23
+ title 'Misc site'
24
+ h1 { controller.controller_name.upcase }
25
+ h2 'default h2'
26
+
27
+ misc(:option) { "dynamic option name at #{controller.controller_name}" }
28
+ end
20
29
  end
21
30
  end
22
- end
23
31
 
24
- subject(:seory) { seory_class.lookup(controller) }
32
+ context 'at reports#index / match with proc' do
33
+ let(:controller) { double('controller', controller_name: 'reports', action_name: 'index') }
34
+
35
+ specify { expect(seory.title).to eq 'Useful reports' }
36
+ end
37
+
38
+ context 'at products#index' do
39
+ let(:controller) { double('controller', controller_name: 'products', action_name: 'index') }
40
+
41
+ specify { expect(seory.title).to eq 'My Great Product' }
42
+ specify { expect(seory.h1).to eq 'Great Product Name' }
43
+ specify { expect(seory.misc(:option)).to eq 'static optional val' }
44
+
45
+ specify { expect(seory.h2).to eq 'default h2' }
46
+ end
25
47
 
26
- context 'at products#index' do
27
- let(:controller) { double('controller', controller_name: 'products', action_name: 'index') }
48
+ context 'at misc#show' do
49
+ let(:controller) { double('controller', controller_name: 'misc', action_name: 'show') }
28
50
 
29
- specify { expect(seory.title).to eq 'My Great Product' }
30
- specify { expect(seory.h1).to eq 'Great Product Name' }
31
- specify { expect(seory.misc(:option)).to eq 'static optional val' }
51
+ specify { expect(seory.h1).to eq 'MISC' }
52
+ specify { expect(seory.misc(:option)).to eq 'dynamic option name at misc' }
53
+ end
32
54
  end
33
55
 
34
- context 'at misc#show' do
35
- let(:controller) { double('controller', controller_name: 'misc', action_name: 'show') }
56
+ context 'with matcher build dsl syntax' do
57
+ let(:seory_class) { Object.new.extend(Seory::Dsl) }
58
+ before do
59
+ seory_class.describe do
60
+ match path('/products/special-product') do
61
+ title 'Special Product Detail'
62
+ end
63
+
64
+ match slug('products#show') do
65
+ title 'Great Product Detail'
66
+ end
67
+ end
68
+ end
69
+
70
+ context 'at products#show' do
71
+ let(:controller) do
72
+ double('controller', controller_name: 'products', action_name: 'show', params: {id: 42}).tap do |c|
73
+ allow(c).to receive_message_chain(:request, :fullpath) { '/products/42' }
74
+ end
75
+ end
76
+
77
+ specify { expect(seory.title).to eq 'Great Product Detail' }
78
+ end
79
+
80
+ context 'at special product with path /products/special-product (although products#show)' do
81
+ let(:controller) do
82
+ double('controller', controller_name: 'products', action_name: 'show').tap do |c|
83
+ allow(c).to receive_message_chain(:request, :fullpath) { '/products/special-product' }
84
+ end
85
+ end
36
86
 
37
- specify { expect(seory.h1).to eq 'MISC' }
38
- specify { expect(seory.misc(:option)).to eq 'dynamic option name at misc' }
87
+ specify { expect(seory.title).to eq 'Special Product Detail' }
88
+ end
39
89
  end
90
+
40
91
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ require 'seory/page_condition/path_condition'
3
+
4
+ describe Seory::PageCondition::PathCondition do
5
+ let(:controller) { double('controller') }
6
+ let(:path_condition) do
7
+ Seory::PageCondition::PathCondition.new('/users/alice')
8
+ end
9
+
10
+ context 'Accessed to /users/alice (controller: users, action: show, id: alice)' do
11
+ before do
12
+ allow(controller).to receive_message_chain(:request, :fullpath) { '/users/alice' }
13
+ end
14
+
15
+ specify { expect(path_condition.match?(controller)).to be_truthy }
16
+ end
17
+
18
+ context 'Accessed to /users/bob (controller: users, action: show, id: bob)' do
19
+ before do
20
+ allow(controller).to receive_message_chain(:request, :fullpath) { '/users/bob' }
21
+ end
22
+
23
+ specify { expect(path_condition.match?(controller)).to be_falsy }
24
+ end
25
+ end
@@ -26,6 +26,16 @@ describe Seory::PageContents do
26
26
 
27
27
  specify { expect(seory_def.content_for(:title).call).to eq 'A title' }
28
28
  end
29
+
30
+ context 'define aliased content' do
31
+ before do
32
+ seory_def.define(:title) { 'A title' }
33
+
34
+ seory_def.define(:h1, :title)
35
+ end
36
+
37
+ specify { expect(seory_def.content_for(:h1)).to eq :title }
38
+ end
29
39
  end
30
40
 
31
41
  describe 'condition and #match?' do
@@ -58,5 +68,54 @@ describe Seory::PageContents do
58
68
  expect(page_contents.match?(controller)).to be_truthy
59
69
  end
60
70
  end
71
+
72
+ describe 'hash conditions' do
73
+ let(:controller) { double('controller', params: params.with_indifferent_access) }
74
+
75
+ context 'when the condition exactly equals the params' do
76
+ let(:params) { { "controller" => 'users', "action" => 'show' } }
77
+ let(:condition) { { controller: 'users', action: 'show' } }
78
+
79
+ specify do
80
+ expect(init_with(condition).match?(controller)).to be_truthy
81
+ end
82
+ end
83
+
84
+ context 'when the condition is a sub-hash of the params' do
85
+ let(:params) { { "controller" => 'users', "action" => 'show', "id" => "123" } }
86
+ let(:condition) { { controller: 'users', action: 'show' } }
87
+
88
+ specify do
89
+ expect(init_with(condition).match?(controller)).to be_truthy
90
+ end
91
+ end
92
+
93
+ context 'when the condition differs with the params' do
94
+ let(:params) { { "controller" => 'users', "action" => 'show' } }
95
+ let(:condition) { { controller: 'users', action: 'index' } }
96
+
97
+ specify do
98
+ expect(init_with(condition).match?(controller)).to be_falsy
99
+ end
100
+ end
101
+ end
102
+
103
+ describe 'proc conditions' do
104
+ let(:page_content) do
105
+ init_with {|c| c.controller_name == 'users' }
106
+ end
107
+
108
+ specify 'match UsersController' do
109
+ allow(controller).to receive(:controller_name) { 'users' }
110
+
111
+ expect(page_content.match?(controller)).to be_truthy
112
+ end
113
+
114
+ specify 'not match GoodsController' do
115
+ allow(controller).to receive(:controller_name) { 'goods' }
116
+
117
+ expect(page_content.match?(controller)).to be_falsy
118
+ end
119
+ end
61
120
  end
62
121
  end
@@ -46,4 +46,27 @@ describe Seory::Runtime do
46
46
 
47
47
  specify { expect(seory.title).to eq 'Good Shop with 42 products!' }
48
48
  end
49
+
50
+ context 'Custom content created by misc()' do
51
+ before do
52
+ page_contents.define(:custom, 'custom variable')
53
+
54
+ page_contents.define(:title) { misc(:custom).upcase }
55
+ end
56
+
57
+ specify 'it was also accessible from other content' do
58
+ expect(seory.title).to eq 'CUSTOM VARIABLE'
59
+ end
60
+ end
61
+
62
+ context 'defined aliased content' do
63
+ before do
64
+ page_contents.define(:title) { 'A title' }
65
+ page_contents.define(:h1, :title)
66
+ end
67
+
68
+ specify 'it was also accessible from other content' do
69
+ expect(seory.h1).to eq 'A title'
70
+ end
71
+ end
49
72
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seory
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - moro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-05 00:00:00.000000000 Z
11
+ date: 2014-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -62,18 +62,27 @@ extra_rdoc_files: []
62
62
  files:
63
63
  - ".gitignore"
64
64
  - ".rspec"
65
+ - ".travis.yml"
65
66
  - Gemfile
66
67
  - LICENSE.txt
67
68
  - README.md
68
69
  - Rakefile
69
70
  - lib/seory.rb
70
71
  - lib/seory/dsl.rb
72
+ - lib/seory/page_condition.rb
73
+ - lib/seory/page_condition/block_condition.rb
74
+ - lib/seory/page_condition/build_dsl.rb
75
+ - lib/seory/page_condition/default_condition.rb
76
+ - lib/seory/page_condition/params_condition.rb
77
+ - lib/seory/page_condition/path_condition.rb
78
+ - lib/seory/page_condition/slug_condition.rb
71
79
  - lib/seory/page_contents.rb
72
80
  - lib/seory/repository.rb
73
81
  - lib/seory/runtime.rb
74
82
  - lib/seory/version.rb
75
83
  - seory.gemspec
76
84
  - spec/seory/dsl_spec.rb
85
+ - spec/seory/page_condition/path_condition_spec.rb
77
86
  - spec/seory/page_contents_spec.rb
78
87
  - spec/seory/runtime_spec.rb
79
88
  - spec/spec_helper.rb
@@ -103,6 +112,7 @@ specification_version: 4
103
112
  summary: SEO contents manager for Rails.
104
113
  test_files:
105
114
  - spec/seory/dsl_spec.rb
115
+ - spec/seory/page_condition/path_condition_spec.rb
106
116
  - spec/seory/page_contents_spec.rb
107
117
  - spec/seory/runtime_spec.rb
108
118
  - spec/spec_helper.rb