Permalink
Browse files

Merge pull request #1 from Asquera/rework

Rework as a well-behaving sinatra plugin
  • Loading branch information...
gazay committed Jan 11, 2012
2 parents 959e32d + 2413e6a commit 086dffc7163a37bcf23e8e194498c9bbd5fe8f0f
Showing with 158 additions and 134 deletions.
  1. +17 −0 README.md
  2. +3 −2 gon-sinatra.gemspec
  3. +8 −67 lib/gon-sinatra.rb
  4. +19 −37 lib/gon/sinatra/helpers.rb
  5. +1 −2 lib/gon/sinatra/rabl.rb
  6. +65 −0 lib/gon/sinatra/store.rb
  7. +45 −26 spec/gon/gon_spec.rb
View
@@ -5,10 +5,27 @@ If you need to send some data to your js files and you don't want to do this wit
Now with [Rabl](https://github.com/nesquena/rabl) support!
+Now with [Padrino](https://github.com/padrino/padrino-framework) support as well!
+
For rails use [gon](https://github.com/gazay/gon).
## Usage
+`my_sinatra_application.rb`
+
+``` ruby
+register Gon::Sinatra
+# and if you want to the use Rabl integration
+register Gon::Sinatra::Rabl
+
+#or, in a classy app:
+
+class MySinatraApplication < Sinatra::Base #or Padrino::Application
+ register Gon::Sinatra
+ register Gon::Sinatra::Rabl
+end
+```
+
`views/application.erb`
``` erb
View
@@ -16,8 +16,9 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]
- s.add_dependency "rabl"
s.add_dependency "sinatra"
- s.add_dependency "json"
+
+ s.add_development_dependency "rabl"
+ s.add_development_dependency "json"
s.add_development_dependency "rspec"
end
View
@@ -1,76 +1,17 @@
require 'sinatra'
+require 'gon/sinatra/store'
require 'gon/sinatra/helpers'
-require 'gon/sinatra/rabl'
module Gon
module Sinatra
- class << self
- def all_variables
- @request_env[:gon]
- end
-
- def clear
- @request_env[:gon] = {}
- end
-
- def request_env=(environment)
- @request_env = environment
- @request_env[:gon] ||= {}
- end
-
- def request_env
- if defined?(@request_env)
- return @request_env
- end
- end
-
- def request
- @request_id if defined? @request_id
- end
-
- def request=(request_id)
- @request_id = request_id
- end
-
- def method_missing(m, *args, &block)
- if ( m.to_s =~ /=$/ )
- if public_methods.include? m.to_s[0..-2].to_sym
- raise "You can't use Gon public methods for storing data"
- end
- set_variable(m.to_s.delete('='), args[0])
- else
- get_variable(m.to_s)
- end
- end
-
- def get_variable(name)
- @request_env[:gon][name]
- end
-
- def set_variable(name, value)
- @request_env[:gon][name] = value
- end
-
- def rabl(view_path, options = {})
- unless options[:instance]
- raise ArgumentError.new("You should pass :instance in options: :instance => self")
- end
-
- rabl_data = Gon::Sinatra::Rabl.parse_rabl(view_path, options[:instance])
-
- if options[:as]
- set_variable(options[:as].to_s, rabl_data)
- elsif rabl_data.is_a? Hash
- rabl_data.each do |key, value|
- set_variable(key, value)
- end
- else
- set_variable('rabl', rabl_data)
- end
- end
+ def self.registered(base)
+ base.helpers(Gon::Sinatra::GonHelpers, Gon::Sinatra::Helpers)
+ end
- def jbuilder(view_path, options = {})
- raise NoMethodError.new("Not available for sinatra")
+ module Rabl
+ def self.registered(base)
+ require 'rabl'
+ require 'gon/sinatra/rabl'
end
end
end
View
@@ -3,51 +3,33 @@
module Gon
module Sinatra
module Helpers
- def self.included base
- base.send(:include, InstanceMethods)
- end
-
- module InstanceMethods
- def include_gon(options = {})
- if Gon::Sinatra.request_env && Gon::Sinatra.all_variables.present?
- data = Gon::Sinatra.all_variables
- namespace = options[:namespace] || 'gon'
- script = "<script>window." + namespace + " = {};"
- unless options[:camel_case]
- data.each do |key, val|
- script += namespace + "." + key.to_s + '=' + val.to_json + ";"
- end
- else
- data.each do |key, val|
- script += namespace + "." + key.to_s.camelize(:lower) + '=' + val.to_json + ";"
- end
+ def include_gon(options = {})
+ unless gon.all_variables.empty?
+ data = gon.all_variables
+ namespace = options[:namespace] || 'gon'
+ script = "<script>window." + namespace + " = {};"
+ unless options[:camel_case]
+ data.each do |key, val|
+ script += namespace + "." + key.to_s + '=' + val.to_json + ";"
end
- script += "</script>"
- script
else
- ""
+ data.each do |key, val|
+ script += namespace + "." + key.to_s.camelize(:lower) + '=' + val.to_json + ";"
+ end
end
+ script += "</script>"
+ script
+ else
+ ""
end
end
end
module GonHelpers
- def self.included base
- base.send(:include, InstanceMethods)
- end
-
- module InstanceMethods
- def gon
- if !Gon::Sinatra.request_env || Gon::Sinatra.request != request.object_id
- Gon::Sinatra.request = request.object_id
- Gon::Sinatra.request_env = request.env
- end
- Gon::Sinatra
- end
+ def gon
+ env["gon"] ||= Gon::Sinatra::Store.new({})
+ @gon = env["gon"]
end
end
end
-end
-
-Sinatra::Application.send :include, Gon::Sinatra::Helpers
-Sinatra::Base.send :include, Gon::Sinatra::GonHelpers
+end
View
@@ -1,5 +1,4 @@
require 'rabl'
-require 'json'
module Gon
module Sinatra
@@ -9,7 +8,7 @@ def parse_rabl(rabl_path, controller)
source = File.read(rabl_path)
rabl_engine = ::Rabl::Engine.new(source, :format => 'json')
output = rabl_engine.render(controller, {})
- JSON.parse(output)
+ ::Rabl.configuration.json_engine.decode(output)
end
end
end
View
@@ -0,0 +1,65 @@
+
+module Gon
+ module Sinatra
+ class Store
+ attr_accessor :request
+
+ def initialize(variables)
+ @env = variables
+ end
+
+ def all_variables
+ @env
+ end
+
+ def clear
+ @env.clear
+ end
+
+ def method_missing(m, *args, &block)
+ if ( m.to_s =~ /=$/ )
+ if public_methods.include? m.to_s[0..-2].to_sym
+ raise "You can't use Gon public methods for storing data"
+ end
+ set_variable(m.to_s.delete('='), args[0])
+ else
+ get_variable(m.to_s)
+ end
+ end
+
+ def get_variable(name)
+ @env[name]
+ end
+ alias :get :get_variable
+
+ def set_variable(name, value)
+ @env[name] = value
+ end
+ alias :set :set_variable
+
+ def rabl(view_path, options = {})
+ raise Exception.new("You must require rabl and register Gon::Sinatra::Rabl to use rabl") unless defined? Rabl
+
+ unless options[:instance]
+ raise ArgumentError.new("You should pass :instance in options: :instance => self")
+ end
+
+ rabl_data = Gon::Sinatra::Rabl.parse_rabl(view_path, options[:instance])
+
+ if options[:as]
+ set_variable(options[:as].to_s, rabl_data)
+ elsif rabl_data.is_a? Hash
+ rabl_data.each do |key, value|
+ set_variable(key, value)
+ end
+ else
+ set_variable('rabl', rabl_data)
+ end
+ end
+
+ def jbuilder(view_path, options = {})
+ raise NoMethodError.new("Not available for sinatra")
+ end
+ end
+ end
+end
View
@@ -1,53 +1,72 @@
# gon_spec_rb
require 'gon-sinatra'
+class App < Sinatra::Base
+ register Gon::Sinatra
+ register Gon::Sinatra::Rabl
+end
+
describe Gon::Sinatra, '#all_variables' do
+ def app
+ app = App.new!
+ app.env = {}
+ app
+ end
before(:each) do
- Gon::Sinatra.request_env = {}
+ @gon = Gon::Sinatra::Store.new({})
end
it 'returns all variables in hash' do
- Gon::Sinatra.a = 1
- Gon::Sinatra.b = 2
- Gon::Sinatra.c = Gon::Sinatra.a + Gon::Sinatra.b
- Gon::Sinatra.c.should == 3
- Gon::Sinatra.all_variables.should == {'a' => 1, 'b' => 2, 'c' => 3}
+ @gon.a = 1
+ @gon.b = 2
+ @gon.c = @gon.a + @gon.b
+ @gon.c.should == 3
+ @gon.all_variables.should == {'a' => 1, 'b' => 2, 'c' => 3}
end
it 'supports all data types' do
- Gon::Sinatra.clear
- Gon::Sinatra.int = 1
- Gon::Sinatra.float = 1.1
- Gon::Sinatra.string = 'string'
- Gon::Sinatra.array = [ 1, 'string' ]
- Gon::Sinatra.hash_var = { :a => 1, :b => '2'}
- Gon::Sinatra.hash_w_array = { :a => [ 2, 3 ] }
- Gon::Sinatra.klass = Hash
+ @gon.clear
+ @gon.int = 1
+ @gon.float = 1.1
+ @gon.string = 'string'
+ @gon.array = [ 1, 'string' ]
+ @gon.hash_var = { :a => 1, :b => '2'}
+ @gon.hash_w_array = { :a => [ 2, 3 ] }
+ @gon.klass = Hash
end
it 'output as js correct' do
- Gon::Sinatra.clear
- Gon::Sinatra.int = 1
- Sinatra::Application.instance_methods.map(&:to_s).include?('include_gon').should == true
+ instance = app
+
+ instance.gon.int = 1
+ instance.methods.map(&:to_s).include?('include_gon').should == true
# TODO: Make it work
- # base = Sinatra::Base.new
- # base.include_gon.should == "<script>window.gon = {};" +
- # "gon.int=1;" +
- # "</script>"
+ instance.include_gon.should == "<script>window.gon = {};" +
+ "gon.int=1;" +
+ "</script>"
end
it 'returns exception if try to set public method as variable' do
- Gon::Sinatra.clear
- lambda { Gon::Sinatra.all_variables = 123 }.should raise_error
+ @gon.clear
+ lambda { @gon.all_variables = 123 }.should raise_error
+ end
+
+ it 'should be threadsafe' do
+ instance1 = app()
+ instance2 = app()
+
+ instance1.gon.test = "foo"
+ instance2.gon.test = "bar"
+ instance1.gon.test.should == "foo"
end
it 'render json from rabl template' do
- Gon::Sinatra.clear
+ @gon.clear
@objects = [1,2]
- Gon::Sinatra.rabl 'spec/test_data/sample.rabl', :instance => self
- Gon::Sinatra.objects.length.should == 2
+ @gon.rabl 'spec/test_data/sample.rabl', :instance => self
+ @gon.objects.length.should == 2
end
def request

0 comments on commit 086dffc

Please sign in to comment.