rack-r 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *~
6
+ .#*
7
+ \#*
data/.rvmrc ADDED
@@ -0,0 +1,81 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
+ # development environment upon cd'ing into the directory
5
+
6
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
7
+ environment_id="ruby-1.8.7-p357@rack-r"
8
+
9
+ #
10
+ # Uncomment the following lines if you want to verify rvm version per project
11
+ #
12
+ # rvmrc_rvm_version="1.10.2" # 1.10.1 seams as a safe start
13
+ # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
+ # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
+ # return 1
16
+ # }
17
+ #
18
+
19
+ #
20
+ # Uncomment following line if you want options to be set only for given project.
21
+ #
22
+ # PROJECT_JRUBY_OPTS=( --1.9 )
23
+ #
24
+ # The variable PROJECT_JRUBY_OPTS requires the following to be run in shell:
25
+ #
26
+ # chmod +x ${rvm_path}/hooks/after_use_jruby_opts
27
+ #
28
+
29
+ #
30
+ # First we attempt to load the desired environment directly from the environment
31
+ # file. This is very fast and efficient compared to running through the entire
32
+ # CLI and selector. If you want feedback on which environment was used then
33
+ # insert the word 'use' after --create as this triggers verbose mode.
34
+ #
35
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
36
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
37
+ then
38
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
39
+
40
+ if [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]]
41
+ then
42
+ . "${rvm_path:-$HOME/.rvm}/hooks/after_use"
43
+ fi
44
+ else
45
+ # If the environment file has not yet been created, use the RVM CLI to select.
46
+ if ! rvm --create use "$environment_id"
47
+ then
48
+ echo "Failed to create RVM environment '${environment_id}'."
49
+ return 1
50
+ fi
51
+ fi
52
+
53
+ #
54
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
55
+ # it be automatically loaded. Uncomment the following and adjust the filename if
56
+ # necessary.
57
+ #
58
+ # filename=".gems"
59
+ # if [[ -s "$filename" ]]
60
+ # then
61
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
62
+ # fi
63
+
64
+ # If you use bundler, this might be useful to you:
65
+ # if [[ -s Gemfile ]] && ! command -v bundle >/dev/null
66
+ # then
67
+ # printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
68
+ # gem install bundler
69
+ # fi
70
+ # if [[ -s Gemfile ]] && command -v bundle
71
+ # then
72
+ # bundle install
73
+ # fi
74
+
75
+ if [[ $- == *i* ]] # check for interactive shells
76
+ then
77
+ echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
78
+ else
79
+ echo "Using: $GEM_HOME" # don't use colors in interactive shells
80
+ fi
81
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in aizuchi.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Phil Hofmann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,106 @@
1
+ RackR - Use R in your Rack stack
2
+ ================================
3
+
4
+ RackR is a Rack middleware which integrates R into a Rack based web
5
+ application (like Rails). With RackR in place displaying graphs is as
6
+ simple as rendering R code into your output. E.g.
7
+
8
+ <script type='text/r'>
9
+ png('sinus.png')
10
+ plot(sin)
11
+ </script>
12
+
13
+ RackR will pick this up on its way out and replace it with an empty
14
+ container and some JavaScript code to perform an immediate async
15
+ request for processing the R code.
16
+
17
+ RackR will answer to this reqyest with processing the R code in a temp
18
+ directory, then searching this directory for displayable content and
19
+ finally return the html code for display. So the example above will
20
+ eventually turn into something like this.
21
+
22
+ <div>
23
+ <img src='/path/to/sinus.png' />
24
+ <pre>
25
+ content of Rout file (stdout of R)
26
+ </pre>
27
+ </div>
28
+
29
+ Almost everything can conveniently be configured in a YAML file. RackR
30
+ will create a sample config file in `config/rack-r.yml` or any other
31
+ path given.
32
+
33
+
34
+ Install in Rails
35
+ ----------------
36
+
37
+ Put the following in your Gemfile and run `bundle install` or let
38
+ [Guard](https://github.com/guard/guard-bundler) kick in.
39
+
40
+ gem 'rack-r', :require => 'rack_r'
41
+
42
+ In Rails 3.2 you will have to put this somewhere
43
+
44
+ require 'rack_r/railtie'
45
+
46
+
47
+ Using RackR outside of Rails
48
+ ----------------------------
49
+
50
+ require 'rack_r/middleware'
51
+ use RackR::Middleware, :config => 'path/to/config/rack-r.yml'
52
+
53
+
54
+ Dependencies
55
+ ------------
56
+
57
+ These instructions are for Debian Squeeze. Install R.
58
+
59
+ apt-get install r-base r-cran-dbi
60
+
61
+ Alternatively you can use the `rodbc` package.
62
+
63
+ apt-get install r-cran-rodbc
64
+
65
+ The RackR-Header is a pice of R code that gets prepended to every R
66
+ script which is processed by RackR. Idealy it will read you database
67
+ config and provide a seperate connection to your database via a DBI
68
+ compatible `con` object.
69
+
70
+ If you want RackR to automatically connect R script to yoyr Rails
71
+ database it is a good idea to install Jeremy Stephens' YAML for R.
72
+
73
+ wget http://cran.r-project.org/src/contrib/yaml_2.1.4.tar.gz
74
+ R CMD INSTALL yaml_2.1.4.tar.gz
75
+
76
+ ### SQLite
77
+
78
+ wget http://cran.r-project.org/src/contrib/RSQLite_0.11.1.tar.gz
79
+ R CMD INSTALL RSQLite_0.11.1.tar.gz
80
+
81
+ ### MySQL
82
+
83
+ apt-get install r-cran-rmysql
84
+
85
+ The whole RackR-Header is a work in progress, if you have to adjust it
86
+ to your database config, please consider to contribute your addition.
87
+
88
+
89
+ Trouble shooting
90
+ ----------------
91
+
92
+ Browse to /rack-r/ (including the trailing slash!) to see if RackR is
93
+ working. If so it should respond with "RackR OK."
94
+
95
+
96
+ Patches and the like
97
+ --------------------
98
+
99
+ If you run into bugs, have suggestions or patches feel free to drop me
100
+ a line.
101
+
102
+
103
+ License
104
+ -------
105
+
106
+ RackR is released under MIT License, see LICENSE.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/TODO ADDED
File without changes
data/lib/rack_r.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "rack_r/railtie" if defined? Rails
2
+
@@ -0,0 +1,224 @@
1
+ require 'ostruct'
2
+ require 'yaml'
3
+ require 'erb'
4
+
5
+ require 'csv'
6
+
7
+ module RackR
8
+ class Middleware < Struct.new :app, :options
9
+
10
+ def call(env)
11
+ @env = env
12
+ return call_app unless config.enabled
13
+ if get? and md = match_path
14
+ key = md.to_a.last
15
+ return [200, {}, ['RackR OK.']] if key.empty?
16
+ process key
17
+ else
18
+ extract
19
+ end
20
+ end
21
+
22
+ def call_app
23
+ app.call(@env)
24
+ end
25
+
26
+ def extract
27
+ status, headers, response = call_app
28
+ if headers["Content-Type"] =~ /text\/html|application\/xhtml\+xml/
29
+ # TODO if contains <script type="text/r">
30
+ body = ""
31
+ response.each { |part| body << part }
32
+ while md = body.match(node_regex)
33
+ tempdir = temp_dir
34
+ key = File.basename(tempdir)
35
+ r_script = ERB.new(config.r_header).result(binding) + md.to_a.last
36
+ write_file(File.join(tempdir, config.r_file), r_script)
37
+ body.sub!(node_regex, ajaxer(key))
38
+ end
39
+ headers["Content-Length"] = body.length.to_s
40
+ response = [ body ]
41
+ end
42
+ [ status, headers, response ]
43
+ end
44
+
45
+ def process(key)
46
+ path = temp_dir(key)
47
+ return call_app unless File.directory?(path) # TODO render error msg
48
+ time = exec_r_script(config.r_file, path)
49
+ files = Dir.entries(path).sort
50
+ # build body
51
+ body = [ config.html.prefix ]
52
+ files.each do |file|
53
+ config.templates.each do |template|
54
+ if file =~ Regexp.new(template['pattern'], Regexp::IGNORECASE)
55
+ src = File.join(path, file)
56
+ eval(template['process']) unless template['process'].nil?
57
+ body << ERB.new(template['template']).result(binding)
58
+ end
59
+ end
60
+ end
61
+ # TODO remove temp dir
62
+ body << config.html.suffix
63
+ [ 200, { "Content-Type" => "text/html" }, body ]
64
+ end
65
+
66
+ # return true if request method is GET
67
+ def get?
68
+ @env["REQUEST_METHOD"] == "GET"
69
+ end
70
+
71
+ def path_regex
72
+ Regexp.new "^#{config.url_scope}/(.*)"
73
+ end
74
+
75
+ def node_regex
76
+ opts = Regexp::IGNORECASE + Regexp::MULTILINE
77
+ Regexp.new config.node_regex, opts
78
+ end
79
+
80
+ def path_info
81
+ @env["PATH_INFO"]
82
+ end
83
+
84
+ def match_path
85
+ path_info.match(path_regex)
86
+ end
87
+
88
+ def exec_r_script(file, path=nil)
89
+ cmd = path.nil? ? "R CMD BATCH #{file}" :
90
+ "(cd #{path} && R CMD BATCH #{file})"
91
+ %x[#{cmd}]
92
+ end
93
+
94
+ def temp_dir(key=nil)
95
+ return Dir.mktmpdir(config.temp.prefix, config.temp.dir) if key.nil?
96
+ File.join config.temp.dir, key
97
+ end
98
+
99
+ def write_file(path, content)
100
+ ::File.open(path, 'w') { |f| f.puts content }
101
+ end
102
+
103
+ def public_path
104
+ config.public_path.tap do |path|
105
+ FileUtils.mkdir_p(path) unless File.directory?(path)
106
+ end
107
+ end
108
+
109
+ def ajaxer(key)
110
+ ERB.new(config.ajaxer).result(binding)
111
+ end
112
+
113
+ def default_config
114
+ ::File.read(__FILE__).gsub(/.*__END__\n/m, '')
115
+ end
116
+
117
+ def config_path
118
+ options[:config].tap do |path|
119
+ raise "no config path given" unless path
120
+ end
121
+ end
122
+
123
+ def config
124
+ return @config unless @config.nil?
125
+ write_file(config_path, default_config) unless ::File.exist?(config_path)
126
+ @config = deep_ostruct(::File.open(config_path) { |yf| YAML::load(yf) })
127
+ end
128
+
129
+ private
130
+
131
+ def deep_ostruct(hash)
132
+ OpenStruct.new(hash).tap do |ostruct|
133
+ hash.keys.each do |key|
134
+ if ostruct.send(key).is_a?(Hash)
135
+ ostruct.send("#{key}=", deep_ostruct(hash[key]))
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+ end
142
+ end
143
+
144
+ __END__
145
+ # RackR -- process R on the fly
146
+ # RackR depends on jQuery >= 1.4.4
147
+ #
148
+ # changes to this file will not be picked up
149
+ # without a restart of your app
150
+ #
151
+ enabled: true
152
+ url_scope: /rack-r
153
+ public_path: public/system/rack-r
154
+ public_url: /system/rack-r
155
+ temp:
156
+ dir: /tmp
157
+ prefix: rr_
158
+ r_file: script.R
159
+ r_header: |
160
+ # modify this header in rack-r config file
161
+ library(yaml)
162
+ library(DBI)
163
+ library(RSQLite)
164
+ root <- '<%= Rails.root %>'
165
+ dbconf <- yaml.load_file(paste(root, '/config/database.yml', sep=''))
166
+ dbfile <- paste(root, '/', dbconf$development$database, sep='')
167
+ drv <- dbDriver("SQLite")
168
+ con <- dbConnect(drv, dbname=dbfile)
169
+ ajaxer: |
170
+ <div class='rack_r' id='<%= key %>'>Processing R...</div>
171
+ <script type='text/javascript'>
172
+ var url = '<%= config.url_scope %>/<%= key %>';
173
+ $.ajax(url, { success: function(data) { $('#<%= key %>').html(data); } });
174
+ </script>
175
+ html:
176
+ prefix: <div class='rack_r_out'>
177
+ suffix: </div>
178
+ templates:
179
+ - pattern: .svg$
180
+ process: |
181
+ svg = File.read(src)
182
+ template: |
183
+ <%= svg %>
184
+ - pattern: .(jpg|jpeg|png)$
185
+ process: |
186
+ # TODO build dst with key, otherwise may lead to undesired results
187
+ dst = File.join(public_path, file)
188
+ FileUtils.cp(src, dst)
189
+ url = "#{config.public_url}/#{file}"
190
+ template: |
191
+ <img src='<%= url %>' />
192
+ - pattern: .csv$
193
+ process: |
194
+ table = CSV.read(src)
195
+ # TODO build dst with key, otherwise may lead to undesired results
196
+ dst = File.join(public_path, file)
197
+ FileUtils.cp(src, dst)
198
+ url = "#{config.public_url}/#{file}"
199
+ template: |
200
+ <a href='<%= url %>'><%= file %></a>
201
+ <table>
202
+ <% table.each do |row| %>
203
+ <tr>
204
+ <% row.each do |col| %>
205
+ <td><%= col %></td>
206
+ <% end %>
207
+ </tr>
208
+ <% end %>
209
+ </table>
210
+ - pattern: .Rout$
211
+ process: |
212
+ rout = File.read(src)
213
+ template: |
214
+ <pre><%= rout %></pre>
215
+ node_regex: <script\s+type=['"]text/r['"]\s*>(.*?)</script>
216
+ #
217
+ # uncomment the following two lines, if your project
218
+ # doesn't use jquery already
219
+ # javascripts:
220
+ # - http://code.jquery.com/jquery-1.5.1.min.js
221
+ # or this line if you want to ship it yourself
222
+ # - /javascripts/jquery-1.5.1.min.js
223
+ # uncomment the following line, in case your project uses prototype
224
+ # jquery_noconflict: true
@@ -0,0 +1,25 @@
1
+ require 'rack_r/middleware'
2
+
3
+ module RackR
4
+
5
+ major, minor, patch = Rails.version.split('.').map { |s| s.to_i }
6
+
7
+ case major
8
+ when 2
9
+ Rails.configuration.middleware.use RackR::Middleware,
10
+ :config => File.expand_path('config/rack-r.yml', RAILS_ROOT)
11
+
12
+ when 3
13
+ class Railtie < Rails::Railtie
14
+ initializer "rack_r.insert_middleware" do |app|
15
+ app.config.middleware.use "RackR::Middleware",
16
+ :config => File.expand_path('config/rack-r.yml', Rails.root)
17
+ end
18
+ end
19
+
20
+ else
21
+ raise "Unknown Rails version #{Rails.version}"
22
+ end
23
+
24
+ end
25
+
@@ -0,0 +1,3 @@
1
+ module RackR
2
+ VERSION = "0.1.0"
3
+ end
data/rack-r.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "rack_r/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "rack-r"
6
+ s.version = RackR::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Phil Hofmann"]
9
+ s.email = ["phil@branch14.org"]
10
+ s.homepage = "http://branch14.org/rack-r"
11
+ s.summary = %q{Use R in your Rack stack}
12
+ s.description = %q{Use R in your Rack stack}
13
+
14
+ # s.rubyforge_project = "rack-r"
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", "rails"]
20
+ end
data/test/example.r ADDED
@@ -0,0 +1,38 @@
1
+ # y mntl. Rate
2
+ # f Franchise
3
+ # s Selbstbehalt
4
+ # m Selbstbehalt max.
5
+
6
+ png('insurance.png')
7
+
8
+ costf <- function(y, f, s=0.1, m=700) {
9
+ return(function(x) {
10
+ (y * 12) + min(f, x) + max(0, min(m - f, s * (max(f, x) - f)))
11
+ })
12
+ }
13
+
14
+ f0 <- costf( 95.70, 0 )
15
+ f1 <- costf( 90.00, 100 )
16
+ f2 <- costf( 84.10, 200 )
17
+ f4 <- costf( 72.40, 400 )
18
+ f6 <- costf( 60.70, 600 )
19
+
20
+ x_max <- 7250
21
+ x <- seq(0, x_max, by=10)
22
+ plot(x, x, type='l', lty=3,
23
+ xlim=range(0, x_max),
24
+ ylim=range(500, 2000),
25
+ xlab='Kosten Verursacht',
26
+ ylab='Kosten Gezahlt')
27
+
28
+ lines(x, apply(array(x), 1, f0), col='green')
29
+ lines(x, apply(array(x), 1, f1))
30
+ lines(x, apply(array(x), 1, f2))
31
+ lines(x, apply(array(x), 1, f4))
32
+ lines(x, apply(array(x), 1, f6), col='red')
33
+
34
+ f <- function(x) { return(f0(x) - f6(x)) }
35
+ lower <- uniroot(f, c(400, 600))
36
+ upper <- uniroot(f, c(2500, 3000))
37
+ abline(v=lower$root, lty=2)
38
+ abline(v=upper$root, lty=2)
data/test/helper.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'rack_r'
8
+ require 'rack_r/middleware'
9
+
10
+ class Test::Unit::TestCase
11
+ end
@@ -0,0 +1,153 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+ require 'rack/mock'
3
+
4
+ class TestRackR < Test::Unit::TestCase
5
+
6
+ CONFIGFILE = '/tmp/test_rack_r'
7
+ File.unlink(CONFIGFILE) if File.exist?(CONFIGFILE)
8
+
9
+ EXPECTED_CODE = /class='rack_r'/
10
+
11
+ context "Util" do
12
+ should "create proper temp dir" do
13
+ td = app.temp_dir
14
+ assert File.directory?(td)
15
+
16
+ base = File.basename(td)
17
+ assert_equal td, app.temp_dir(base)
18
+
19
+ assert FileUtils.rm_rf(td)
20
+ assert !File.exist?(td)
21
+ end
22
+ end
23
+
24
+ context "Proper regexs" do
25
+ should "detect r code if present" do
26
+ assert_match app.node_regex, HTML_POSITIVE
27
+ end
28
+
29
+ should "not detect r code if none is present" do
30
+ assert_no_match app.node_regex, HTML_NEGATIVE
31
+ end
32
+ end
33
+
34
+ context "Embedding payload" do
35
+ should "place the payload in body of an HTML request" do
36
+ assert_match EXPECTED_CODE, request.body
37
+ end
38
+
39
+ should "place the payload in body of an XHTML request" do
40
+ response = request(:content_type => 'application/xhtml+xml')
41
+ assert_match EXPECTED_CODE, response.body
42
+ end
43
+
44
+ should "not place the payload in a non HTML request" do
45
+ response = request(:content_type => 'application/xml', :body => [XML])
46
+ assert_no_match EXPECTED_CODE, response.body
47
+ end
48
+
49
+ should "not place the playload in a document not containing r code" do
50
+ response = request(:body => HTML_NEGATIVE)
51
+ assert_no_match EXPECTED_CODE, response.body
52
+ end
53
+ end
54
+
55
+ context "Processing R" do
56
+ should 'detect get request' do
57
+ request(:path => "/rack-r/rr-some-random-key")
58
+ assert @app.get?
59
+ end
60
+
61
+ should 'detect path' do
62
+ request(:path => "/rack-r/rr-some-random-key")
63
+ assert @app.match_path
64
+ end
65
+
66
+ should 'properly respond to rack_r request' do
67
+ key = 'rr-some-key'
68
+ path = app.temp_dir(key)
69
+ FileUtils.rm_rf(path) if File.exist?(path)
70
+ Dir.mkdir(path)
71
+ src = File.expand_path('../example.r', __FILE__)
72
+ dst = File.join(path, app.config.r_file)
73
+ FileUtils.cp(src, dst)
74
+ response = request(:path => "/rack-r/#{key}")
75
+ assert Dir.entries(path).include?('insurance.png')
76
+ regex = Regexp.new("src='#{@app.config.public_url}/insurance.png'")
77
+ assert_match regex, response.body
78
+ FileUtils.rm_rf(path)
79
+ end
80
+ end
81
+
82
+ # context "Deliver payload" do
83
+ # setup do
84
+ # @expected_file = File.expand_path(File.join(%w(.. .. public) << PAYLOAD), __FILE__)
85
+ # @response = request({}, "/#{PAYLOAD}")
86
+ # end
87
+ #
88
+ # should "deliver #{PAYLOAD}" do
89
+ # expected = File.read(@expected_file)
90
+ # assert expected, @response.body
91
+ # end
92
+ #
93
+ # should "set the content-type correctly" do
94
+ # assert 'text/javascript', @response.body
95
+ # end
96
+ # end
97
+
98
+ private
99
+
100
+ HTML_POSITIVE = <<-EOHTML
101
+ <html>
102
+ <head>
103
+ <title>Sample Page</title>
104
+ </head>
105
+ <body>
106
+ <h2>Here goes some R</h2>
107
+ <script type='text/r'>
108
+ some invalid r code
109
+ </script>
110
+ </body>
111
+ </html>
112
+ EOHTML
113
+
114
+ HTML_NEGATIVE = <<-EOHTML
115
+ <html>
116
+ <head>
117
+ <title>Sample page with no matching node</title>
118
+ </head>
119
+ <body>
120
+ <p>Empty page.</p>
121
+ </body>
122
+ </html>
123
+ EOHTML
124
+
125
+ XML = <<-EOXML
126
+ <?xml version="1.0" encoding="ISO-8859-1"?>
127
+ <user>
128
+ <name>Some Name</name>
129
+ <age>Some Age</age>
130
+ </user>
131
+ EOXML
132
+
133
+ def request(options={})
134
+ path = options.delete(:path) || '/'
135
+ @app = app(options)
136
+ request = Rack::MockRequest.new(@app).get(path)
137
+ yield(@app, request) if block_given?
138
+ request
139
+ end
140
+
141
+ def app(options={})
142
+ options = options.clone
143
+ options[:content_type] ||= "text/html"
144
+ options[:body] ||= [ HTML_POSITIVE ]
145
+ rack_app = lambda do |env|
146
+ [ 200,
147
+ { 'Content-Type' => options.delete(:content_type) },
148
+ options.delete(:body) ]
149
+ end
150
+ RackR::Middleware.new(rack_app, :config => CONFIGFILE)
151
+ end
152
+
153
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-r
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Phil Hofmann
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-04-23 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: Use R in your Rack stack
22
+ email:
23
+ - phil@branch14.org
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - .rvmrc
33
+ - Gemfile
34
+ - LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - TODO
38
+ - lib/rack_r.rb
39
+ - lib/rack_r/middleware.rb
40
+ - lib/rack_r/railtie.rb
41
+ - lib/rack_r/version.rb
42
+ - rack-r.gemspec
43
+ - test/example.r
44
+ - test/helper.rb
45
+ - test/test_rack_r.rb
46
+ homepage: http://branch14.org/rack-r
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ - rails
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.8.23
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Use R in your Rack stack
80
+ test_files: []
81
+