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.
Files changed (38) hide show
  1. data/CHANGELOG +3 -0
  2. data/LICENSE +20 -0
  3. data/Rakefile +15 -0
  4. data/generators/netzke_core/USAGE +8 -0
  5. data/generators/netzke_core/netzke_core_generator.rb +13 -0
  6. data/generators/netzke_core/templates/create_netzke_layouts.rb +14 -0
  7. data/generators/netzke_core/templates/create_netzke_preferences.rb +18 -0
  8. data/generators/netzke_core/templates/netzke.html.erb +10 -0
  9. data/init.rb +1 -0
  10. data/install.rb +1 -0
  11. data/javascripts/core.js +126 -0
  12. data/lib/app/controllers/netzke_controller.rb +16 -0
  13. data/lib/app/models/netzke_layout.rb +75 -0
  14. data/lib/app/models/netzke_preference.rb +66 -0
  15. data/lib/netzke/base.rb +198 -0
  16. data/lib/netzke/controller_extensions.rb +87 -0
  17. data/lib/netzke/core_ext.rb +77 -0
  18. data/lib/netzke/js_class_builder.rb +125 -0
  19. data/lib/netzke-core.rb +22 -0
  20. data/lib/vendor/facets/hash/recursive_merge.rb +28 -0
  21. data/netzke-core.gemspec +32 -0
  22. data/tasks/netzke_core_tasks.rake +4 -0
  23. data/test/app_root/app/controllers/application.rb +2 -0
  24. data/test/app_root/config/boot.rb +114 -0
  25. data/test/app_root/config/database.yml +21 -0
  26. data/test/app_root/config/environment.rb +13 -0
  27. data/test/app_root/config/environments/in_memory.rb +0 -0
  28. data/test/app_root/config/environments/mysql.rb +0 -0
  29. data/test/app_root/config/environments/postgresql.rb +0 -0
  30. data/test/app_root/config/environments/sqlite.rb +0 -0
  31. data/test/app_root/config/environments/sqlite3.rb +0 -0
  32. data/test/app_root/config/routes.rb +4 -0
  33. data/test/app_root/script/console +6 -0
  34. data/test/core_ext_test.rb +35 -0
  35. data/test/netzke_core_test.rb +136 -0
  36. data/test/test_helper.rb +20 -0
  37. data/uninstall.rb +1 -0
  38. 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
@@ -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
@@ -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,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :netzke-core do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,2 @@
1
+ class ApplicationController < ActionController::Base
2
+ 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,4 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.connect ':controller/:action/:id'
3
+ map.connect ':controller/:action/:id.:format'
4
+ end
@@ -0,0 +1,6 @@
1
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
2
+ libs = " -r irb/completion"
3
+ libs << " -r test/test_helper"
4
+ libs << " -r console_app"
5
+ libs << " -r console_with_helpers"
6
+ exec "#{irb} #{libs} --simple-prompt"
@@ -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