gon-6.4.0/ 0000755 0000041 0000041 00000000000 13747504657 012356 5 ustar www-data www-data gon-6.4.0/.travis.yml 0000644 0000041 0000041 00000000240 13747504657 014463 0 ustar www-data www-data language: ruby
sudo: false
env:
- "RABL_GEM=rabl"
- "RABL_GEM=rabl-rails"
rvm:
- 2.2.10
- 2.3.8
- 2.4.10
- 2.5.8
- 2.6.6
- 2.7.1
- ruby-head
gon-6.4.0/README.md 0000644 0000041 0000041 00000016020 13747504657 013634 0 ustar www-data www-data # Gon gem — get your Rails variables in your js
[](https://gitter.im/gazay/gon?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

[](https://travis-ci.org/gazay/gon) [](https://codeclimate.com/github/gazay/gon)
If you need to send some data to your js files and you don't want to do this with long way through views and parsing - use this force!
Now you can easily renew data in your variables through ajax with [gon.watch](https://github.com/gazay/gon/wiki/Usage-gon-watch)!
With [Jbuilder](https://github.com/rails/jbuilder), [Rabl](https://github.com/nesquena/rabl), and [Rabl-Rails](https://github.com/ccocchi/rabl-rails) support!
For Sinatra available [gon-sinatra](https://github.com/gazay/gon-sinatra).
For .Net MVC available port [NGon](https://github.com/brooklynDev/NGon).
For elixir Phoenix available [PhoenixGon](https://github.com/khusnetdinov/phoenix_gon).
## An example of typical use
### Very good and detailed example and reasons to use is considered in [railscast](http://railscasts.com/episodes/324-passing-data-to-javascript) by Ryan Bates
When you need to send some start data from your controller to your js
you might be doing something like this:
1. Write this data in controller(presenter/model) to some variable
2. In view for this action you put this variable to some objects by data
attributes, or write js right in view
3. Then there can be two ways in js:
+ if you previously wrote data in data
attributes - you should parse this attributes and write data to some
js variable.
+ if you wrote js right in view (many frontenders would shame you for
that) - you just use data from this js - OK.
4. You can use your data in your js
And every time when you need to send some data from action to js you do this.
With gon you configure it firstly - just put in layout one tag, and add
gem line to your Gemfile and do the following:
1. Write variables by
``` ruby
gon.variable_name = variable_value
# or new syntax
gon.push({
:user_id => 1,
:user_role => "admin"
})
gon.push(any_object) # any_object with respond_to? :each_pair
```
2. In your js you get this by
``` js
gon.variable_name
```
3. profit?
With the `gon.watch` feature you can easily renew data in gon variables!
Simply call `gon.watch` from your js file. It's super useful
in modern web applications!
## Usage
### More details about configuration and usage you can find in [gon wiki](https://github.com/gazay/gon/wiki)
`app/views/layouts/application.html.erb`
``` erb
some title
<%= Gon::Base.render_data %>
...
```
For rails 3:
``` erb
<%= include_gon %>
...
```
You can pass some [options](https://github.com/gazay/gon/wiki/Options)
to `render_data` method.
You put something like this in the action of your controller:
``` ruby
@your_int = 123
@your_array = [1,2]
@your_hash = {'a' => 1, 'b' => 2}
gon.your_int = @your_int
gon.your_other_int = 345 + gon.your_int
gon.your_array = @your_array
gon.your_array << gon.your_int
gon.your_hash = @your_hash
gon.all_variables # > {:your_int => 123, :your_other_int => 468, :your_array => [1, 2, 123], :your_hash => {'a' => 1, 'b' => 2}}
gon.your_array # > [1, 2, 123]
# gon.clear # gon.all_variables now is {}
```
Access the variables from your JavaScript file:
``` js
alert(gon.your_int)
alert(gon.your_other_int)
alert(gon.your_array)
alert(gon.your_hash)
```
### AMD compatible version: `include_gon_amd`
If your site uses AMD modules you can use the `include_gon_amd` helper to
include the variables and watch function as a module. Options are mostly
the same as for `include_gon`, except for `namespace_check`, which does
nothing and `namespace`, which is used as the name of the defined module.
The end result will look somewhat like the following:
```js
define('yourNameSpace', [], function() {
var gon = {};
gon.yourVariable = yourValue;
// etc...
return gon;
});
```
A (very) simplified usage example:
`app/views/layouts/application.html.erb`
```ruby
include_gon_amd namespace: 'data'
```
`Some JavaScript module`
```js
define(['data'], function(data) {
alert(data.myVariable);
});
```
## gon.watch - renew your data easily!
You can use gon for renewing your data without reloading pages and
writing long js functions! It's really great for some live values.
Supports `gon.watch.rabl` and `gon.watch.jbuilder` usage.
[Instruction](https://github.com/gazay/gon/wiki/Usage-gon-watch) for
usage gon.watch.
## Usage with Rabl
You can write your variables assign logic to templates with [Rabl](https://github.com/nesquena/rabl).
The way of writing Rabl templates is very clearly described in their repo.
Profit of using Rabl with gon:
1. You can clean your controllers now!
2. Work with database objects and collections clearly and easyly
3. All power of Rabl
4. You can still be lazy and don't use common way to transfer data in js
5. And so on
[Instruction](https://github.com/gazay/gon/wiki/Usage-with-rabl) for
usage gon with Rabl.
## Usage with Rabl-Rails
`gon.rabl` works with [rabl-rails](https://github.com/ccocchi/rabl-rails). Learn to write RABL the rabl-rails way [here](https://github.com/ccocchi/rabl-rails).
Add gon and rabl-rails to your environment:
```ruby
gem 'gon'
gem 'rabl-rails'
```
Define a rabl template using rabl-rails syntax:
```rabl
#app/views/users/show.rabl
object :@user
attributes :id, :name, :email, :location
```
Call gon.rabl in your controller
```ruby
#app/controllers/users_controller.rb
def show
@user = User.find(params[:id])
gon.rabl
end
```
## Usage with Jbuilder
Use gon with [Jbuilder](https://github.com/rails/jbuilder) as with [Rabl](https://guthub.com/nesquena/rabl):
[Instruction](https://github.com/gazay/gon/wiki/Usage-with-jbuilder) for
usage gon with Jbuilder.
## gon.global
You can use gon for sending your data to js from anywhere! It's really
great for some init data.
[Instruction](https://github.com/gazay/gon/wiki/Usage-gon-global) for
usage gon.global.
## Speed up Gon
You can use any [JSON Engine](https://github.com/intridea/multi_json#supported-json-engines) you want.
Gon uses `MultiJson` with autodetect mode, so all you need is just require your JSON library.
## Contributors
* @gazay
* @takiy33
Special thanks to @brainopia, @kossnocorp and @ai.
## License
The MIT License
## Security Contact
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
gon-6.4.0/spec/ 0000755 0000041 0000041 00000000000 13747504657 013310 5 ustar www-data www-data gon-6.4.0/spec/gon/ 0000755 0000041 0000041 00000000000 13747504657 014073 5 ustar www-data www-data gon-6.4.0/spec/gon/templates_spec.rb 0000644 0000041 0000041 00000002210 13747504657 017423 0 ustar www-data www-data describe Gon do
describe '.template_path' do
context 'template is specified' do
it 'add the extension if not included in the template name' do
expect(Gon::EnvFinder.send(:template_path, { :template => 'spec/test_data/sample' }, 'jbuilder')).to eql('spec/test_data/sample.jbuilder')
end
it 'return the specified template' do
expect(Gon::EnvFinder.send(:template_path, { :template => 'spec/test_data/sample.jbuilder' }, 'jbuilder')).to eql('spec/test_data/sample.jbuilder')
end
end
context 'template is not specified' do
before do
Gon.clear
controller.instance_variable_set('@objects', objects)
controller.action_name = 'show'
end
let(:controller) { ActionController::Base.new }
let(:objects) { [1, 2] }
context 'the action doesn as a template at a different format' do
it 'return the same template as the action with rabl extension' do
expect(Gon::EnvFinder.send(:template_path, { :controller => controller }, 'jbuilder')).to eql('app/views/action_controller/base/show.json.jbuilder')
end
end
end
end
end
gon-6.4.0/spec/gon/watch_spec.rb 0000644 0000041 0000041 00000004602 13747504657 016542 0 ustar www-data www-data describe Gon::Watch do
let(:controller) { ActionController::Base.new }
let(:request) { ActionDispatch::Request.new({}) }
before :each do
controller.request = request
controller.params = {}
env = {}
env['ORIGINAL_FULLPATH'] = '/foo'
env['REQUEST_METHOD'] = 'GET'
Gon::Watch.clear
Gon.send(:current_gon).instance_variable_set(:@env, env)
Gon.send(:current_gon).env['action_controller.instance'] = controller
Gon.clear
end
it 'should add variables to Gon#all_variables hash' do
Gon.a = 1
Gon.watch.b = 2
expect(Gon.all_variables).to eq({ 'a' => 1, 'b' => 2 })
end
describe '#all_variables' do
it 'should generate array with current request url, method type and variable names' do
Gon.watch.a = 1
expect(Gon.watch.all_variables).to eq({ 'a' => { 'url' => '/foo', 'method' => 'GET', 'name' => 'a' } })
end
end
describe '#render' do
it 'should render function with variables in gon namespace' do
Gon.watch.a = 1
expect(Gon.watch.render).to match(/gon\.watch\s=/)
expect(Gon.watch.render).to match(/gon\.watchedVariables/)
end
end
describe 'Render concrete variable' do
before do
env = Gon.send(:current_gon).env
env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
allow(controller).to receive_messages(request: ActionDispatch::Request.new(env))
Gon.send(:current_gon).env['action_controller.instance'] = controller
end
context 'when request variable is json safe content' do
before do
allow(controller).to receive_messages(params: {
gon_return_variable: true,
gon_watched_variable: 'safety'})
end
it 'should return value of variable if called right request' do
expect(controller).to receive(:render).with(json: '12345')
Gon.watch.safety = 12345
end
end
context 'when request variable is json unsafe content' do
let(:expected) { %Q{"\\u003cscript\\u003e'\\"\\u003c/script\\u003e
Dangerous"} }
before do
allow(controller).to receive_messages(params: {
gon_return_variable: true,
gon_watched_variable: 'danger'})
end
it 'should return value of variable if called right request' do
expect(controller).to receive(:render).with(json: expected)
Gon.watch.danger = %Q{\u2028Dangerous}
end
end
end
end
gon-6.4.0/spec/gon/rabl_spec.rb 0000644 0000041 0000041 00000005477 13747504657 016367 0 ustar www-data www-data describe Gon do
describe '.rabl' do
before :each do
Gon.clear
controller.instance_variable_set('@objects', objects)
end
let(:controller) { ActionController::Base.new }
let(:objects) { [1, 2] }
context 'render template with deprecation' do
it 'still works' do
Gon.rabl 'spec/test_data/sample.rabl', :controller => controller
expect(Gon.objects.length).to eq(2)
end
end
context 'option locals' do
it 'works without locals object properly' do
Gon.rabl(
:template => 'spec/test_data/sample.rabl',
:controller => controller
)
expect(Gon.objects.map { |it| it['object']['inspect'] }).to eq(%w(1 2))
end
it 'works with different locals object' do
Gon.rabl(
:template => 'spec/test_data/sample.rabl',
:controller => controller,
:locals => { :objects => [3, 4] }
)
expect(Gon.objects.map { |it| it['object']['inspect'] }).to eq(%w(3 4))
end
end
it 'works if rabl is included' do
Gon.rabl :template => 'spec/test_data/sample.rabl', :controller => controller
expect(Gon.objects.length).to eq(2)
end
it 'works with ActionView::Helpers' do
Gon.rabl :template => 'spec/test_data/sample_with_helpers.rabl', :controller => controller
expect(Gon.objects.first['object']['time_ago']).to eq('about 6 hours')
end
it 'raise exception if rabl is not included' do
Gon.send :remove_const, 'Rabl'
expect { Gon.rabl :template => 'spec/test_data/sample.rabl', :controller => controller }.to raise_error(NameError)
load 'rabl.rb'
load 'gon/rabl.rb'
end
context '.template_path' do
context 'template is specified' do
it 'add the extension if not included in the template name' do
expect(Gon::EnvFinder.send(:template_path, { :template => 'spec/test_data/sample' }, 'rabl')).to eql('spec/test_data/sample.rabl')
end
it 'return the specified template' do
expect(Gon::EnvFinder.send(:template_path, { :template => 'spec/test_data/sample.rabl' }, 'rabl')).to eql('spec/test_data/sample.rabl')
end
end
context 'template is not specified' do
before do
Gon.clear
controller.instance_variable_set('@objects', objects)
controller.action_name = 'show'
end
let(:controller) { ActionController::Base.new }
let(:objects) { [1, 2] }
context 'the action doesn as a template at a different format' do
it 'return the same template as the action with rabl extension' do
expect(Gon::EnvFinder.send(:template_path, { :controller => controller }, 'rabl')).to eql('app/views/action_controller/base/show.json.rabl')
end
end
end
end
end
end
gon-6.4.0/spec/gon/basic_spec.rb 0000644 0000041 0000041 00000024141 13747504657 016515 0 ustar www-data www-data describe Gon do
before(:each) do
Gon.clear
end
describe '#all_variables' do
it 'returns all variables in hash' do
Gon.a = 1
Gon.b = 2
Gon.c = Gon.a + Gon.b
expect(Gon.c).to eq(3)
expect(Gon.all_variables).to eq({ 'a' => 1, 'b' => 2, 'c' => 3 })
end
it 'supports all data types' do
Gon.int = 1
Gon.float = 1.1
Gon.string = 'string'
Gon.symbol = :symbol
Gon.array = [1, 'string']
Gon.hash_var = { :a => 1, :b => '2' }
Gon.hash_w_array = { :a => [2, 3] }
Gon.klass = Hash
end
it 'can be filled with dynamic named variables' do
check = {}
3.times do |i|
Gon.set_variable("variable#{i}", i)
check["variable#{i}"] = i
end
expect(Gon.all_variables).to eq(check)
end
it 'can set and get variable with dynamic name' do
var_name = "variable#{rand}"
Gon.set_variable(var_name, 1)
expect(Gon.get_variable(var_name)).to eq(1)
end
it 'can be support new push syntax' do
Gon.push({ :int => 1, :string => 'string' })
expect(Gon.all_variables).to eq({ 'int' => 1, 'string' => 'string' })
end
it 'push with wrong object' do
expect {
Gon.push(String.new('string object'))
}.to raise_error('Object must have each_pair method')
end
describe "#merge_variable" do
it 'deep merges the same key' do
Gon.merge_variable(:foo, { bar: { tar: 12 }, car: 23 })
Gon.merge_variable(:foo, { bar: { dar: 21 }, car: 12 })
expect(Gon.get_variable(:foo)).to eq(bar: { tar: 12, dar: 21 }, car: 12)
end
it 'merges on push with a flag' do
Gon.push(foo: { bar: 1 })
Gon.push({ foo: { tar: 1 } }, :merge)
expect(Gon.get_variable("foo")).to eq(bar: 1, tar: 1)
end
context 'overrides key' do
specify "the previous value wasn't hash" do
Gon.merge_variable(:foo, 2)
Gon.merge_variable(:foo, { a: 1 })
expect(Gon.get_variable(:foo)).to eq(a: 1)
end
specify "the new value isn't a hash" do
Gon.merge_variable(:foo, { a: 1 })
Gon.merge_variable(:foo, 2)
expect(Gon.get_variable(:foo)).to eq(2)
end
end
end
end
describe '#include_gon' do
before(:each) do
Gon::Request.
instance_variable_set(:@request_id, request.object_id)
expect(ActionView::Base.instance_methods).to include(:include_gon)
@base = ActionView::Base.new
@base.request = request
end
it 'outputs correct js with an integer' do
Gon.int = 1
expect(@base.include_gon).to eq(wrap_script(
'window.gon={};' +
'gon.int=1;'))
end
it 'outputs correct js with a string' do
Gon.str = %q(a'b"c)
expect(@base.include_gon).to eq(wrap_script(
'window.gon={};' +
%q(gon.str="a'b\"c";))
)
end
it 'outputs correct js with a script string' do
Gon.str = %q()
escaped_str = "\\u003c/script\\u003e\\u003cscript\\u003ealert('!')\\u003c/script\\u003e"
expect(@base.include_gon).to eq(wrap_script(
'window.gon={};' +
%Q(gon.str="#{escaped_str}";))
)
end
it 'outputs correct js with an integer and type' do
Gon.int = 1
expect(@base.include_gon(type: true)).to eq('')
end
it 'outputs correct js with an integer, camel-case and namespace' do
Gon.int_cased = 1
expect(@base.include_gon(camel_case: true, namespace: 'camel_cased')).to eq(
wrap_script('window.camel_cased={};' +
'camel_cased.intCased=1;')
)
end
it 'outputs correct js with camel_depth = :recursive' do
Gon.test_hash = { test_depth_one: { test_depth_two: 1 } }
expect(@base.include_gon(camel_case: true, camel_depth: :recursive)).to eq(
wrap_script('window.gon={};' +
'gon.testHash={"testDepthOne":{"testDepthTwo":1}};')
)
end
it 'outputs correct js with camel_depth = 2' do
Gon.test_hash = { test_depth_one: { test_depth_two: 1 } }
expect(@base.include_gon(camel_case: true, camel_depth: 2)).to eq(
wrap_script('window.gon={};' +
'gon.testHash={"testDepthOne":{"test_depth_two":1}};')
)
end
it 'outputs correct js for an array with camel_depth = :recursive' do
Gon.test_hash = { test_depth_one: [{ test_depth_two: 1 }, { test_depth_two: 2 }] }
expect(@base.include_gon(camel_case: true, camel_depth: :recursive)).to eq( \
wrap_script('window.gon={};' +
'gon.testHash={"testDepthOne":[{"testDepthTwo":1},{"testDepthTwo":2}]};')
)
end
it 'outputs correct key with camel_case option set alternately ' do
Gon.test_hash = 1
@base.include_gon(camel_case: true)
expect(@base.include_gon(camel_case: false)).to eq(
wrap_script('window.gon={};' +
'gon.test_hash=1;')
)
end
it 'outputs correct js with an integer and without tag' do
Gon.int = 1
expect(@base.include_gon(need_tag: false)).to eq( \
'window.gon={};' +
'gon.int=1;'
)
end
it 'outputs correct js without variables, without tag and gon init if before there was data' do
Gon::Request.
instance_variable_set(:@request_id, 123)
Gon::Request.instance_variable_set(:@request_env, { 'gon' => { :a => 1 } })
expect(@base.include_gon(need_tag: false, init: true)).to eq( \
'window.gon={};'
)
end
it 'outputs correct js without variables, without tag and gon init' do
expect(@base.include_gon(need_tag: false, init: true)).to eq( \
'window.gon={};'
)
end
it 'outputs correct js without variables, without tag, gon init and an integer' do
Gon.int = 1
expect(@base.include_gon(need_tag: false, init: true)).to eq( \
'window.gon={};' +
'gon.int=1;'
)
end
it 'outputs correct js without cdata, without type, gon init and an integer' do
Gon.int = 1
expect(@base.include_gon(cdata: false, type: false)).to eq(
wrap_script(
"\n" +
'window.gon={};' +
'gon.int=1;' +
"\n", false)
)
end
it 'outputs correct js with type text/javascript' do
expect(@base.include_gon(need_type: true, init: true)).to eq(wrap_script('window.gon={};'))
end
it 'outputs correct js with namespace check' do
expect(@base.include_gon(namespace_check: true)).to eq(wrap_script('window.gon=window.gon||{};'))
end
it 'outputs correct js without namespace check' do
expect(@base.include_gon(namespace_check: false)).to eq(wrap_script('window.gon={};'))
end
context "without a current_gon instance" do
before(:each) do
RequestStore.store[:gon] = nil
allow(Gon).to receive(:current_gon).and_return(nil)
end
it "does not raise an exception" do
expect { @base.include_gon }.to_not raise_error
end
it 'outputs correct js' do
expect(@base.include_gon).to eq("")
end
it 'outputs correct js with init' do
expect(@base.include_gon(init: true)).to eq(wrap_script('window.gon={};'))
end
end
end
describe '#include_gon_amd' do
before(:each) do
Gon::Request.
instance_variable_set(:@request_id, request.object_id)
@base = ActionView::Base.new
@base.request = request
end
it 'is included in ActionView::Base as a helper' do
expect(ActionView::Base.instance_methods).to include(:include_gon_amd)
end
it 'outputs correct js without variables' do
expect(@base.include_gon_amd).to eq( wrap_script( \
'define(\'gon\',[],function(){'+
'var gon={};return gon;'+
'});')
)
end
it 'outputs correct js with an integer' do
Gon.int = 1
expect(@base.include_gon_amd).to eq( wrap_script(
'define(\'gon\',[],function(){'+
'var gon={};gon[\'int\']=1;return gon;'+
'});')
)
end
it 'outputs correct module name when given a namespace' do
expect(@base.include_gon_amd(namespace: 'data')).to eq(wrap_script(
'define(\'data\',[],function(){'+
'var gon={};return gon;'+
'});')
)
end
end
it 'returns exception if try to set public method as variable' do
expect { Gon.all_variables = 123 }.to raise_error(RuntimeError)
expect { Gon.rabl = 123 }.to raise_error(RuntimeError)
end
describe '#check_for_rabl_and_jbuilder' do
let(:controller) { ActionController::Base.new }
it 'should be able to handle constants array (symbols)' do
allow(Gon).to receive(:constants) { Gon.constants }
expect { Gon.rabl :template => 'spec/test_data/sample.rabl', :controller => controller }.not_to raise_error
expect { Gon.jbuilder :template => 'spec/test_data/sample.json.jbuilder', :controller => controller }.not_to raise_error
end
end
end
gon-6.4.0/spec/gon/thread_spec.rb 0000644 0000041 0000041 00000001125 13747504657 016700 0 ustar www-data www-data class GonTestWorker
include Gon::ControllerHelpers
def request
@request ||= ActionDispatch::TestRequest.create
end
def env
request.env
end
def execute
gon.clear
gon.a ||= 1
gon.a += 1
end
def value
gon.a
end
end
describe 'threading behaviour' do
before do
allow(Gon).to receive(:current_gon).and_call_original
end
it 'is threadsafe' do
threads = []
10.times do
threads << Thread.new do
gtw = GonTestWorker.new
gtw.execute
expect(gtw.value).to eq 2
end
end
threads.each(&:join)
end
end
gon-6.4.0/spec/gon/jbuilder_spec.rb 0000644 0000041 0000041 00000005013 13747504657 017231 0 ustar www-data www-data describe Gon do
describe '.jbuilder' do
context 'render jbuilder templates' do
before do
Gon.clear
controller.instance_variable_set('@objects', objects)
end
let(:controller) { ActionController::Base.new }
let(:objects) { [1, 2] }
it 'render json from jbuilder template' do
Gon.jbuilder :template => 'spec/test_data/sample.json.jbuilder', :controller => controller
expect(Gon.objects.length).to eq(2)
end
it 'render json from jbuilder template with locals' do
Gon.jbuilder :template => 'spec/test_data/sample_with_locals.json.jbuilder',
:controller => controller,
:locals => { :some_local => 1234, :some_complex_local => OpenStruct.new(:id => 1234) }
expect(Gon.some_local).to eq(1234)
expect(Gon.some_complex_local_id).to eq(1234)
end
it 'render json from jbuilder template with locals' do
Gon.jbuilder :template => 'spec/test_data/sample_with_helpers.json.jbuilder', :controller => controller
expect(Gon.date).to eq('about 6 hours')
end
it 'render json from jbuilder template with controller methods' do
class << controller
def private_controller_method
'gon test helper works'
end
helper_method :private_controller_method
private :private_controller_method
end
Gon.jbuilder :template => 'spec/test_data/sample_with_controller_method.json.jbuilder', :controller => controller
expect(Gon.data_from_method).to eq('gon test helper works')
end
it 'render json from jbuilder template with a partial' do
controller.view_paths << 'spec/test_data'
Gon.jbuilder :template => 'spec/test_data/sample_with_partial.json.jbuilder', :controller => controller
expect(Gon.objects.length).to eq(2)
end
context 'within Rails' do
before do
module ::Rails
end
allow(Rails).to receive_message_chain("application.routes.url_helpers.instance_methods") { [:user_path] }
controller.instance_variable_set('@user_id', 1)
end
after do
Object.send(:remove_const, :Rails)
end
it 'includes url_helpers' do
expect(controller).to receive(:user_path) { |id| "/users/#{id}" }
Gon.jbuilder :template => 'spec/test_data/sample_url_helpers.json.jbuilder', :controller => controller
expect(Gon.url).to eq '/users/1'
end
end
end
end
end
gon-6.4.0/spec/gon/global_spec.rb 0000644 0000041 0000041 00000012260 13747504657 016673 0 ustar www-data www-data describe Gon::Global do
before(:each) do
Gon::Global.clear
Gon::Request.instance_variable_set(:@request_env, nil)
end
describe '#all_variables' do
it 'returns all variables in hash' do
Gon.global.a = 1
Gon.global.b = 2
Gon.global.c = Gon.global.a + Gon.global.b
expect(Gon.global.c).to eq(3)
expect(Gon.global.all_variables).to eq({ 'a' => 1, 'b' => 2, 'c' => 3 })
end
it 'supports all data types' do
Gon.global.int = 1
Gon.global.float = 1.1
Gon.global.string = 'string'
Gon.global.symbol = :symbol
Gon.global.array = [1, 'string']
Gon.global.hash_var = { :a => 1, :b => '2' }
Gon.global.hash_w_array = { :a => [2, 3] }
Gon.global.klass = Hash
end
end
describe '#include_gon' do
before(:each) do
Gon.clear
expect(ActionView::Base.instance_methods).to include(:include_gon)
@base = ActionView::Base.new
@base.request = request
end
it 'outputs correct js with an integer' do
Gon.global.int = 1
expect(@base.include_gon).to eq("")
end
it 'outputs correct js with an integer and integer in Gon' do
Gon.int = 1
Gon.global.int = 1
expect(@base.include_gon).to eq("")
end
it 'outputs correct js with a string' do
Gon.global.str = %q(a'b"c)
expect(@base.include_gon).to eq("")
end
it 'outputs correct js with a script string' do
Gon.global.str = %q()
escaped_str = "\\u003c/script\\u003e\\u003cscript\\u003ealert('!')\\u003c/script\\u003e"
expect(@base.include_gon).to eq("")
end
it 'outputs correct js with a unicode line separator' do
Gon.global.str = "\u2028"
expect(@base.include_gon).to eq("")
end
it 'outputs locally overridden value' do
Gon.str = 'local value'
Gon.global.str = 'global value'
expect(@base.include_gon(global_root: '')).to eq("")
end
it "includes the tag attributes in the script tag" do
Gon.global.int = 1
expect(@base.include_gon(nonce: 'test')).to eq("")
end
end
it 'returns exception if try to set public method as variable' do
expect { Gon.global.all_variables = 123 }.to raise_error(RuntimeError)
expect { Gon.global.rabl = 123 }.to raise_error(RuntimeError)
end
context 'with jbuilder and rabl' do
before :each do
controller.instance_variable_set('@objects', objects)
end
let(:controller) { ActionController::Base.new }
let(:objects) { [1, 2] }
it 'works fine with rabl' do
Gon.global.rabl :template => 'spec/test_data/sample.rabl', :controller => controller
expect(Gon.global.objects.length).to eq(2)
end
it 'works fine with jbuilder' do
Gon.global.jbuilder :template => 'spec/test_data/sample.json.jbuilder', :controller => controller
expect(Gon.global.objects.length).to eq(2)
end
it 'should throw exception, if use rabl or jbuilder without :template' do
expect { Gon.global.rabl }.to raise_error(RuntimeError)
expect { Gon.global.jbuilder }.to raise_error(RuntimeError)
end
end
end
gon-6.4.0/spec/test_data/ 0000755 0000041 0000041 00000000000 13747504657 015260 5 ustar www-data www-data gon-6.4.0/spec/test_data/sample_with_controller_method.json.jbuilder 0000644 0000041 0000041 00000000106 13747504657 026066 0 ustar www-data www-data json.objects @objects
json.data_from_method private_controller_method
gon-6.4.0/spec/test_data/_sample_partial.json.jbuilder 0000644 0000041 0000041 00000000025 13747504657 023103 0 ustar www-data www-data json.objects objects
gon-6.4.0/spec/test_data/sample_with_helpers.rabl 0000644 0000041 0000041 00000000151 13747504657 022155 0 ustar www-data www-data collection @objects => 'objects'
attributes :id
node(:time_ago) { |_| distance_of_time_in_words(20000) }
gon-6.4.0/spec/test_data/sample.json.jbuilder 0000644 0000041 0000041 00000000026 13747504657 021231 0 ustar www-data www-data json.objects @objects
gon-6.4.0/spec/test_data/sample_with_helpers_rabl_rails.rabl 0000644 0000041 0000041 00000000153 13747504657 024351 0 ustar www-data www-data collection :@objects => 'objects'
attributes :inspect
node(:time_ago) { distance_of_time_in_words(20000) }
gon-6.4.0/spec/test_data/sample_with_helpers.json.jbuilder 0000644 0000041 0000041 00000000053 13747504657 024006 0 ustar www-data www-data json.date distance_of_time_in_words(20000)
gon-6.4.0/spec/test_data/sample_rabl_rails.rabl 0000644 0000041 0000041 00000000066 13747504657 021577 0 ustar www-data www-data collection :@objects => 'objects'
attributes :inspect
gon-6.4.0/spec/test_data/sample_with_locals.json.jbuilder 0000644 0000041 0000041 00000000114 13747504657 023617 0 ustar www-data www-data json.some_local some_local
json.some_complex_local_id some_complex_local.id
gon-6.4.0/spec/test_data/sample_url_helpers.json.jbuilder 0000644 0000041 0000041 00000000035 13747504657 023635 0 ustar www-data www-data json.url user_path(@user_id)
gon-6.4.0/spec/test_data/sample.rabl 0000644 0000041 0000041 00000000065 13747504657 017404 0 ustar www-data www-data collection @objects => 'objects'
attributes :inspect
gon-6.4.0/spec/test_data/sample_with_partial.json.jbuilder 0000644 0000041 0000041 00000000123 13747504657 023776 0 ustar www-data www-data json.partial! 'spec/test_data/_sample_partial.json.jbuilder', :objects => @objects
gon-6.4.0/spec/spec_helper.rb 0000644 0000041 0000041 00000001372 13747504657 016131 0 ustar www-data www-data require 'rails/railtie'
# We don't require rails for specs, but jbuilder works only in rails.
# And it checks version of rails. I've decided to configure jbuilder for rails v4
module Rails
module VERSION
MAJOR = 4
end
def self.version
'4.2.0'
end
end
require 'gon'
require 'jbuilder'
RSpec.configure do |config|
config.before(:each) do
RequestStore.store[:gon] = Gon::Request.new({})
@request = RequestStore.store[:gon]
allow(Gon).to receive(:current_gon).and_return(@request)
end
end
def request
@request ||= double 'request', :env => {}
end
def wrap_script(content, cdata=true)
script = "'
end
gon-6.4.0/CHANGELOG.md 0000644 0000041 0000041 00000017444 13747504657 014201 0 ustar www-data www-data # CHANGELOG
## [Unreleased]
## [6.4.0] - 2020-09-18
### Security
- CVE-2020-25739: Enforce HTML entities escaping in gon output
## [6.3.2] - 2019-11-18
### Security
- Restrict possibility of vulnerable i18n legacy verision (0.3.6.pre)
installation
## [6.3.1] - 2019-11-18
### Changed
- ActionView::Base and ActionController::Base should be loaded inside
ActiveSupport.on_load hook. Thanks to @amatsuda
- Require Ruby >= 2.2.2 (activesupport). Thanks to @nicolasleger
- Update old_rails.rb to reflect GonHelpers -> ControllerHelpers name change.
Thanks to @etipton
## [6.2.1] - 2018-07-11
### Changed
- Update README: correct spelling mistake. Thanks to @EdwardBetts
- Autoload test classes only in test env. Thanks to @wilddima
### Fixed
- Fix keys cache. Thanks to @ertrzyiks
- fixing tests by running with rabl and rabl-rails separately. Thanks to
@dsalahutdinov
## [6.2.0] - 2017-10-04
### Added
- Introduce keys cache. Thanks to @vlazar
- Add possibleErrorCallback to watch params. Thanks to @etagwerker
### Changed
- Update readme with PhoenixGon hex link. Thanks to @khusnetdinov
- Fix code highlighting in README. Thanks to @ojab
- Refactoring: use attr_reader
### Removed
- Remove unnecessary json dependency.
- Remove rubysl and rubinius-developer_tools gem.
## [6.1.0] - 2016-07-11
### Deprecated
- env is deprecated and will be removed from Rails 5.0. Thanks to @dlupu
### Fixed
- fix merging routes bug. Thanks to @strikyflo
- Show what method was used in public methods error.
### Changed
- Use 'need_tag' as option name to prevent calling 'tag' method. Thanks to
@june29
- Update README; comment out gon.clear from sample code. Thanks to
@speee-nakajima
- Update README; Replace the include_gon method with render_data method.
- Refactoring: use attr_accessor method.
- Refactoring: use attr_reader method.
## [6.0.1] - 2015-07-22
### Changed
- Free dependencies
## [6.0.0] - 2015-07-22
### Added
- nonce option. Thanks to @joeljackson
### Changed
- Refactoring
- Included rails url_helpers into jbuilder. Thanks to @razum2um
## [5.2.3] - 2014-11-03
### Added
- Coffescript implementation of watch.js. Thanks to @willcosgrove
- unwatchAll function in watch.js. Thanks to @willcosgrove
## [5.2.2] - 2014-10-31
### Added
- support for controller helper methods in jbuilder
## [5.2.1] - 2014-10-28
### Added
- merge variable feature (for merge hash-like variables instead of overriding
them). Thanks to @jalkoby
### Fixed
- fix for jbuilder module. Thanks to @jankovy
## [5.2.0] - 2014-08-26
### Added
- namespace_check option. Thanks to @tommyh
- AMD compatible version of including gon. Thanks to @vijoc
### Changed
- Only inject gon into ActionController::Base-like object in spec_helper. Thanks
to @kevinoconnor7
### Fixed
- fix issue where include_gon would raise exception if the controller did not
assign any gon variables. Thanks to @asalme
## [5.1.2] - 2014-07-22
### Changed
- Clarifying helpers, dump gon#watch content to safe json before render. Thanks
to @Strech
## [5.1.1] - 2014-07-17
### Added
- global_root option. Thanks to @rafaelliu
- MultiJson support. Thanks to @Strech
## [5.1.0] - 2014-06-29
### Fixed
- Many fixes. Thanks to @Silex, @kilefritz, @irobayna, @kyrylo, @randoum,
@jackquack, @tuvistavie, @Strech for awesome commits and help!
## [5.0.4] - 2014-02-13
### Fixed
- Fix check for get and assign variables for Gon.global
## [5.0.3] - 2014-02-12
### Removed
- Revert changes in gemspec
## [5.0.2] - 2014-02-12
### Fixed
- Fix issue when there is no gon object for current thread and rendering
include_gon (#108 part) (wasn't fixed) (@gregmolnar)
## [5.0.1] - 2013-12-30
### Fixed
- Fix issue when there is no gon object for current thread and rendering
include_gon (#108 part)
## [5.0.0] - 2013-12-26
### Changed
- Gon is threadsafe now! (@razum2um)
- Camelcasing with depth (@MaxSchmeling)
- Optional CDATA and style refactoring (@torbjon)
- jBuilder supports not only String and Hash types of locals (@steakchaser)
- Using ActionDispatch::Request#uuid instead of ActionDispatch::Request#id
(@sharshenov)
## [4.1.1] - 2013-06-04
### Fixed
- Fixed critical XSS vulnerability https://github.com/gazay/gon/issues/84
(@vadimr & @Hebo)
## [4.1.0] - 2013-04-14
### Added
- rabl-rails support (@jtherrell)
### Changed
- Refactored script tag generation (@toothrot)
- Stop support for MRI 1.8.7
- Accepting locals in jbuilder templates
## [4.0.3] - 2013-04-14
!!!IMPORTANT!!! Last version with compatibility for MRI 1.8.7
### Added
- new method `Gon#push` for assign variables through Hash-like objects (@topdev)
### Changed
- Fixes for 1.8.7 compatibility.
## [4.0.2] - 2012-12-17
### Fixed
- Fixed gon.watch in JS without callback and options
## [4.0.1] - 2012-10-25
### Added
- option :locals to gon.rabl functionality
### Changed
- Gon#set_variable and Gon#get_variable moved to public scope
### Removed
- BlankSlate requirement (@phoet)
## [4.0.0] - 2012-07-23
### Added
- gon.watch functionality (thanks to @brainopia and @kossnocorp)
- Compatibility with jbuilder paths for partial! method
### Changed
- Little bit refactoring - Gon now is a class
### Fixed
- Fixed some bugs
## [3.0.5] - 2012-06-22
### Added
- type text/javascript option (@torbjon)
### Changed
- A litlle bit refactoring
- Made compatible with active support json encoding for escaping script tags
### Fixed
- bug for init option
- clear if init true (@torbjon)
## [3.0.4] - 2012-06-02
### Fixed
- Fix bug with gon clear with global variables, bump version
## [3.0.3] - 2012-05-22
### Added
- init option (@torbjon)
### Changed
- Include ActionView::Helpers into Gon::JBuilder
## [3.0.2] - 2012-04-28
### Added
- need_tag option (@afa)
## [3.0.0] - 2012-04-17
### Added
- Added Gon.global for using gon everywhere
### Changed
- Almost all code refactored
- Included ActionView::Helpers into Rabl::Engine
## [2.3.0] - 2012-04-09
### Changed
- Don't really remember what was before this version
[Unreleased]: https://github.com/gazay/gon/compare/v6.3.2...master
[6.3.2]: https://github.com/gazay/gon/compare/v6.3.1...v6.3.2
[6.3.1]: https://github.com/gazay/gon/compare/v6.2.1...v6.3.1
[6.2.1]: https://github.com/gazay/gon/compare/v6.2.0...v6.2.1
[6.2.0]: https://github.com/gazay/gon/compare/v6.1.0...v6.2.0
[6.1.0]: https://github.com/gazay/gon/compare/v6.0.1...v6.1.0
[6.0.1]: https://github.com/gazay/gon/compare/v6.0.0...v6.0.1
[6.0.0]: https://github.com/gazay/gon/compare/v5.2.3...v6.0.0
[5.2.3]: https://github.com/gazay/gon/compare/v5.2.2...v5.2.3
[5.2.2]: https://github.com/gazay/gon/compare/v5.2.1...v5.2.2
[5.2.1]: https://github.com/gazay/gon/compare/v5.2.0...v5.2.1
[5.2.0]: https://github.com/gazay/gon/compare/v5.1.2...v5.2.0
[5.1.2]: https://github.com/gazay/gon/compare/v5.1.1...v5.1.2
[5.1.1]: https://github.com/gazay/gon/compare/v5.1.0...v5.1.1
[5.1.0]: https://github.com/gazay/gon/compare/v5.0.4...v5.1.0
[5.0.4]: https://github.com/gazay/gon/compare/v5.0.3...v5.0.4
[5.0.3]: https://github.com/gazay/gon/compare/v5.0.2...v5.0.3
[5.0.2]: https://github.com/gazay/gon/compare/v5.0.1...v5.0.2
[5.0.1]: https://github.com/gazay/gon/compare/v5.0.0...v5.0.1
[5.0.0]: https://github.com/gazay/gon/compare/v4.1.1...v5.0.0
[4.1.1]: https://github.com/gazay/gon/compare/v4.1.0...v4.1.1
[4.1.0]: https://github.com/gazay/gon/compare/v4.0.3...v4.1.0
[4.0.3]: https://github.com/gazay/gon/compare/v4.0.2...v4.0.3
[4.0.2]: https://github.com/gazay/gon/compare/v4.0.1...v4.0.2
[4.0.1]: https://github.com/gazay/gon/compare/v4.0.0...v4.0.1
[4.0.0]: https://github.com/gazay/gon/compare/v3.0.5...v4.0.0
[3.0.5]: https://github.com/gazay/gon/compare/v3.0.4...v3.0.5
[3.0.4]: https://github.com/gazay/gon/compare/v3.0.3...v3.0.4
[3.0.3]: https://github.com/gazay/gon/compare/v3.0.2...v3.0.3
[3.0.2]: https://github.com/gazay/gon/compare/v3.0.0...v3.0.2
[3.0.0]: https://github.com/gazay/gon/compare/v2.3.0...v3.0.0
[2.3.0]: https://github.com/gazay/gon/releases/tag/v2.3.0
gon-6.4.0/.gitignore 0000644 0000041 0000041 00000000065 13747504657 014347 0 ustar www-data www-data *.gem
.bundle
Gemfile.lock
pkg/*
tmp/*
.rvmrc
*.idea
gon-6.4.0/LICENSE 0000644 0000041 0000041 00000002067 13747504657 013370 0 ustar www-data www-data The MIT License
Copyright (c) 2011-2019 Alexey Gaziev
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
gon-6.4.0/coffee/ 0000755 0000041 0000041 00000000000 13747504657 013605 5 ustar www-data www-data gon-6.4.0/coffee/watch.coffee 0000644 0000041 0000041 00000002462 13747504657 016070 0 ustar www-data www-data gon._timers = {}
gon.watch = (name, possibleOptions, possibleCallback, possibleErrorCallback) ->
return unless $?
if typeof possibleOptions == 'object'
options = {}
for key, value of gon.watchedVariables[name]
options[key] = value
for key, value of possibleOptions
options[key] = value
callback = possibleCallback
errorCallback = possibleErrorCallback
else
options = gon.watchedVariables[name]
callback = possibleOptions
errorCallback = possibleCallback
performAjax = ->
xhr = $.ajax
type: options.type || 'GET'
url: options.url
data:
_method: options.method
gon_return_variable: true
gon_watched_variable: name
if errorCallback
xhr.done(callback).fail(errorCallback);
else
xhr.done(callback)
if options.interval
timer = setInterval(performAjax, options.interval)
gon._timers[name] ?= []
return gon._timers[name].push
timer: timer
fn: callback
else
return performAjax()
gon.unwatch = (name, fn) ->
for timer, index in gon._timers[name] when timer.fn == fn
clearInterval(timer.timer)
gon._timers[name].splice(index, 1)
return
gon.unwatchAll = ->
for variable, timers of gon._timers
for timer in timers
clearInterval(timer.timer)
gon._timers = {}
gon-6.4.0/Rakefile 0000644 0000041 0000041 00000000365 13747504657 014027 0 ustar www-data www-data require 'bundler'
Bundler::GemHelper.install_tasks
desc 'Run all tests by default'
task :default => :spec
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new do |t|
t.rspec_opts = ["--color", '--format doc', '--require spec_helper']
end gon-6.4.0/lib/ 0000755 0000041 0000041 00000000000 13747504657 013124 5 ustar www-data www-data gon-6.4.0/lib/gon.rb 0000644 0000041 0000041 00000005751 13747504657 014244 0 ustar www-data www-data require 'request_store'
require 'action_view'
require 'action_controller'
require 'multi_json'
require 'gon/base'
require 'gon/env_finder'
require 'gon/global'
require 'gon/watch'
require 'gon/request'
require 'gon/helpers'
require 'gon/escaper'
require 'gon/rabl'
require 'gon/jbuilder'
require 'gon/jbuilder/parser'
require 'gon/json_dumper'
# NOTE : ActionDispatch::Request#uuid appears only in Rails 3.2.1
unless ActionDispatch::Request.public_instance_methods.include?(:uuid)
require 'gon/compatibility/old_rails'
end
require 'gon/spec_helpers'
class Gon
class << self
def global
Gon::Global
end
def watch
Gon::Watch
end
def method_missing(method, *args, &block)
if method.to_s =~ /=$/
if public_method_name?(method)
raise "You can't use Gon public methods for storing data: #{method}"
end
if self == Gon && !current_gon
raise 'Assign request-specific gon variables only through `gon` helper, not through Gon constant'
end
set_variable(method.to_s.delete('='), args[0])
else
get_variable(method.to_s)
end
end
def get_variable(name)
current_gon.gon[name]
end
def set_variable(name, value)
current_gon.gon[name] = value
end
def merge_variable(name, value)
old_value = all_variables[name]
if value.is_a?(Hash) && old_value.is_a?(Hash)
value = old_value.deep_merge(value)
end
set_variable(name, value)
end
def push(data = {}, merge = false)
raise 'Object must have each_pair method' unless data.respond_to? :each_pair
if merge
data.each_pair do |name, value|
merge_variable(name.to_s, value)
end
else
data.each_pair do |name, value|
set_variable(name.to_s, value)
end
end
end
def all_variables
current_gon ? current_gon.gon : {}
end
def clear
current_gon.clear if current_gon
end
def rabl(*args)
data, options = Gon::Rabl.handler(args)
store_builder_data 'rabl', data, options
end
def jbuilder(*args)
ensure_template_handler_is_defined
data, options = Gon::Jbuilder.handler(args)
store_builder_data 'jbuilder', data, options
end
def inspect
'Gon'
end
private
def current_gon
RequestStore.store[:gon]
end
def store_builder_data(builder, data, options)
if options[:as]
set_variable(options[:as].to_s, data)
elsif data.is_a? Hash
data.each { |k, v| set_variable(k, v) }
else
set_variable(builder, data)
end
end
def public_method_name?(method)
public_methods.include?(method.to_s[0..-2].to_sym)
end
# JbuilderTemplate will not be defined if jbuilder is required
# before gon. By loading jbuilder again, JbuilderTemplate will
# now be defined
def ensure_template_handler_is_defined
load 'jbuilder.rb' unless defined?(JbuilderTemplate)
end
end
end
gon-6.4.0/lib/gon/ 0000755 0000041 0000041 00000000000 13747504657 013707 5 ustar www-data www-data gon-6.4.0/lib/gon/version.rb 0000644 0000041 0000041 00000000042 13747504657 015715 0 ustar www-data www-data class Gon
VERSION = '6.4.0'
end
gon-6.4.0/lib/gon/json_dumper.rb 0000644 0000041 0000041 00000001005 13747504657 016555 0 ustar www-data www-data class Gon
module JsonDumper
# Taken from ERB::Util
JSON_ESCAPE_REGEXP = /[\u2028\u2029&><]/u
JSON_ESCAPE = {
"&" => '\u0026',
">" => '\u003e',
"<" => '\u003c',
"\u2028" => '\u2028',
"\u2029" => '\u2029'
}
def self.dump(object)
dumped_json = MultiJson.dump object,
mode: :compat, escape_mode: :xss_safe, time_format: :ruby
escape(dumped_json)
end
def self.escape(json)
json.gsub(JSON_ESCAPE_REGEXP, JSON_ESCAPE)
end
end
end
gon-6.4.0/lib/gon/env_finder.rb 0000644 0000041 0000041 00000002234 13747504657 016354 0 ustar www-data www-data class Gon
module EnvFinder
ENV_CONTROLLER_KEY = 'action_controller.instance'
ENV_RESPONSE_KEY = 'action_controller.rescue.response'
class << self
def controller_env(options = {})
options[:controller] ||
(
current_gon &&
current_gon.env[ENV_CONTROLLER_KEY] ||
current_gon.env[ENV_RESPONSE_KEY].
instance_variable_get('@template').
instance_variable_get('@controller')
)
end
def template_path(options, extension)
if options[:template]
if right_extension?(extension, options[:template])
options[:template]
else
[options[:template], extension].join('.')
end
else
controller = controller_env(options).controller_path
action = controller_env(options).action_name
"app/views/#{controller}/#{action}.json.#{extension}"
end
end
private
def right_extension?(extension, template_path)
File.extname(template_path) == ".#{extension}"
end
def current_gon
RequestStore.store[:gon]
end
end
end
end
gon-6.4.0/lib/gon/helpers.rb 0000644 0000041 0000041 00000002343 13747504657 015700 0 ustar www-data www-data class Gon
module ViewHelpers
def include_gon(options = {})
if variables_for_request_present?
Gon::Base.render_data(options)
elsif Gon.global.all_variables.present? || options[:init].present?
Gon.clear
Gon::Base.render_data(options)
else
''
end
end
def include_gon_amd(options={})
Gon::Base.render_data(options.merge({amd: true}))
end
private
def variables_for_request_present?
current_gon && current_gon.gon
end
def current_gon
RequestStore.store[:gon]
end
end
module ControllerHelpers
def gon
if wrong_gon_request?
gon_request = Request.new(request.env)
gon_request.id = gon_request_uuid
RequestStore.store[:gon] = gon_request
end
Gon
end
private
def wrong_gon_request?
current_gon.blank? || current_gon.id != gon_request_uuid
end
def current_gon
RequestStore.store[:gon]
end
def gon_request_uuid
request.uuid
end
end
end
ActiveSupport.on_load :action_view do
ActionView::Base.send :include, Gon::ViewHelpers
end
ActiveSupport.on_load :action_controller do
ActionController::Base.send :include, Gon::ControllerHelpers
end
gon-6.4.0/lib/gon/base.rb 0000644 0000041 0000041 00000006602 13747504657 015152 0 ustar www-data www-data require 'ostruct'
class Gon
module Base
VALID_OPTION_DEFAULTS = {
namespace: 'gon',
camel_case: false,
camel_depth: 1,
watch: false,
need_tag: true,
type: false,
cdata: true,
global_root: 'global',
namespace_check: false,
amd: false,
nonce: nil
}
class << self
def render_data(options = {})
_o = define_options(options)
script = formatted_data(_o)
script = Gon::Escaper.escape_unicode(script)
script = Gon::Escaper.javascript_tag(script, _o.type, _o.cdata, _o.nonce) if _o.need_tag
script.html_safe
end
private
def define_options(options)
_o = OpenStruct.new
VALID_OPTION_DEFAULTS.each do |opt_name, default|
_o.send("#{opt_name}=", options.fetch(opt_name, default))
end
_o.watch = options[:watch] || !Gon.watch.all_variables.empty?
_o.cameled = _o.camel_case
_o
end
def formatted_data(_o)
script = ''
before, after = render_wrap(_o)
script << before
script << gon_variables(_o.global_root).
map { |key, val| render_variable(_o, key, val) }.join
script << (render_watch(_o) || '')
script << after
script
end
def render_wrap(_o)
if _o.amd
["define('#{_o.namespace}',[],function(){var gon={};", 'return gon;});']
else
before = \
if _o.namespace_check
"window.#{_o.namespace}=window.#{_o.namespace}||{};"
else
"window.#{_o.namespace}={};"
end
[before, '']
end
end
def render_variable(_o, key, value)
js_key = convert_key(key, _o.cameled)
if _o.amd
"gon['#{js_key}']=#{to_json(value, _o.camel_depth)};"
else
"#{_o.namespace}.#{js_key}=#{to_json(value, _o.camel_depth)};"
end
end
def render_watch(_o)
if _o.watch and Gon::Watch.all_variables.present?
if _o.amd
Gon.watch.render_amd
else
Gon.watch.render
end
end
end
def to_json(value, camel_depth)
# starts at 2 because 1 is the root key which is converted in the formatted_data method
Gon::JsonDumper.dump convert_hash_keys(value, 2, camel_depth)
end
def convert_hash_keys(value, current_depth, max_depth)
return value if current_depth > (max_depth.is_a?(Symbol) ? 1000 : max_depth)
case value
when Hash
Hash[value.map { |k, v|
[ convert_key(k, true), convert_hash_keys(v, current_depth + 1, max_depth) ]
}]
when Enumerable
value.map { |v| convert_hash_keys(v, current_depth + 1, max_depth) }
else
value
end
end
def gon_variables(global_root)
data = {}
if Gon.global.all_variables.present?
if global_root.blank?
data = Gon.global.all_variables
else
data[global_root.to_sym] = Gon.global.all_variables
end
end
data.merge(Gon.all_variables)
end
def convert_key(key, camelize)
cache = RequestStore.store[:gon_keys_cache] ||= {}
cache["#{key}_#{camelize}"] ||= camelize ? key.to_s.camelize(:lower) : key.to_s
end
end
end
end
gon-6.4.0/lib/gon/request.rb 0000644 0000041 0000041 00000000317 13747504657 015725 0 ustar www-data www-data class Gon
class Request
attr_reader :env, :gon
attr_accessor :id
def initialize(environment)
@env = environment
@gon = {}
end
def clear
@gon = {}
end
end
end
gon-6.4.0/lib/gon/jbuilder/ 0000755 0000041 0000041 00000000000 13747504657 015507 5 ustar www-data www-data gon-6.4.0/lib/gon/jbuilder/parser.rb 0000644 0000041 0000041 00000010214 13747504657 017326 0 ustar www-data www-data class Gon
module Jbuilder
class Parser
include ::ActionView::Helpers
attr_accessor :template_location, :controller, :_controller_name, :locals
def initialize(parse_params)
@template_location = parse_params[:template_path]
@controller = parse_params[:controller]
@_controller_name = parse_params[:controller_name]
@locals = parse_params[:locals] || {}
end
def parse!
assign_controller_variables controller
eval_controller_helpers controller
eval_controller_url_helpers controller
locals['__controller'] = controller
wrap_locals_in_methods locals
partials = find_partials(File.readlines(template_location))
source = partials.join('')
parse_source source, controller
end
def assign_controller_variables(controller)
controller.instance_variables.each do |name|
self.instance_variable_set \
name,
controller.instance_variable_get(name)
end
end
def eval_controller_helpers(controller)
controller._helper_methods.each do |meth|
self.class.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
def #{meth}(*args, &blk) # def current_user(*args, &blk)
__controller.send(%(#{meth}), *args, &blk) # controller.send(:current_user, *args, &blk)
end # end
ruby_eval
end
end
def eval_controller_url_helpers(controller)
if defined?(Rails) && Rails.respond_to?(:application)
Rails.application.routes.url_helpers.instance_methods.each do |meth|
self.class.class_eval <<-ruby_eval, __FILE__, __LINE__ + 1
def #{meth}(*args, &blk) # def user_path(*args, &blk)
__controller.send(%(#{meth}), *args, &blk) # controller.send(:user_path, *args, &blk)
end # end
ruby_eval
end
end
end
def wrap_locals_in_methods(locals)
locals.each do |name, value|
self.class.class_eval do
define_method "#{name}" do
return value
end
end
end
end
def parse_source(source, controller)
output = ::JbuilderTemplate.encode(controller) do |json|
eval source
end
JSON.parse(output)
end
def parse_partial(partial_line)
path = partial_line.match(/['"]([^'"]*)['"]/)[1]
path = parse_path path
options_hash = partial_line.match(/,(.*)/)[1]
set_options_from_hash(options_hash) if options_hash.present?
find_partials File.readlines(path)
end
def set_options_from_hash(options_hash)
options = eval "{#{options_hash}}"
options.each do |name, val|
self.instance_variable_set("@#{name.to_s}", val)
eval "def #{name}; self.instance_variable_get('@' + '#{name.to_s}'); end"
end
end
def parse_path(path)
return path if File.exists?(path)
if (splitted = path.split('/')).blank?
raise 'Something wrong with partial path in your jbuilder templates'
elsif splitted.size == 1
splitted.shift(@_controller_name)
end
construct_path(splitted)
end
def construct_path(args)
last_arg = args.pop
tmp_path = 'app/views/' + args.join('/')
path = path_with_ext(tmp_path + "/_#{last_arg}")
path || path_with_ext(tmp_path + "/#{last_arg}")
end
def path_with_ext(path)
return path if File.exists?(path)
return "#{path}.jbuilder" if File.exists?("#{path}.jbuilder")
return "#{path}.json.jbuilder" if File.exists?("#{path}.json.jbuilder")
end
def find_partials(lines = [])
lines.map do |line|
if line =~ /partial!/
parse_partial line
else
line
end
end.flatten
end
end
end
end
gon-6.4.0/lib/gon/escaper.rb 0000644 0000041 0000041 00000001662 13747504657 015663 0 ustar www-data www-data class Gon
module Escaper
extend ActionView::Helpers::JavaScriptHelper
extend ActionView::Helpers::TagHelper
class << self
def escape_unicode(javascript)
if javascript
result = escape_line_separator(javascript)
javascript.html_safe? ? result.html_safe : result
end
end
def javascript_tag(content, type, cdata, nonce)
options = {}
options.merge!( { type: 'text/javascript' } ) if type
options.merge!( { nonce: nonce } ) if nonce
content_tag(:script, javascript_cdata_section(content, cdata).html_safe, options)
end
def javascript_cdata_section(content, cdata)
if cdata
"\n//#{cdata_section("\n#{content}\n//")}\n"
else
"\n#{content}\n"
end
end
private
def escape_line_separator(javascript)
javascript.gsub(/\\u2028/u, '
')
end
end
end
end
gon-6.4.0/lib/gon/watch.rb 0000644 0000041 0000041 00000002737 13747504657 015353 0 ustar www-data www-data class Gon
class Watch < Gon
class << self
JS_FUNCTION = File.read(File.expand_path('../../../js/watch.js', __FILE__))
def render
JS_FUNCTION + "window.gon.watchedVariables=#{Gon::JsonDumper.dump all_variables};"
end
def render_amd
JS_FUNCTION + "gon.watchedVariables=#{Gon::JsonDumper.dump all_variables};"
end
def all_variables
@watch_variables || {}
end
def clear
@watch_variables = {}
end
private
def set_variable(name, value)
if return_variable?(name)
return_variable value
elsif Gon.send(:current_gon)
variable = {}
@watch_variables ||= {}
env = Gon.send(:current_gon).env
variable['url'] = env['ORIGINAL_FULLPATH'] || env['REQUEST_URI']
variable['method'] = env['REQUEST_METHOD']
variable['name'] = name
@watch_variables[name] = variable
super
end
end
def return_variable?(variable)
controller = Gon::EnvFinder.controller_env
params = controller.params
variable = variable.to_s.gsub('=', '')
controller.request.xhr? &&
params[:gon_return_variable] &&
params[:gon_watched_variable] == variable
end
def return_variable(value)
controller = Gon::EnvFinder.controller_env
controller.render json: Gon::Escaper.escape_unicode(Gon::JsonDumper.dump value)
end
end
end
end
gon-6.4.0/lib/gon/jbuilder.rb 0000644 0000041 0000041 00000002554 13747504657 016042 0 ustar www-data www-data class Gon
module Jbuilder
class << self
def handler(args, global = false)
options = parse_options_from args
valid_options? options, global
controller = Gon::EnvFinder.controller_env(options)
controller_name = global ? '' : controller.controller_path
parser = Gon::Jbuilder::Parser.new(
template_path: Gon::EnvFinder.template_path(options, 'jbuilder'),
controller: controller,
controller_name: controller_name,
locals: options[:locals]
)
data = parser.parse!
[data, options]
end
private
def valid_options?(options, global)
if global && !options[:template]
raise 'You should provide :template when use jbuilder with global variables'
end
end
def parse_options_from(args)
if old_api? args
text = "[DEPRECATION] view_path argument is now optional. "
text << "If you need to specify it, "
text << "please use gon.jbuilder(:template => 'path')"
warn text
args.extract_options!.merge(:template => args[0])
elsif new_api? args
args.first
else
{}
end
end
def old_api?(args)
args.first.is_a? String
end
def new_api?(args)
args.first.is_a? Hash
end
end
end
end
gon-6.4.0/lib/gon/global.rb 0000644 0000041 0000041 00000001415 13747504657 015475 0 ustar www-data www-data class Gon
class Global < Gon
class << self
def all_variables
@global_vars || {}
end
def clear
@global_vars = {}
end
def inspect
'Gon::Global'
end
def rabl(*args)
data, options = Gon::Rabl.handler(args, true)
store_builder_data 'rabl', data, options
end
def jbuilder(*args)
ensure_template_handler_is_defined
data, options = Gon::Jbuilder.handler(args, true)
store_builder_data 'jbuilder', data, options
end
private
def get_variable(name)
@global_vars ||= {}
@global_vars[name]
end
def set_variable(name, value)
@global_vars ||= {}
@global_vars[name] = value
end
end
end
end
gon-6.4.0/lib/gon/spec_helpers.rb 0000644 0000041 0000041 00000001336 13747504657 016713 0 ustar www-data www-data class Gon
module SpecHelper
module Rails
extend ActiveSupport::Concern
module ClassMethods
module GonSession
def process(*, **)
# preload threadlocal & store controller instance
if controller.is_a? ActionController::Base
controller.gon
Gon.send(:current_gon).env[Gon::EnvFinder::ENV_CONTROLLER_KEY] =
controller
end
super
end
end
def new(*)
super.extend(GonSession)
end
end
end
end
end
if ENV['RAILS_ENV'] == 'test' && defined?(ActionController::TestCase::Behavior)
ActionController::TestCase::Behavior.send :include, Gon::SpecHelper::Rails
end
gon-6.4.0/lib/gon/compatibility/ 0000755 0000041 0000041 00000000000 13747504657 016560 5 ustar www-data www-data gon-6.4.0/lib/gon/compatibility/old_rails.rb 0000644 0000041 0000041 00000000366 13747504657 021062 0 ustar www-data www-data require 'securerandom'
class Gon
module ControllerHelpers
private
# override this since ActionDispatch::Request#uuid appears only in Rails 3.2.1
def gon_request_uuid
@gon_request_uuid ||= SecureRandom.uuid
end
end
end
gon-6.4.0/lib/gon/rabl.rb 0000644 0000041 0000041 00000005122 13747504657 015154 0 ustar www-data www-data require 'action_view'
begin
require 'rabl' # use rabl gem if it's available
rescue LoadError
end
begin
require 'rabl-rails' # use rabl-rails gem if it's available
rescue LoadError
end
class Gon
module Rabl
class << self
def handler(args, global = false)
options = parse_options_from args, global
if global && !options[:template]
raise 'You should provide :template when use rabl with global variables'
end
data = parse_rabl \
Gon::EnvFinder.template_path(options, 'rabl'),
Gon::EnvFinder.controller_env(options),
options[:locals]
[data, options]
end
private
def parse_rabl(rabl_path, controller, locals)
if defined? ::Rabl
parse_with_rabl rabl_path, controller, locals
elsif defined? ::RablRails
parse_with_rabl_rails rabl_path, controller, locals
else
raise 'rabl or rabl-rails must be required in order to use gon.rabl'
end
end
def parse_with_rabl(rabl_path, controller, locals)
locals ||= {}
source = File.read(rabl_path)
include_helpers
rabl_engine = ::Rabl::Engine.new(source, :format => 'json', :template => rabl_path)
output = rabl_engine.render(controller, locals)
JSON.parse(output)
end
def parse_with_rabl_rails(rabl_path, controller, locals)
locals ||= {}
source = File.read(rabl_path)
original_formats = controller.formats
controller.formats = [:json]
view_context = controller.send(:view_context)
locals.each { |k, v| view_context.assigns[k.to_s] = v }
output = RablRails::Library.instance.get_rendered_template(source, view_context)
controller.formats = original_formats
JSON.parse(output)
end
def parse_options_from(args, global)
if old_api? args
unless global
text = "[DEPRECATION] view_path argument is now optional. "
text << "If you need to specify it, "
text << "please use gon.rabl(:template => 'path')"
warn text
end
args.extract_options!.merge(:template => args[0])
elsif new_api? args
args.first
else
{}
end
end
def include_helpers
unless ::Rabl::Engine.include? ::ActionView::Helpers
::Rabl::Engine.send(:include, ::ActionView::Helpers)
end
end
def old_api?(args)
args.first.is_a? String
end
def new_api?(args)
args.first.is_a? Hash
end
end
end
end
gon-6.4.0/doc/ 0000755 0000041 0000041 00000000000 13747504657 013123 5 ustar www-data www-data gon-6.4.0/doc/logo.png 0000644 0000041 0000041 00000046735 13747504657 014610 0 ustar www-data www-data PNG
IHDR , p Z]8 pHYs
OiCCPPhotoshop ICC profile xڝSgTS=BKKoR RB&*! J!QEEȠQ,
!{kּ>H3Q5B.@
$p d!s# ~<<+" x M0B\t8K @zB @F&S