rack-rewrite-dynamic 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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