simple_decorator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in simple_decorator.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # Simple decorator
2
+
3
+ A simple sitemesh-like rack filter for Rails apps
4
+
5
+ This gem lets you specify a url to a place to fetch the layout for your application using a method in you controllers.
6
+
7
+ ## Installation
8
+
9
+ In your Gemfile
10
+
11
+ gem 'simple_decorator', '0.0.1', git: 'git://github.com/Posten-konsernportal/simple_decorator.git'
12
+
13
+ In any controller
14
+
15
+ # usually you put this in your ApplicationController
16
+ # but feel free to override in any other controller
17
+ def decorator_url
18
+ "some url to a velocity style decorator"
19
+ end
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = "spec/**/*_spec.rb"
8
+ end
9
+
10
+ task :default => :spec
@@ -0,0 +1,22 @@
1
+ module SimpleDecorator
2
+ module Controller
3
+ ## this one manages the usual self.included, klass_eval stuff
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ after_filter :call_decorator_url
8
+ end
9
+
10
+
11
+ def call_decorator_url
12
+ return unless respond_to? :decorator_url
13
+
14
+ request.env['simple_decorator.layout.url'] = decorator_url
15
+
16
+ end
17
+
18
+
19
+ end
20
+ end
21
+
22
+ ::ActionController::Base.send :include, SimpleDecorator::Controller
@@ -0,0 +1,19 @@
1
+ require 'rack-plastic'
2
+ require 'open-uri'
3
+
4
+ module SimpleDecorator
5
+ module Filter
6
+ class Decorator < Rack::Plastic
7
+ def change_html_string(html)
8
+ return html unless request.env["simple_decorator.layout.url"]
9
+
10
+ layout = request.env["simple_decorator.layout.url"]
11
+
12
+ decorator = open(layout, :proxy => nil).read
13
+
14
+ weaver = ResponseWeaver.new(decorator)
15
+ weaver.apply(html)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,67 @@
1
+ class ResponseWeaver
2
+
3
+ def initialize(decorator)
4
+ @init_time = Time.now
5
+ @decorator = decorator
6
+ @placeholders = build_placeholders(decorator)
7
+ @fields = keys(@placeholders)
8
+ end
9
+
10
+ def apply(response)
11
+ response_array = @placeholders
12
+
13
+ @fields.each do |tag_name|
14
+ content_for_tag = extract_from_response(response, tag_name)
15
+
16
+ #<title> is nested within <head>, so we will have to remove the <title> tag from the head placeholder
17
+ content_for_tag = remove_nested_tags(content_for_tag)
18
+ response_array[response_array.index("$#{tag_name}")] = content_for_tag
19
+ end
20
+
21
+ #build a response string from the array
22
+ ret = ''
23
+ response_array.each { |str| ret << str }
24
+
25
+ #puts "time since init: #{Time.now - @init_time} "
26
+ ret
27
+ end
28
+
29
+
30
+ private
31
+
32
+ def remove_nested_tags(content)
33
+ @fields.each do |tag_name|
34
+ content = content.gsub(/<#{tag_name}>.*<\/#{tag_name}>/im, '')
35
+ end
36
+ content
37
+ end
38
+
39
+ def extract_from_response(response, tag_name)
40
+ matchdata = /<#{tag_name}>(.*)<\/#{tag_name}>/im.match(response)
41
+ if matchdata
42
+ matchdata[1]
43
+ else
44
+ ""
45
+ end
46
+ end
47
+
48
+ # returns an array containing the enire page, but splitted with keys as separate elements
49
+ # ['<some body html>' , '$title', '<morebody>', '$head', '<more body>']
50
+ def build_placeholders(template_string)
51
+ template_string.split(/(\$[\w]+)/)
52
+ end
53
+
54
+ def keys(page_array)
55
+ ret_keys = []
56
+ page_array.each {|elem| ret_keys << keyname(elem) if key?(elem)}
57
+ ret_keys
58
+ end
59
+
60
+ def key?(str)
61
+ str.start_with?('$')
62
+ end
63
+
64
+ def keyname(str)
65
+ str.gsub(/\$/, '')
66
+ end
67
+ end
@@ -0,0 +1,7 @@
1
+ module SimpleDecorator
2
+ class Railtie < Rails::Railtie
3
+ initializer "simple_decorator.configure_rails_initialization" do |app|
4
+ app.middleware.use SimpleDecorator::Filter::Decorator
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleDecorator
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,10 @@
1
+ require "simple_decorator/version"
2
+
3
+ require 'simple_decorator/filter/response_weaver'
4
+ require 'simple_decorator/filter/decorator'
5
+ require 'simple_decorator/controller'
6
+ require 'simple_decorator/railtie' if defined?(Rails)
7
+
8
+ module SimpleDecorator
9
+
10
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "simple_decorator/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "simple_decorator"
7
+ s.version = SimpleDecorator::VERSION
8
+ s.authors = ["Eirik Lied"]
9
+ s.email = ["eiriklied@gmail.com"]
10
+ s.homepage = "https://github.com/Posten-Konsernportal/simple_decorator"
11
+ s.summary = %q{A ruby sitemesh-like implementation}
12
+ s.description = %q{A simple gem to give sitemesh-like functionality in a rack app using decorators.}
13
+
14
+ s.rubyforge_project = "simple_decorator"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ s.add_development_dependency "rspec"
23
+ s.add_runtime_dependency "rack-plastic"
24
+ end
@@ -0,0 +1,28 @@
1
+ module CustomHtmlMatcher
2
+ class HaveSameMarkup
3
+ def initialize(expected)
4
+ @expected = expected
5
+ end
6
+
7
+ def matches?(target)
8
+ @target = target
9
+ normalize_whitespaces(@target).eql?(normalize_whitespaces(@expected))
10
+ end
11
+ def failure_message
12
+ "expected #{@target} to match #{@expected}"
13
+ end
14
+ def negative_failure_message
15
+ "expected #{@target} not to match #{@expected}"
16
+ end
17
+
18
+ private
19
+ def normalize_whitespaces(str)
20
+ str.gsub(/\s+/, ' ') #replace all whitespace occurences with just once space
21
+ end
22
+ end
23
+
24
+
25
+ def be_same_markup(expected)
26
+ HaveSameMarkup.new(expected)
27
+ end
28
+ end
@@ -0,0 +1,91 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe ResponseWeaver do
4
+
5
+ it "should strip out placeholders in response" do
6
+ response = ResponseWeaver.new('<html>$some_placeholder</html>').apply('Jadajada')
7
+ response.should == "<html></html>"
8
+ end
9
+
10
+ it "should inject a tag from apply to placeholder with matching name" do
11
+ response =
12
+ ResponseWeaver.new('<html><head><script scr="http://jquery.com/jquery.js"/>$head</head><body></body></html>').
13
+ apply('<html class="bladi"><head><title>should be applied</title></head><body></body></html>')
14
+
15
+ response.should == '<html><head><script scr="http://jquery.com/jquery.js"/><title>should be applied</title></head><body></body></html>'
16
+ end
17
+
18
+ it "should be case insensitive when injecting tags into placeholders" do
19
+ response =
20
+ ResponseWeaver.new('<Html><head>$HEad</head><body></body></html>').
21
+ apply('<HTML><HEAD>MYHEADCONTENT</head><body></body></html>')
22
+ response.should == '<Html><head>MYHEADCONTENT</head><body></body></html>'
23
+ end
24
+
25
+ it "should match multiline responses" do
26
+ response =
27
+ ResponseWeaver.new(%{
28
+ <html>
29
+ <head>
30
+ <script scr="http://jquery.com/jquery.js"></script>
31
+ <meta name="description" value="blasbdlasbd"/>
32
+ $head
33
+ </head>
34
+ <body>
35
+ Some body
36
+ $body
37
+ </body>
38
+ </html>
39
+ }).
40
+ apply(%{
41
+ <html>
42
+ <head>
43
+ <head_tag_to_be_applied/>
44
+ </head>
45
+ <body>
46
+ </body>
47
+ </html>
48
+ })
49
+
50
+ response.should be_same_markup(%{
51
+ <html>
52
+ <head>
53
+ <script scr="http://jquery.com/jquery.js"></script>
54
+ <meta name="description" value="blasbdlasbd"/>
55
+ <head_tag_to_be_applied/>
56
+ </head>
57
+ <body>
58
+ Some body
59
+ </body>
60
+ </html>
61
+ })
62
+ end
63
+
64
+ it "should remove nested tags that apply to other placeholders" do
65
+ response =
66
+ ResponseWeaver.new(%{
67
+ <html>
68
+ <head>
69
+ <title>$title</title>
70
+ $head
71
+ </head>
72
+ <body></body>
73
+ </html>
74
+ }).apply(%{
75
+ <html>
76
+ <head><title>This should appear once</title>
77
+ </head>
78
+ <body></body>
79
+ </html>
80
+ })
81
+ response.should be_same_markup(%{
82
+ <html>
83
+ <head>
84
+ <title>This should appear once</title>
85
+ </head>
86
+ <body></body>
87
+ </html>
88
+ })
89
+ end
90
+
91
+ end
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/simple_decorator/filter/response_weaver.rb')
2
+ Dir["#{File.dirname(__FILE__)}/matchers/**/*.rb"].each {|f| require f}
3
+
4
+ RSpec.configure do |config|
5
+ config.include(CustomHtmlMatcher)
6
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_decorator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Eirik Lied
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &2153198560 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *2153198560
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack-plastic
27
+ requirement: &2153198140 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2153198140
36
+ description: A simple gem to give sitemesh-like functionality in a rack app using
37
+ decorators.
38
+ email:
39
+ - eiriklied@gmail.com
40
+ executables: []
41
+ extensions: []
42
+ extra_rdoc_files: []
43
+ files:
44
+ - .gitignore
45
+ - Gemfile
46
+ - README.md
47
+ - Rakefile
48
+ - lib/simple_decorator.rb
49
+ - lib/simple_decorator/controller.rb
50
+ - lib/simple_decorator/filter/decorator.rb
51
+ - lib/simple_decorator/filter/response_weaver.rb
52
+ - lib/simple_decorator/railtie.rb
53
+ - lib/simple_decorator/version.rb
54
+ - simple_decorator.gemspec
55
+ - spec/matchers/have_same_markup.rb
56
+ - spec/response_weaver_spec.rb
57
+ - spec/spec_helper.rb
58
+ homepage: https://github.com/Posten-Konsernportal/simple_decorator
59
+ licenses: []
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project: simple_decorator
78
+ rubygems_version: 1.8.10
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: A ruby sitemesh-like implementation
82
+ test_files:
83
+ - spec/matchers/have_same_markup.rb
84
+ - spec/response_weaver_spec.rb
85
+ - spec/spec_helper.rb