skozlov-netzke-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|