rack-rewrite-dynamic 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.
@@ -8,36 +8,87 @@ module Rack
8
8
 
9
9
  def perform(match, rack_env)
10
10
  if !(match[1] =~ /assets/)
11
- filter_parts = match[1].split(@opts[:separator])
12
- if filter_parts.present?
13
- slugs = filter_parts.map do |slug_candidate|
14
- find_sluggable(slug_candidate)
11
+ filter_parts = parse_filter_parts(match)
12
+ build_return_path(filter_parts, rack_env)
13
+ else
14
+ original_path(rack_env)
15
+ end
16
+ end
17
+
18
+ private
19
+ def build_return_path(filter_parts, rack_env)
20
+ if filter_parts.length > 0
21
+ slugs = filter_parts.map do |candidate|
22
+ find_sluggable(candidate)
15
23
  end
24
+
25
+ filter_params = {}
16
26
  if !slugs.include?(nil)
17
- filter_params = {}
18
27
  slugs.each do |s|
19
- filter_params["#{s[:sluggable_type].underscore}_ids"] ||= []
20
- filter_params["#{s[:sluggable_type].underscore}_ids"] << s[:sluggable_id]
28
+ add_filter_param(filter_params, s)
21
29
  end
22
- return "/#{@opts[:target]}?#{filter_params.to_query}"
23
30
  end
31
+
32
+ return "/#{@opts[:target]}?#{filter_params.to_query}" if filter_params.length > 0
24
33
  end
25
- else
26
- rack_env['REQUEST_URI'] || rack_env['PATH_INFO']
34
+ original_path(rack_env)
35
+ end
36
+
37
+ def parse_filter_parts(match)
38
+ slug_index = 0
39
+
40
+ @opts[:url_parts].map do |url_part|
41
+ if url_part.keys.include?(:static)
42
+ # :)
43
+ elsif url_part.keys.include?(:prefix) || url_part.keys.include?(:suffix)
44
+ slug_index += 1
45
+ if match[slug_index]
46
+ match[slug_index].chomp(url_part[:separator])
47
+ end
48
+ elsif url_part.keys.include?(:groups)
49
+ if match[slug_index+1]
50
+ slug_index += 1
51
+ match[slug_index..-1].each_with_index.map { |slug_group, i| slug_group.split(url_part[:groups][i][:separator]) if slug_group }.flatten
52
+ end
53
+ end
54
+ end.flatten.compact
55
+ end
56
+
57
+ def add_filter_param(filter_params, slug)
58
+ filter_params["#{slug[:sluggable_type].underscore}_ids"] ||= []
59
+ filter_params["#{slug[:sluggable_type].underscore}_ids"] << slug[:sluggable_id]
60
+ end
61
+
62
+ def slug_group_matcher_string(groups)
63
+ groups.map do |group|
64
+ "(#{group[:prefix]}#{filter_string}#{group[:suffix]})?-?"
65
+ end.join
66
+ end
67
+
68
+ def slug_group_matcher(groups)
69
+ Regexp.new(slug_group_matcher_string(groups))
27
70
  end
28
- end
29
71
 
30
- private
31
72
  def build_match_string
32
- match_string = '^'
33
- match_string << "#{@opts[:prefix]}" if @opts[:prefix]
34
- match_string << '\/' + "#{filter_string}"
35
- match_string << "#{@opts[:separator]}#{@opts[:suffix]}" if @opts[:suffix] && @opts[:separator]
36
- match_string << "\/?$"
37
- match_string
73
+ match_string = '^\/'
74
+ match_string << @opts[:url_parts].map do |url_part|
75
+ if url_part.keys.include?(:static)
76
+ "(#{url_part[:static]})"
77
+ elsif url_part.keys.include?(:prefix) || url_part.keys.include?(:suffix)
78
+ "#{url_part[:prefix]}#{filter_string}#{('?' unless url_part[:required])}#{url_part[:separator]}?#{url_part[:suffix]}"
79
+ elsif url_part.keys.include?(:groups)
80
+ slug_group_matcher_string(url_part[:groups]).to_s
81
+ end + suburl_separator(url_part[:required])
82
+ end.join
83
+
84
+ match_string.chomp!(suburl_separator(true))
85
+ match_string.chomp(suburl_separator(false))
38
86
  end
39
87
  def filter_string
40
- '([^\/]+)'
88
+ '(?<slug_groups>[^\/]+)'
89
+ end
90
+ def suburl_separator(required = false)
91
+ "\\/#{'?' unless required}"
41
92
  end
42
93
  end
43
94
  end
@@ -1,7 +1,7 @@
1
1
  module Rack
2
2
  class Rewrite
3
3
  module Dynamic
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.4"
5
5
  end
6
6
  end
7
7
  end
@@ -13,40 +13,97 @@ describe Rack::Rewrite::Dynamic::FilterRewrite do
13
13
  end
14
14
  end
15
15
 
16
- let(:opts) do
17
- {
18
- separator: '-', target: 'outfits', suffix: 'outfits'
19
- }
20
- end
21
- subject { Rack::Rewrite::Dynamic::FilterRewrite.new(opts) }
22
16
  let(:base) { mock(:base) }
17
+ let(:rack_env) { { 'REQUEST_URI' => 'some/path' } }
23
18
 
19
+ let(:opts) { {} }
20
+ subject { Rack::Rewrite::Dynamic::FilterRewrite.new(opts) }
24
21
  its(:opts) { should eq(opts) }
25
22
 
26
- it 'should apply rewrite' do
27
- base.should_receive(:rewrite)
28
- subject.apply_rewrite(base)
23
+ it 'should return the original request if assets' do
24
+ match = ['', 'assets']
25
+ subject.perform(match, rack_env).should eq('some/path')
29
26
  end
30
27
 
31
- describe '#perform' do
32
- let(:match) { ['', 'filter_slug-outfits'] }
33
- let(:rack_env) { { 'REQUEST_URI' => 'some/path' } }
34
- it 'should perform rewrite' do
35
- subject.stub(:find_sluggable) { { sluggable_type: 'color', sluggable_id: 42 } }
36
- subject.perform(match, rack_env).should eq('/outfits?color_ids%5B%5D=42&color_ids%5B%5D=42')
28
+ context 'handle SEO urls like /slug1-slug2-outfits/red-green-colored-from-nike-and-red-mountain' do
29
+ let(:opts) do
30
+ {
31
+ target: 'outfits',
32
+ url_parts: [{suffix: 'outfits', separator: '-'},
33
+ {
34
+ groups: [
35
+ {suffix: '-colored', separator: '-'},
36
+ {prefix: 'from-', separator: '-and-'}
37
+ ]
38
+ }
39
+ ]
40
+ }
37
41
  end
42
+ let(:match) { ['', 'business-', 'red-darkblue', 'nike-and-red-mountain'] }
38
43
 
39
- it 'should return the original request if assets' do
40
- match[1] = 'assets'
41
- subject.perform(match, rack_env).should eq('some/path')
44
+ it 'should apply rewrite' do
45
+ base.should_receive(:rewrite).with(/^\/(?<slug_groups>[^\/]+)?-?outfits\/?((?<slug_groups>[^\/]+)-colored)?-?(from-(?<slug_groups>[^\/]+))?-?/, anything)
46
+ subject.apply_rewrite(base)
47
+ end
48
+
49
+ it 'should perform rewrite' do
50
+ subject.stub(:find_sluggable).with('business'){ { sluggable_type: 'outfit_category', sluggable_id: 42 } }
51
+ subject.stub(:find_sluggable).with('red'){ { sluggable_type: 'color', sluggable_id: 42 } }
52
+ subject.stub(:find_sluggable).with('darkblue'){ { sluggable_type: 'color', sluggable_id: 43 } }
53
+ subject.stub(:find_sluggable).with('nike'){ { sluggable_type: 'brand', sluggable_id: 42 } }
54
+ subject.stub(:find_sluggable).with('red-mountain'){ { sluggable_type: 'brand', sluggable_id: 43 } }
55
+
56
+ subject.perform(match, rack_env).should eq('/outfits?brand_ids%5B%5D=42&brand_ids%5B%5D=43&color_ids%5B%5D=42&color_ids%5B%5D=43&outfit_category_ids%5B%5D=42')
42
57
  end
43
58
 
44
59
  it 'should not return path if slug wasn not found' do
45
60
  subject.stub(:find_sluggable)
46
- subject.perform(match, rack_env).should be_nil
61
+ subject.perform(match, rack_env).should eq('some/path')
47
62
  end
48
-
49
63
  end
50
64
 
65
+ context 'handle SEO urls like /fashion-items/slug1-slug2/red-green-colored-from-nike-or-red-mountain' do
66
+ let(:opts) do
67
+ {
68
+ target: 'products',
69
+ url_parts: [{static: 'fashion-items'},
70
+ {suffix: '', separator: '-'},
71
+ {
72
+ groups: [
73
+ {suffix: '-colored', separator: '-'},
74
+ {prefix: 'from-', separator: '-or-'}
75
+ ]
76
+ }
77
+ ]
78
+ }
79
+ end
80
+ let(:match) { ['', 'tops-shirts', 'blue-red-darkgray', 'nike-or-adidas'] }
81
+
82
+ before :each do
83
+ subject.stub(:find_sluggable).with('tops-shirts'){ { sluggable_type: 'product_category', sluggable_id: 42 } }
84
+ subject.stub(:find_sluggable).with('blue'){ { sluggable_type: 'color', sluggable_id: 42 } }
85
+ subject.stub(:find_sluggable).with('red'){ { sluggable_type: 'color', sluggable_id: 43 } }
86
+ subject.stub(:find_sluggable).with('darkgray'){ { sluggable_type: 'color', sluggable_id: 44 } }
87
+ subject.stub(:find_sluggable).with('nike'){ { sluggable_type: 'brand', sluggable_id: 42 } }
88
+ subject.stub(:find_sluggable).with('adidas'){ { sluggable_type: 'brand', sluggable_id: 43 } }
89
+ end
90
+
91
+ it 'should apply rewrite' do
92
+ base.should_receive(:rewrite).with(/^\/(fashion-items)\/?(?<slug_groups>[^\/]+)?-?\/?((?<slug_groups>[^\/]+)-colored)?-?(from-(?<slug_groups>[^\/]+))?-?/, anything)
93
+ subject.apply_rewrite(base)
94
+ end
95
+
96
+ it 'should perform the rewrite' do
97
+ subject.perform(match, rack_env).should eq('/products?brand_ids%5B%5D=42&brand_ids%5B%5D=43&color_ids%5B%5D=42&color_ids%5B%5D=43&color_ids%5B%5D=44&product_category_ids%5B%5D=42')
98
+ end
99
+
100
+ it 'should perform the rewrite even if some of the slug groups are missing' do
101
+ match = ['', 'tops-shirts', 'blue-red-darkgray']
102
+
103
+ subject.perform(match, rack_env).should eq('/products?color_ids%5B%5D=42&color_ids%5B%5D=43&color_ids%5B%5D=44&product_category_ids%5B%5D=42')
104
+ end
105
+
106
+
107
+ end
51
108
  end
52
109
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-rewrite-dynamic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-18 00:00:00.000000000 Z
12
+ date: 2013-01-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack-rewrite