skozlov-netzke-core 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/LICENSE +20 -0
- data/Rakefile +15 -0
- data/generators/netzke_core/USAGE +8 -0
- data/generators/netzke_core/netzke_core_generator.rb +13 -0
- data/generators/netzke_core/templates/create_netzke_layouts.rb +14 -0
- data/generators/netzke_core/templates/create_netzke_preferences.rb +18 -0
- data/generators/netzke_core/templates/netzke.html.erb +10 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/javascripts/core.js +126 -0
- data/lib/app/controllers/netzke_controller.rb +16 -0
- data/lib/app/models/netzke_layout.rb +75 -0
- data/lib/app/models/netzke_preference.rb +66 -0
- data/lib/netzke/base.rb +198 -0
- data/lib/netzke/controller_extensions.rb +87 -0
- data/lib/netzke/core_ext.rb +77 -0
- data/lib/netzke/js_class_builder.rb +125 -0
- data/lib/netzke-core.rb +22 -0
- data/lib/vendor/facets/hash/recursive_merge.rb +28 -0
- data/netzke-core.gemspec +32 -0
- data/tasks/netzke_core_tasks.rake +4 -0
- data/test/app_root/app/controllers/application.rb +2 -0
- data/test/app_root/config/boot.rb +114 -0
- data/test/app_root/config/database.yml +21 -0
- data/test/app_root/config/environment.rb +13 -0
- data/test/app_root/config/environments/in_memory.rb +0 -0
- data/test/app_root/config/environments/mysql.rb +0 -0
- data/test/app_root/config/environments/postgresql.rb +0 -0
- data/test/app_root/config/environments/sqlite.rb +0 -0
- data/test/app_root/config/environments/sqlite3.rb +0 -0
- data/test/app_root/config/routes.rb +4 -0
- data/test/app_root/script/console +6 -0
- data/test/core_ext_test.rb +35 -0
- data/test/netzke_core_test.rb +136 -0
- data/test/test_helper.rb +20 -0
- data/uninstall.rb +1 -0
- metadata +109 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
module Netzke
|
2
|
+
module ControllerExtensions
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ControllerClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
def method_missing(method_name)
|
8
|
+
if self.class.widget_config_storage == {}
|
9
|
+
super
|
10
|
+
else
|
11
|
+
widget, *action = method_name.to_s.split('__')
|
12
|
+
widget = widget.to_sym
|
13
|
+
action = !action.empty? && action.join("__").to_sym
|
14
|
+
|
15
|
+
# only widget's actions starting with "interface_" are accessible from outside (security)
|
16
|
+
if action
|
17
|
+
interface_action = action.to_s.index('__') ? action : "interface_#{action}"
|
18
|
+
|
19
|
+
# widget module
|
20
|
+
widget_class = "Netzke::#{self.class.widget_config_storage[widget][:widget_class_name]}".constantize
|
21
|
+
|
22
|
+
# instantiate the server part of the widget
|
23
|
+
widget_instance = widget_class.new(self.class.widget_config_storage[widget].merge(:controller => self)) # OPTIMIZE: top-level widgets have access to the controller - can we avoid that?
|
24
|
+
render :text => widget_instance.send(interface_action, params)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module ControllerClassMethods
|
30
|
+
|
31
|
+
# widget_config_storage for all widgets
|
32
|
+
def widget_config_storage
|
33
|
+
@@widget_config_storage ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Use this method to declare a widget in the controller
|
38
|
+
#
|
39
|
+
def netzke_widget(name, config={})
|
40
|
+
# which module is the widget?
|
41
|
+
config[:widget_class_name] ||= name.to_s.classify
|
42
|
+
config[:name] ||= name
|
43
|
+
|
44
|
+
# register the widget config in the storage
|
45
|
+
widget_config_storage[name] = config
|
46
|
+
|
47
|
+
# provide widget helpers
|
48
|
+
ActionView::Base.module_eval <<-END_EVAL, __FILE__, __LINE__
|
49
|
+
def #{name}_widget_instance(config = {})
|
50
|
+
# get the global config from the controller's singleton class
|
51
|
+
global_config = controller.class.widget_config_storage[:#{name}]
|
52
|
+
|
53
|
+
# when instantiating a client side instance, the configuration may be overwritten
|
54
|
+
# (but the server side will know nothing about it!)
|
55
|
+
local_config = global_config.merge(config)
|
56
|
+
|
57
|
+
# instantiate it
|
58
|
+
widget_instance = Netzke::#{config[:widget_class_name]}.new(local_config)
|
59
|
+
|
60
|
+
# return javascript code for instantiating on the javascript level
|
61
|
+
widget_instance.js_widget_instance
|
62
|
+
end
|
63
|
+
|
64
|
+
def #{name}_class_definition
|
65
|
+
config = controller.class.widget_config_storage[:#{name}]
|
66
|
+
Netzke::#{config[:widget_class_name]}.new(config).js_missing_code
|
67
|
+
end
|
68
|
+
END_EVAL
|
69
|
+
|
70
|
+
# add controller action which will render a simple HTML page containing the widget
|
71
|
+
define_method("#{name}_test") do
|
72
|
+
render :inline => %Q(
|
73
|
+
<script type="text/javascript" charset="utf-8">
|
74
|
+
<%= #{name}_class_definition %>
|
75
|
+
Ext.onReady(function(){
|
76
|
+
<%= #{name}_widget_instance %>
|
77
|
+
#{name.to_js}.render("#{name.to_s.split('_').join('-')}");
|
78
|
+
})
|
79
|
+
</script>
|
80
|
+
<div id="#{name.to_s.split('_').join('-')}"></div>
|
81
|
+
), :layout => "netzke"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Recursively convert the keys. Example:
|
4
|
+
# irb> {:bla_bla => 1, "wow_now" => {:look_ma => true}}.convert_keys{|k| k.camelize}
|
5
|
+
# irb> => {:BlaBla => 1, "WowNow" => {:LookMa => true}}
|
6
|
+
def convert_keys(&block)
|
7
|
+
block_given? ? self.inject({}) do |h,(k,v)|
|
8
|
+
h[k.is_a?(Symbol) ? yield(k.to_s).to_sym : yield(k.to_s)] = v.respond_to?('convert_keys') ? v.convert_keys(&block) : v
|
9
|
+
h
|
10
|
+
end : self
|
11
|
+
end
|
12
|
+
|
13
|
+
# First camelizes the keys, then convert the whole hash to JSON
|
14
|
+
def to_js
|
15
|
+
# self.delete_if{ |k,v| v.nil? } # we don't need to explicitely pass null values to javascript
|
16
|
+
self.recursive_delete_if_nil.convert_keys{|k| k.camelize(:lower)}.to_json
|
17
|
+
end
|
18
|
+
|
19
|
+
# Converts values to strings
|
20
|
+
def stringify_values!
|
21
|
+
self.each_pair{|k,v| self[k] = v.to_s if v.is_a?(Symbol)}
|
22
|
+
end
|
23
|
+
|
24
|
+
def recursive_delete_if_nil
|
25
|
+
self.inject({}) do |h,(k,v)|
|
26
|
+
if !v.nil?
|
27
|
+
h[k] = v.respond_to?('recursive_delete_if_nil') ? v.recursive_delete_if_nil : v
|
28
|
+
end
|
29
|
+
h
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
class Array
|
36
|
+
# Camelizes the keys of hashes and converts them to JSON
|
37
|
+
def to_js
|
38
|
+
self.recursive_delete_if_nil.map{|el| el.is_a?(Hash) ? el.convert_keys{|k| k.camelize(:lower)} : el}.to_json
|
39
|
+
end
|
40
|
+
|
41
|
+
# Applies convert_keys to each element which responds to convert_keys
|
42
|
+
def convert_keys(&block)
|
43
|
+
block_given? ? self.map do |i|
|
44
|
+
i.respond_to?('convert_keys') ? i.convert_keys(&block) : i
|
45
|
+
end : self
|
46
|
+
end
|
47
|
+
|
48
|
+
def recursive_delete_if_nil
|
49
|
+
self.map{|el| el.respond_to?('recursive_delete_if_nil') ? el.recursive_delete_if_nil : el}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class String
|
54
|
+
# Converts self to "literal JSON"-string - one that doesn't get quotes appended when being sent "to_json" method
|
55
|
+
def l
|
56
|
+
def self.to_json
|
57
|
+
self
|
58
|
+
end
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_js
|
63
|
+
self.camelize(:lower)
|
64
|
+
end
|
65
|
+
|
66
|
+
# removes JS-comments (both single-line and multiple-line) from the string
|
67
|
+
def strip_js_comments
|
68
|
+
regexp = /\/\/.*$|(?m:\/\*.*?\*\/)/
|
69
|
+
self.gsub(regexp, '')
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class Symbol
|
74
|
+
def to_js
|
75
|
+
self.to_s.camelize(:lower).to_sym
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Netzke
|
2
|
+
#
|
3
|
+
# Module which provides JS-class generation functionality for the widgets ("client-side"). This code is executed only once per widget class, and the results are cached at the server (unless widget specifies config[:no_caching] => true).
|
4
|
+
# Included into Netzke::Base class
|
5
|
+
# Most of the methods below are meant to be overwritten by a concrete widget class.
|
6
|
+
#
|
7
|
+
module JsClassBuilder
|
8
|
+
# the JS (Ext) class that we inherit from
|
9
|
+
def js_base_class; "Ext.Panel"; end
|
10
|
+
|
11
|
+
# widget's actions that are loaded at the moment of instantiating a widget
|
12
|
+
def actions; null; end
|
13
|
+
|
14
|
+
# widget's tools that are loaded at the moment of instantiating a widget see (js_config method)
|
15
|
+
def tools; []; end
|
16
|
+
|
17
|
+
def tbar; null; end
|
18
|
+
|
19
|
+
def bbar; null; end
|
20
|
+
|
21
|
+
# functions and properties that will be used to extend the functionality of (Ext) JS-class specified in js_base_class
|
22
|
+
def js_extend_properties; {}; end
|
23
|
+
|
24
|
+
# code executed before and after the constructor
|
25
|
+
def js_before_constructor; ""; end
|
26
|
+
def js_after_constructor; ""; end
|
27
|
+
|
28
|
+
# widget's listeners
|
29
|
+
def js_listeners; {}; end
|
30
|
+
|
31
|
+
# widget's menus
|
32
|
+
def js_menus; []; end
|
33
|
+
|
34
|
+
# items
|
35
|
+
def js_items; null; end
|
36
|
+
|
37
|
+
# default config that is passed into the constructor
|
38
|
+
def js_default_config
|
39
|
+
{
|
40
|
+
:title => short_widget_class_name,
|
41
|
+
:listeners => js_listeners,
|
42
|
+
:tools => "config.tools".l,
|
43
|
+
:actions => "config.actions".l,
|
44
|
+
:tbar => "config.tbar".l,
|
45
|
+
:bbar => "config.bbar".l,
|
46
|
+
:items => js_items,
|
47
|
+
:height => 400,
|
48
|
+
:width => 800,
|
49
|
+
:border => false
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
# declaration of widget's class (stored directly in the cache storage at the client side to be reused at the moment of widget instantiation)
|
54
|
+
def js_class
|
55
|
+
<<-JS
|
56
|
+
|
57
|
+
/* Wow, look...
|
58
|
+
Wow, look...
|
59
|
+
Wow, look...
|
60
|
+
Wow, look...
|
61
|
+
Wow, look...
|
62
|
+
Wow, look...
|
63
|
+
Wow, look...
|
64
|
+
Wow, look...
|
65
|
+
*/
|
66
|
+
|
67
|
+
Ext.componentCache['#{short_widget_class_name}'] = Ext.extend(#{js_base_class}, Ext.chainApply([Ext.widgetMixIn, {
|
68
|
+
constructor: function(config){
|
69
|
+
this.widgetInit(config);
|
70
|
+
#{js_before_constructor}
|
71
|
+
Ext.componentCache['#{short_widget_class_name}'].superclass.constructor.call(this, Ext.apply(#{js_default_config.to_js}, config));
|
72
|
+
#{js_after_constructor}
|
73
|
+
this.setEvents();
|
74
|
+
this.addMenus(#{js_menus.to_js});
|
75
|
+
}
|
76
|
+
}, #{js_extend_properties.to_js}]))
|
77
|
+
JS
|
78
|
+
end
|
79
|
+
|
80
|
+
# generate instantiating - used when a widget is generated stand-alone (as a part of a HTML page)
|
81
|
+
def js_widget_instance
|
82
|
+
%Q(var #{config[:name].to_js} = new Ext.componentCache['#{short_widget_class_name}'](#{js_config.to_js});)
|
83
|
+
end
|
84
|
+
|
85
|
+
# the config that is send from the server and is used for instantiating a widget
|
86
|
+
def js_config
|
87
|
+
res = {}
|
88
|
+
|
89
|
+
# recursively include configs of all (non-late) aggregatees, so that the widget can instantiate them, too
|
90
|
+
aggregatees.each_pair do |aggr_name, aggr_config|
|
91
|
+
next if aggr_config[:late_aggregation]
|
92
|
+
res["#{aggr_name}_config".to_sym] = aggregatee_instance(aggr_name.to_sym).js_config
|
93
|
+
end
|
94
|
+
|
95
|
+
# interface
|
96
|
+
interface = interface_points.inject({}){|h,interfacep| h.merge(interfacep => widget_action(interfacep))}
|
97
|
+
res.merge!(:interface => interface)
|
98
|
+
|
99
|
+
res.merge!(:widget_class_name => short_widget_class_name)
|
100
|
+
|
101
|
+
res.merge!(config[:ext_config])
|
102
|
+
res.merge!(:id => @id_name)
|
103
|
+
|
104
|
+
# include tools and actions
|
105
|
+
res.merge!(:tools => tools)
|
106
|
+
res.merge!(:actions => actions)
|
107
|
+
res
|
108
|
+
end
|
109
|
+
|
110
|
+
# class definition of the widget plus that of all the dependencies, minus those that are specified as dependencies_to_exclude
|
111
|
+
def js_missing_code(dependencies_to_exclude = [])
|
112
|
+
result = ""
|
113
|
+
dependencies.each do |dep_name|
|
114
|
+
dependency_class = "Netzke::#{dep_name}".constantize
|
115
|
+
result << dependency_class.new(config).js_missing_code(dependencies_to_exclude)
|
116
|
+
end
|
117
|
+
result << js_class.strip_js_comments unless dependencies_to_exclude.include?(short_widget_class_name) && !config[:no_caching]
|
118
|
+
result
|
119
|
+
end
|
120
|
+
|
121
|
+
# little helpers
|
122
|
+
def this; "this".l; end
|
123
|
+
def null; "null".l; end
|
124
|
+
end
|
125
|
+
end
|
data/lib/netzke-core.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# NetzkeCore
|
2
|
+
require 'netzke/js_class_builder'
|
3
|
+
require 'netzke/base'
|
4
|
+
require 'netzke/core_ext'
|
5
|
+
require 'netzke/controller_extensions'
|
6
|
+
|
7
|
+
# Vendor
|
8
|
+
require 'vendor/facets/hash/recursive_merge'
|
9
|
+
|
10
|
+
|
11
|
+
%w{ models controllers }.each do |dir|
|
12
|
+
path = File.join(File.dirname(__FILE__), 'app', dir)
|
13
|
+
$LOAD_PATH << path
|
14
|
+
ActiveSupport::Dependencies.load_paths << path
|
15
|
+
ActiveSupport::Dependencies.load_once_paths.delete(path)
|
16
|
+
end
|
17
|
+
|
18
|
+
ActionController::Base.class_eval do
|
19
|
+
include Netzke::ControllerExtensions
|
20
|
+
end
|
21
|
+
|
22
|
+
# Netzke::Base.config[:javascripts] << "#{File.dirname(__FILE__)}/../javascripts/core.js"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Hash
|
2
|
+
# Same as Hash#merge but recursively merges sub-hashes.
|
3
|
+
def recursive_merge(other)
|
4
|
+
hash = self.dup
|
5
|
+
other.each do |key, value|
|
6
|
+
myval = self[key]
|
7
|
+
if value.is_a?(Hash) && myval.is_a?(Hash)
|
8
|
+
hash[key] = myval.recursive_merge(value)
|
9
|
+
else
|
10
|
+
hash[key] = value
|
11
|
+
end
|
12
|
+
end
|
13
|
+
hash
|
14
|
+
end
|
15
|
+
|
16
|
+
# Same as Hash#merge! but recursively merges sub-hashes.
|
17
|
+
def recursive_merge!(other)
|
18
|
+
other.each do |key, value|
|
19
|
+
myval = self[key]
|
20
|
+
if value.is_a?(Hash) && myval.is_a?(Hash)
|
21
|
+
myval.recursive_merge!(value)
|
22
|
+
else
|
23
|
+
self[key] = value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
data/netzke-core.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{netzke-core}
|
5
|
+
s.version = "0.1.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Sergei Kozlov"]
|
9
|
+
s.date = %q{2008-12-27}
|
10
|
+
s.description = %q{Build ExtJS/Rails widgets with minimum effort}
|
11
|
+
s.email = %q{sergei@writelesscode.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/base.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/js_class_builder.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "README.markdown", "tasks/netzke_core_tasks.rake"]
|
13
|
+
s.files = ["CHANGELOG", "generators/netzke_core/netzke_core_generator.rb", "generators/netzke_core/templates/create_netzke_layouts.rb", "generators/netzke_core/templates/create_netzke_preferences.rb", "generators/netzke_core/templates/netzke.html.erb", "generators/netzke_core/USAGE", "init.rb", "install.rb", "javascripts/core.js", "lib/app/controllers/netzke_controller.rb", "lib/app/models/netzke_layout.rb", "lib/app/models/netzke_preference.rb", "lib/netzke/base.rb", "lib/netzke/controller_extensions.rb", "lib/netzke/core_ext.rb", "lib/netzke/js_class_builder.rb", "lib/netzke-core.rb", "lib/vendor/facets/hash/recursive_merge.rb", "LICENSE", "Manifest", "Rakefile", "README.markdown", "tasks/netzke_core_tasks.rake", "test/app_root/app/controllers/application.rb", "test/app_root/config/boot.rb", "test/app_root/config/database.yml", "test/app_root/config/environment.rb", "test/app_root/config/environments/in_memory.rb", "test/app_root/config/environments/mysql.rb", "test/app_root/config/environments/postgresql.rb", "test/app_root/config/environments/sqlite.rb", "test/app_root/config/environments/sqlite3.rb", "test/app_root/config/routes.rb", "test/app_root/script/console", "test/core_ext_test.rb", "test/netzke_core_test.rb", "test/test_helper.rb", "uninstall.rb", "netzke-core.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://writelesscode.com}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Netzke-core", "--main", "README.markdown"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{netzke-core}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Build ExtJS/Rails widgets with minimum effort}
|
21
|
+
s.test_files = ["test/core_ext_test.rb", "test/netzke_core_test.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 2
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
else
|
29
|
+
end
|
30
|
+
else
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# Allow customization of the rails framework path
|
2
|
+
RAILS_FRAMEWORK_ROOT = (ENV['RAILS_FRAMEWORK_ROOT'] || "#{File.dirname(__FILE__)}/../../../../../../vendor/rails") unless defined?(RAILS_FRAMEWORK_ROOT)
|
3
|
+
|
4
|
+
# Don't change this file!
|
5
|
+
# Configure your app in config/environment.rb and config/environments/*.rb
|
6
|
+
|
7
|
+
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
|
8
|
+
|
9
|
+
module Rails
|
10
|
+
class << self
|
11
|
+
def boot!
|
12
|
+
unless booted?
|
13
|
+
preinitialize
|
14
|
+
pick_boot.run
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def booted?
|
19
|
+
defined? Rails::Initializer
|
20
|
+
end
|
21
|
+
|
22
|
+
def pick_boot
|
23
|
+
(vendor_rails? ? VendorBoot : GemBoot).new
|
24
|
+
end
|
25
|
+
|
26
|
+
def vendor_rails?
|
27
|
+
File.exist?(RAILS_FRAMEWORK_ROOT)
|
28
|
+
end
|
29
|
+
|
30
|
+
def preinitialize
|
31
|
+
load(preinitializer_path) if File.exist?(preinitializer_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
def preinitializer_path
|
35
|
+
"#{RAILS_ROOT}/config/preinitializer.rb"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Boot
|
40
|
+
def run
|
41
|
+
load_initializer
|
42
|
+
Rails::Initializer.run(:set_load_path)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class VendorBoot < Boot
|
47
|
+
def load_initializer
|
48
|
+
require "#{RAILS_FRAMEWORK_ROOT}/railties/lib/initializer"
|
49
|
+
Rails::Initializer.run(:install_gem_spec_stubs)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class GemBoot < Boot
|
54
|
+
def load_initializer
|
55
|
+
self.class.load_rubygems
|
56
|
+
load_rails_gem
|
57
|
+
require 'initializer'
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_rails_gem
|
61
|
+
if version = self.class.gem_version
|
62
|
+
gem 'rails', version
|
63
|
+
else
|
64
|
+
gem 'rails'
|
65
|
+
end
|
66
|
+
rescue Gem::LoadError => load_error
|
67
|
+
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
|
68
|
+
exit 1
|
69
|
+
end
|
70
|
+
|
71
|
+
class << self
|
72
|
+
def rubygems_version
|
73
|
+
Gem::RubyGemsVersion rescue nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def gem_version
|
77
|
+
if defined? RAILS_GEM_VERSION
|
78
|
+
RAILS_GEM_VERSION
|
79
|
+
elsif ENV.include?('RAILS_GEM_VERSION')
|
80
|
+
ENV['RAILS_GEM_VERSION']
|
81
|
+
else
|
82
|
+
parse_gem_version(read_environment_rb)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def load_rubygems
|
87
|
+
require 'rubygems'
|
88
|
+
min_version = '1.1.1'
|
89
|
+
unless rubygems_version >= min_version
|
90
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
|
91
|
+
exit 1
|
92
|
+
end
|
93
|
+
|
94
|
+
rescue LoadError
|
95
|
+
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
|
96
|
+
exit 1
|
97
|
+
end
|
98
|
+
|
99
|
+
def parse_gem_version(text)
|
100
|
+
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
def read_environment_rb
|
105
|
+
environment_rb = "#{RAILS_ROOT}/config/environment.rb"
|
106
|
+
environment_rb = "#{HELPER_RAILS_ROOT}/config/environment.rb" unless File.exists?(environment_rb)
|
107
|
+
File.read(environment_rb)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# All that for this:
|
114
|
+
Rails.boot!
|
@@ -0,0 +1,21 @@
|
|
1
|
+
in_memory:
|
2
|
+
adapter: sqlite3
|
3
|
+
database: ":memory:"
|
4
|
+
verbosity: quiet
|
5
|
+
sqlite:
|
6
|
+
adapter: sqlite
|
7
|
+
dbfile: plugin_test.sqlite.db
|
8
|
+
sqlite3:
|
9
|
+
adapter: sqlite3
|
10
|
+
dbfile: plugin_test.sqlite3.db
|
11
|
+
postgresql:
|
12
|
+
adapter: postgresql
|
13
|
+
username: postgres
|
14
|
+
password: postgres
|
15
|
+
database: plugin_test
|
16
|
+
mysql:
|
17
|
+
adapter: mysql
|
18
|
+
host: localhost
|
19
|
+
username: root
|
20
|
+
password:
|
21
|
+
database: plugin_test
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
2
|
+
|
3
|
+
Rails::Initializer.run do |config|
|
4
|
+
config.cache_classes = false
|
5
|
+
config.whiny_nils = true
|
6
|
+
config.plugin_locators.unshift(
|
7
|
+
Class.new(Rails::Plugin::Locator) do
|
8
|
+
def plugins
|
9
|
+
[Rails::Plugin.new(File.expand_path('.'))]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
) unless defined?(PluginTestHelper::PluginLocator)
|
13
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'netzke/core_ext'
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
class CoreExtTest < ActiveSupport::TestCase
|
7
|
+
test "to_js" do
|
8
|
+
assert_equal({"aProperty" => true}, JSON.parse({:a_property => true}.to_js))
|
9
|
+
assert_equal({"aProperty" => true}, JSON.parse({:a_property => true, :nil_property => nil}.to_js))
|
10
|
+
assert_equal([{"aProperty" => true}, {"anotherProperty" => false}], JSON.parse([{:a_property => true}, {:another_property => false}].to_js))
|
11
|
+
assert_equal([{"aProperty" => true}, {"anotherProperty" =>false}], JSON.parse([{:a_property => true, :nil_property => nil}, {:another_property => false}].to_js))
|
12
|
+
end
|
13
|
+
|
14
|
+
test "recursive delete if nil" do
|
15
|
+
assert_equal({:a => 1, :b => {:c => 4, :d => 5}}, {:a => 1, :aa => nil, :b => {:c => 4, :d => 5, :cc => nil}}.recursive_delete_if_nil)
|
16
|
+
|
17
|
+
assert_equal({:a => [{:e => 5}, {:f => 7}], :b => {:c => 4, :d => 5}}, {:a => [{:e => 5, :ee => nil},{:f => 7, :ff => nil}], :aa => nil, :b => {:c => 4, :d => 5, :cc => nil}}.recursive_delete_if_nil)
|
18
|
+
|
19
|
+
assert_equal([
|
20
|
+
{:a => [{:e => 5}]},
|
21
|
+
{},
|
22
|
+
{:b => {:c => 4, :d => 5}}
|
23
|
+
], [
|
24
|
+
{:a => [{:e => 5, :ee => nil}]},
|
25
|
+
{:aa => nil},
|
26
|
+
{:b => {:c => 4, :d => 5, :cc => nil}}
|
27
|
+
].recursive_delete_if_nil)
|
28
|
+
end
|
29
|
+
|
30
|
+
test "convert keys" do
|
31
|
+
assert_equal([
|
32
|
+
{:aB => 1, :cDD => [{:lookMa => true},{:wowNow => true}]}
|
33
|
+
],[:a_b => 1, :c_d_d => [{:look_ma => true},{:wow_now => true}]].convert_keys{|k| k.camelize(:lower)})
|
34
|
+
end
|
35
|
+
end
|