ruby_ext_direct 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/Gemfile +1 -1
  2. data/README.markdown +60 -0
  3. data/lib/ext_direct/api.rb +68 -10
  4. data/lib/ext_direct/router.rb +25 -5
  5. data/lib/ext_direct/version.rb +1 -1
  6. data/ruby_ext_direct.gemspec +1 -0
  7. data/test/test_ext_direct.rb +19 -0
  8. metadata +17 -34
  9. data/README +0 -12
  10. data/examples/API/Gemfile +0 -29
  11. data/examples/API/app/actions/api_action.rb +0 -18
  12. data/examples/API/app/actions/home_action.rb +0 -11
  13. data/examples/API/app/actions/router_action.rb +0 -18
  14. data/examples/API/application.rb +0 -37
  15. data/examples/API/config.ru +0 -25
  16. data/examples/API/config/database.yml +0 -6
  17. data/examples/API/config/routes.rb +0 -6
  18. data/examples/API/public/NamesApp/app/store/NamesStore.js +0 -48
  19. data/examples/API/public/NamesApp/app/view/namesWindow.js +0 -21
  20. data/examples/API/public/NamesApp/app/view/ui/namesWindow.js +0 -58
  21. data/examples/API/public/NamesApp/designer.html +0 -19
  22. data/examples/API/public/NamesApp/designer.js +0 -32
  23. data/examples/API/public/NamesApp/designer_includeOrder.txt +0 -3
  24. data/examples/API/public/namesApp.xds +0 -200
  25. data/examples/rack/config.ru +0 -40
  26. data/examples/rack/exposed_classes/countries.rb +0 -10
  27. data/examples/rack/exposed_classes/names.rb +0 -82
  28. data/examples/rack/html/NamesApp/app/store/NamesStore.js +0 -56
  29. data/examples/rack/html/NamesApp/app/view/namesWindow.js +0 -49
  30. data/examples/rack/html/NamesApp/app/view/ui/namesWindow.js +0 -92
  31. data/examples/rack/html/NamesApp/designer.html +0 -19
  32. data/examples/rack/html/NamesApp/designer.js +0 -32
  33. data/examples/rack/html/NamesApp/designer_includeOrder.txt +0 -3
  34. data/examples/rack/html/names.xds +0 -275
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in ext_direct.gemspec
3
+ # Specify your gem's dependencies in ruby_ext_direct.gemspec
4
4
  gemspec
data/README.markdown ADDED
@@ -0,0 +1,60 @@
1
+ This is an attempt to implement **Ext.Direct** (see http://www.sencha.com/products/extjs/extdirect for more info)
2
+
3
+ I wanted to have a library that did not have to many dependencies.
4
+
5
+ The idea is very simple:
6
+
7
+ > 1. add an **'api'** and **'router'** endpoint to your backend.
8
+ > 2. expose your classes.
9
+
10
+ and you are set
11
+
12
+ #INSTALL#
13
+ gem install ruby_ext_direct
14
+ ---
15
+
16
+ #Example:#
17
+ (For more [examples](https://github.com/mehmetc/ruby_ext_direct_examples "EXAMPLES") )
18
+ ##A RACK based example##
19
+
20
+ ###*Gemfile*
21
+
22
+ gem 'ruby_ext_direct', :require => 'ext_direct'
23
+
24
+
25
+ ###*web_service.rb*
26
+
27
+ require 'rubygems'
28
+ require 'bundler/setup'
29
+ require 'rack'
30
+ require 'json'
31
+
32
+ require 'ext_direct'
33
+
34
+ #Expose all classes in a directory
35
+ ExtDirect::Api.expose_all("./exposed_classes")
36
+
37
+ #Generate a client-side descriptor
38
+ map '/api' do
39
+ run Proc.new { |env|
40
+ [200, {'Content-Type' => 'text/json'}, [ExtDirect::Api.to_json]]
41
+ }
42
+ end
43
+
44
+ #Route request to methods
45
+ map '/router' do
46
+ run Proc.new { |env|
47
+ result = ''
48
+
49
+ req = Rack::Request.new(env)
50
+ if req.post?
51
+ data = env["rack.input"].gets
52
+ result = ExtDirect::Router.route(data)
53
+ end
54
+
55
+ [200, {'Content-Type' => 'text/html'}, [result.to_json]]
56
+ }
57
+ end
58
+
59
+ TODO: add documentation
60
+ TODO: add rails engine
@@ -4,16 +4,17 @@ module ExtDirect
4
4
  # Simply expose a class
5
5
  # @author Mehmet Celik
6
6
  class Api
7
- attr_reader :exposed_api
8
-
9
- # Expose a class
7
+ @exposed_api_raw = nil
8
+ @router_url = '/router'
9
+
10
+ # Expose methods from a class and his ancestor, if class was inherited
10
11
  #
11
12
  # @author Mehmet Celik
12
13
  # @param [Class] class that needs to be exposed
13
14
  # @param [Hash] instructions to how to expose the class. For now just the ':only' key is accepted.
14
15
  # @return [Hash] returns a list of exposed classes
15
16
  def self.expose(class_to_expose, options = {})
16
- @exposed_api = {} if @exposed_api.nil?
17
+ @exposed_api_raw = {} if @exposed_api_raw.nil?
17
18
 
18
19
  methods = []
19
20
 
@@ -21,16 +22,36 @@ module ExtDirect
21
22
  raw_methods = options[:only] || []
22
23
  else
23
24
  raw_methods = class_to_expose.instance_methods(false) - (options[:except] || [])
25
+ raw_methods += class_to_expose.methods(false) - (options[:except] || [])
26
+ raw_methods += class_to_expose.ancestors[1].methods(false) - (options[:except] || [])
27
+ raw_methods += class_to_expose.ancestors[1].instance_methods(false) - (options[:except] || [])
24
28
  end
25
29
 
26
30
  raw_methods.uniq!
27
31
  raw_methods.each do |m|
28
32
  name = m
29
- len = class_to_expose.instance_method(m).parameters.size
30
- methods << {:name => name, :len => len}
33
+ parameters = []
34
+ method_to_run = nil
35
+
36
+ if class_to_expose.methods(false).include?(m)
37
+ method_to_run = class_to_expose.method(m)
38
+ elsif class_to_expose.instance_methods(false).include?(m)
39
+ method_to_run = class_to_expose.instance_method(m)
40
+ elsif class_to_expose.ancestors[1].methods(false).include?(m)
41
+ method_to_run = class_to_expose.ancestors[1].method(m)
42
+ elsif class_to_expose.ancestors[1].instance_methods(false).include?(m)
43
+ method_to_run = class_to_expose.ancestors[1].instance_method(m)
44
+ end
45
+
46
+ unless method_to_run.nil?
47
+ method_to_run.parameters.each do |p|
48
+ parameters << {:name => p[1].to_s, :optional => p[0] == :opt}
49
+ end
50
+ end
51
+ methods << {:name => name, :parameters => parameters}
31
52
  end
32
53
 
33
- @exposed_api.store(class_to_expose.name, methods)
54
+ @exposed_api_raw.store(class_to_expose.name, methods)
34
55
  end
35
56
 
36
57
  # Expose all classes in a directory(conviniance method)
@@ -38,7 +59,7 @@ module ExtDirect
38
59
  # @author Mehmet Celik
39
60
  # @param [String] Directory where all classes are stored
40
61
  def self.expose_all(class_dir)
41
- @exposed_api = {}
62
+ @exposed_api_raw = {}
42
63
 
43
64
  Dir.glob("#{class_dir}/**/*.rb").each do |r|
44
65
  rr = r.split("#{class_dir}/")[1].gsub('.rb','')
@@ -64,9 +85,46 @@ module ExtDirect
64
85
  # @author Mehmet Celik
65
86
  # @return [Hash] exposed classes
66
87
  def self.to_raw
67
- api = {:url => '/router',
88
+
89
+ api = {:url => @router_url || '/router',
68
90
  :type => 'remoting',
69
- :actions => @exposed_api}
91
+ :actions => self.exposed_api}
92
+ end
93
+ # Set the router url
94
+
95
+ # @author Mehmet Celik
96
+ # @param [String] router url defaults to '/router'
97
+ def self.router_url=(url = '/router')
98
+ @router_url = url
99
+ end
100
+
101
+ # Get the router url
102
+
103
+ # @author Mehmet Celik
104
+ # @return [String] router url
105
+ def self.router_url
106
+ @router_url
107
+ end
108
+
109
+ # TODO
110
+
111
+ # @author Mehmet Celik
112
+ # @param [String] router url defaults to '/router'
113
+ # @return [Hash] exposed API data
114
+ def self.exposed_api(show_parameters = false)
115
+ result = @exposed_api_raw
116
+ unless show_parameters
117
+ result = {}
118
+ @exposed_api_raw.each do |k,v|
119
+ methods = []
120
+ v.each do |method|
121
+ methods << {:name => method[:name], :len => method[:parameters].size}
122
+ end
123
+ result.store(k,methods)
124
+ end
125
+ end
126
+
127
+ result
70
128
  end
71
129
  end
72
130
  end
@@ -35,12 +35,32 @@ module ExtDirect
35
35
  klass = self.class.const_get(params[:klass_name])
36
36
  #call method on class
37
37
  klass_instance = klass.new
38
- method_to_call = klass_instance.method(params[:method_to_call_name].to_sym)
38
+
39
+ method_to_call = nil
40
+
41
+ method_to_call_name = params[:method_to_call_name].to_sym
42
+ =begin
43
+ if klass_instance.methods(false).include?(method_to_call_name)
44
+ method_to_call = klass_instance.method(method_to_call_name)
45
+ elsif klass_instance.instance_methods(false).include?( params[:method_to_call_name].to_sym)
46
+ method_to_call = klass_instance.instance_method(method_to_call_name)
47
+ elsif klass_instance.ancestors[1].methods(false).include?(method_to_call_name)
48
+ method_to_call = klass_instance.ancestors[1].method(method_to_call_name)
49
+ elsif klass_instance.ancestors[1].instance_methods(false).include?(method_to_call_name)
50
+ method_to_call = klass_instance.ancestors[1].instance_method(method_to_call_name)
51
+ end
52
+ =end
53
+
54
+
55
+ # method_to_call = klass_instance.method(params[:method_to_call_name].to_sym)
56
+ method_to_call = klass_instance.method(method_to_call_name)
39
57
 
40
- if method_to_call.parameters.size > 0
41
- data = method_to_call.call(params[:args])
42
- else
43
- data = method_to_call.call
58
+ unless method_to_call.nil?
59
+ if method_to_call.parameters.size > 0
60
+ data = method_to_call.call(params[:args]) || []
61
+ else
62
+ data = method_to_call.call || []
63
+ end
44
64
  end
45
65
 
46
66
  response = {
@@ -1,3 +1,3 @@
1
1
  module ExtDirect
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -21,4 +21,5 @@ Gem::Specification.new do |s|
21
21
  # specify any dependencies here; for example:
22
22
  # s.add_development_dependency "rspec"
23
23
  # s.add_runtime_dependency "rest-client"
24
+ s.add_dependency("json")
24
25
  end
@@ -14,6 +14,8 @@ class MyClass
14
14
  end
15
15
  end
16
16
 
17
+ class InheritedFromMyClass < MyClass
18
+ end
17
19
 
18
20
 
19
21
  class TestExtDirect < Test::Unit::TestCase
@@ -125,5 +127,22 @@ class TestExtDirect < Test::Unit::TestCase
125
127
  assert_equal(expected, result)
126
128
  end
127
129
  end
130
+
131
+ context 'Calling methods in sub classes' do
132
+ setup do
133
+ @request_without_arguments = "{\"action\":\"InheritedFromMyClass\",\"method\":\"method_without_arguments\",\"data\":null,\"type\":\"rpc\",\"tid\":1}"
134
+ ExtDirect::Api.expose InheritedFromMyClass
135
+ end
136
+
137
+ should "call method without parameters" do
138
+ expected = "method_without_arguments called"
139
+
140
+ result = ExtDirect::Router.route(@request_without_arguments)[:result]
141
+
142
+ assert_equal(expected, result)
143
+ end
144
+
145
+
146
+ end
128
147
  end
129
148
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ruby_ext_direct
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.2
5
+ version: 0.0.3
6
6
  platform: ruby
7
7
  authors:
8
8
  - Mehmet Celik
@@ -10,10 +10,19 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-10-23 00:00:00 +02:00
14
- default_executable:
15
- dependencies: []
16
-
13
+ date: 2012-03-22 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
17
26
  description: An attempt to implement Ext.Direct from Sencha
18
27
  email:
19
28
  - mehmet@celik.be
@@ -26,7 +35,7 @@ extra_rdoc_files: []
26
35
  files:
27
36
  - .gitignore
28
37
  - Gemfile
29
- - README
38
+ - README.markdown
30
39
  - Rakefile
31
40
  - doc/ExtDirect.html
32
41
  - doc/ExtDirect/Api.html
@@ -46,39 +55,12 @@ files:
46
55
  - doc/js/jquery.js
47
56
  - doc/method_list.html
48
57
  - doc/top-level-namespace.html
49
- - examples/API/Gemfile
50
- - examples/API/app/actions/api_action.rb
51
- - examples/API/app/actions/home_action.rb
52
- - examples/API/app/actions/router_action.rb
53
- - examples/API/application.rb
54
- - examples/API/config.ru
55
- - examples/API/config/database.yml
56
- - examples/API/config/routes.rb
57
- - examples/API/public/NamesApp/app/store/NamesStore.js
58
- - examples/API/public/NamesApp/app/view/namesWindow.js
59
- - examples/API/public/NamesApp/app/view/ui/namesWindow.js
60
- - examples/API/public/NamesApp/designer.html
61
- - examples/API/public/NamesApp/designer.js
62
- - examples/API/public/NamesApp/designer_includeOrder.txt
63
- - examples/API/public/namesApp.xds
64
- - examples/rack/config.ru
65
- - examples/rack/exposed_classes/countries.rb
66
- - examples/rack/exposed_classes/names.rb
67
- - examples/rack/html/.DS_Store
68
- - examples/rack/html/NamesApp/app/store/NamesStore.js
69
- - examples/rack/html/NamesApp/app/view/namesWindow.js
70
- - examples/rack/html/NamesApp/app/view/ui/namesWindow.js
71
- - examples/rack/html/NamesApp/designer.html
72
- - examples/rack/html/NamesApp/designer.js
73
- - examples/rack/html/NamesApp/designer_includeOrder.txt
74
- - examples/rack/html/names.xds
75
58
  - lib/ext_direct.rb
76
59
  - lib/ext_direct/api.rb
77
60
  - lib/ext_direct/router.rb
78
61
  - lib/ext_direct/version.rb
79
62
  - ruby_ext_direct.gemspec
80
63
  - test/test_ext_direct.rb
81
- has_rdoc: true
82
64
  homepage: https://github.com/mehmetc/ruby_ext_direct
83
65
  licenses: []
84
66
 
@@ -102,9 +84,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
102
84
  requirements: []
103
85
 
104
86
  rubyforge_project: ruby_ext_direct
105
- rubygems_version: 1.6.2
87
+ rubygems_version: 1.8.15
106
88
  signing_key:
107
89
  specification_version: 3
108
90
  summary: An attempt to implement Ext.Direct from Sencha
109
91
  test_files:
110
92
  - test/test_ext_direct.rb
93
+ has_rdoc:
data/README DELETED
@@ -1,12 +0,0 @@
1
- This is an attempt to implement Ext.Direct (see http://www.sencha.com/products/extjs/extdirect for more info)
2
-
3
- I wanted to have a library that did not explicitly bind to any ORM(like ActiveRecord, Datamapper, ...).
4
- The idea is very simple just add an 'api' and 'router' path to your backend point to your exposed classes and you are set.
5
-
6
- Example: (See examples directory for more)
7
- Add this to your Gemfile
8
- gem 'ruby_ext_direct', :require => 'ext_direct'
9
-
10
-
11
- TODO: add documentation
12
- TODO: add rails engine
data/examples/API/Gemfile DELETED
@@ -1,29 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'cramp'
4
-
5
- # Async webserver for running a cramp application
6
- gem 'thin'
7
-
8
- # Rack based routing
9
- gem 'http_router'
10
-
11
- # Collection of async-proof rack middlewares - https://github.com/rkh/async-rack.git
12
- gem 'async-rack'
13
-
14
- # For async Active Record models
15
- gem 'mysql2', '~> 0.2.11'
16
- gem 'activerecord', :require => 'active_record'
17
-
18
- gem 'ext_direct', '0.0.1'
19
-
20
- # Using Fibers + async callbacks to emulate synchronous programming
21
- # gem 'em-synchrony'
22
-
23
- # Generic interface to multiple Ruby template engines - https://github.com/rtomayko/tilt
24
- # gem 'tilt'
25
-
26
- group :development do
27
- # Development gems
28
- # gem 'ruby-debug19'
29
- end
@@ -1,18 +0,0 @@
1
- #require 'ext_direct'
2
-
3
- class ApiAction < Cramp::Action
4
- on_start :render_api
5
-
6
- def render_api
7
- # ExtDirect::Api.expose_all "/Users/mehmetc/Sources/LBT/ext_direct/examples/rack/exposed_classes"
8
- render ExtDirect::Api.to_json
9
- finish
10
- end
11
-
12
- def respond_with
13
- # content_type = params[:format] == 'xml' ? 'application/xml' : 'application/json'
14
- [200, {'Content-Type' => 'application/json'}]
15
- end
16
-
17
-
18
- end
@@ -1,11 +0,0 @@
1
- class HomeAction < Cramp::Action
2
- use_fiber_pool do |pool|
3
- # Checkin database connection after each callback
4
- pool.generic_callbacks << proc { ActiveRecord::Base.clear_active_connections! }
5
- end
6
-
7
- def start
8
- render "Hello World!"
9
- finish
10
- end
11
- end
@@ -1,18 +0,0 @@
1
- class RouterAction < Cramp::Action
2
- on_start :route_data_to_class
3
-
4
- def route_data_to_class
5
- ExtDirect::Api.expose_all "/Users/mehmetc/Sources/LBT/ext_direct/examples/rack/exposed_classes"
6
- data = ''
7
- if request.post?
8
- data = request.env['rack.input'].gets
9
- result = ExtDirect::Router.route(data)
10
- end
11
-
12
- render result.to_json
13
- end
14
-
15
- def respond_with
16
- [200, {'Content-Type' => 'application/json'}]
17
- end
18
- end