skozlov-netzke-core 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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