appbase 0.0.2 → 0.0.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4287ccf943cbb1549e3524e7e20d676f0bc1fc16
4
- data.tar.gz: 91a967f151ead8e747170cc8e4129162b2b4d7ff
3
+ metadata.gz: d24b5aefaba7ab3de7fa709dced97ff3d2b24539
4
+ data.tar.gz: 8a666834bc752c9128b37e94845ae4ca7272f192
5
5
  SHA512:
6
- metadata.gz: d5c3719f395cd41c315df6ae9af9efd9f8e683af7ed464eb9aa903d999e19d224cad5f9a84c859feac49f543589965ac6e258cb2c5d60e2bbaf1562c0a051ff1
7
- data.tar.gz: 10597b8d9d43506240431a9f6e89b886e073841c90363c69cf7e26c5336dd080f5ac656e8f5380582f268f4794c6d732bf4db3476be107a1a912a7892f6f20e4
6
+ metadata.gz: b41847490b989888115964cda8848be3d3417117391958dadebc0d6696f01daaa090f0e99fedb4c7177e0763f370cb067a73e46b90e1915ecd6b4a06a3ecb2c0
7
+ data.tar.gz: 129624fb6e14b2c6ef94a0f3033997101e79b3b7ac50081ef9f93f38be7924ecb3811d42ec62eaf6c5376725d06da3dcd5fb5286d50aa227767e85f960e6f750
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
1
  [![Build Status](https://travis-ci.org/bestmike007/appbase.svg?branch=master)](https://travis-ci.org/bestmike007/appbase)
2
+ [![Code Climate](https://codeclimate.com/github/bestmike007/appbase/badges/gpa.svg)](https://codeclimate.com/github/bestmike007/appbase)
3
+ [![Test Coverage](https://codeclimate.com/github/bestmike007/appbase/badges/coverage.svg)](https://codeclimate.com/github/bestmike007/appbase)
4
+ [![Gem Version](https://badge.fury.io/rb/appbase.svg)](http://badge.fury.io/rb/appbase)
2
5
 
3
6
  Nowadays BaaS and mBaaS platforms (e.g. [firebase](https://www.firebase.com/), [parse](https://www.parse.com/), [appbase.io](https://appbase.io/)) abound. Open source solutions (e.g. [usergrid](http://usergrid.incubator.apache.org/) using LAMP, [helios](http://helios.io/) using Ruby, [deployd](http://deployd.com/) and [StrongLoop](http://strongloop.com/) using nodejs, and a lot more) are also available. And appbase is much less than those.
4
7
 
@@ -154,7 +157,7 @@ Basic CRUD api conforms to the representational state transfer (REST) architectu
154
157
  Request to create a model with JSON serialized body:
155
158
 
156
159
  ```
157
- PUT /_api/note HTTP/1.1
160
+ POST /_api/note HTTP/1.1
158
161
  HOST xxx
159
162
  Content-Type: application/json
160
163
 
@@ -179,7 +182,7 @@ HTTP/1.1 200 OK
179
182
 
180
183
  #### Update
181
184
 
182
- Almost the same as create except for adding the `:id` parameter (e.g. `/_api/note/:id`):
185
+ Almost the same as create except for using `PUT` and adding the `:id` parameter (e.g. `/_api/note/:id`):
183
186
 
184
187
  ```
185
188
  PUT /_api/note/1 HTTP/1.1
@@ -254,4 +257,4 @@ You're welcome to contribute to this project by creating an issue / a pull reque
254
257
 
255
258
  ## License
256
259
 
257
- Appbase is released under the [MIT License](http://opensource.org/licenses/MIT).
260
+ Appbase is released under the [MIT License](http://opensource.org/licenses/MIT).
@@ -27,43 +27,42 @@ class AppBaseController < ActionController::Base
27
27
  -
28
28
  end
29
29
 
30
- def add_create_stub(model)
30
+ def permits(model, arg_str=false)
31
+ if arg_str
32
+ "[#{model.columns.map { |item| ":" + item.name }.join(", ")}]"
33
+ else
34
+ model.columns.map { |item| item.name.to_sym }
35
+ end
36
+ end
37
+
38
+ def add_create_or_update_stub(op, model, prepare)
31
39
  m = model.name
32
- permits = model.columns.map { |item| item.name }.to_json
33
40
  self.class_eval %-
34
- def create_#{AppBase.underscore m}
35
- obj = #{m}.new(params.except(:action, :controller, :id).permit(#{permits}))
36
- if !#{m}.allow_create?(current_user, obj)
37
- render json: { status: "error", msg: "unauthorized" }
38
- else
39
- obj.save!
40
- render json: { status: 'ok', id: obj.id }
41
- end
41
+ def #{op}_#{AppBase.underscore m}
42
+ #{prepare}
43
+ raise "unauthorized" if !#{m}.allow_#{op}?(current_user, obj)
44
+ obj.save!
45
+ rs = { status: 'ok' }
46
+ #{ 'rs[:id] = obj.id' if op == :create }
47
+ render json: rs
42
48
  rescue Exception => e
43
49
  render json: { status: 'error', msg: e.to_s }
44
50
  end
45
51
  -
46
52
  end
53
+ private :add_create_or_update_stub
54
+
55
+ def add_create_stub(model)
56
+ add_create_or_update_stub :create, model, %-
57
+ obj = #{model.name}.new(params.except(:action, :controller, :id).permit(#{permits(model, true)}))
58
+ -
59
+ end
47
60
 
48
61
  def add_update_stub(model)
49
- m = model.name
50
- permits = model.columns.map { |item| item.name }.to_json
51
- self.class_eval %-
52
- def update_#{AppBase.underscore m}
53
- obj = #{m}.find(params[:id])
54
- if obj.nil?
55
- return render json: { status: 'error', msg: 'not_found' }
56
- end
57
- obj.update_attributes(params.except(:action, :controller, :id).permit(#{permits}))
58
- if !#{m}.allow_update?(current_user, obj)
59
- render json: { status: "error", msg: "unauthorized" }
60
- else
61
- obj.save!
62
- render json: { status: 'ok' }
63
- end
64
- rescue Exception => e
65
- render json: { status: 'error', msg: e.to_s }
66
- end
62
+ add_create_or_update_stub :update, model, %-
63
+ obj = #{model.name}.find(params[:id])
64
+ raise 'not_found' if obj.nil?
65
+ obj.update_attributes(params.except(:action, :controller, :id).permit(#{permits(model, true)}))
67
66
  -
68
67
  end
69
68
 
@@ -89,7 +88,6 @@ class AppBaseController < ActionController::Base
89
88
 
90
89
  def add_query_stub(model)
91
90
  m = model.name
92
- columns = model.columns.map{|c|c.name}
93
91
  self.class_eval %-
94
92
  def query_#{AppBase.underscore m}
95
93
  query = #{m}.accessible_by(current_user)
@@ -141,36 +139,69 @@ class AppBaseController < ActionController::Base
141
139
  end
142
140
 
143
141
  def add_rpc_method_stub(bound_method, auth=false)
144
- m = bound_method.receiver.name
145
- mn = bound_method.name
146
- parameters = bound_method.parameters
147
- if auth && (parameters.count == 0 || parameters[0][0] != :req)
148
- raise "#{m}.#{mn} does not accept current user identity as the first parameter. Using `expose_to_appbase :method_name, auth: false` to expose #{m}.#{mn} to appbase without user authentication."
142
+ RpcMethodStubHelper.new(bound_method, auth).add_stub(self)
143
+ end
144
+
145
+ class RpcMethodStubHelper
146
+
147
+ def initialize(bound_method, auth=false)
148
+ @bound_method = bound_method
149
+ @auth = auth
150
+ @method_name = bound_method.name
151
+ @model_name = bound_method.receiver.name.to_s.extend(AppBase::StringExtension)
152
+ init
149
153
  end
150
- need_params = false
151
- if parameters.count > 0 && parameters.last[0] == :opt
152
- need_params = true
153
- parameters = parameters[(auth ? 1 : 0)..-2]
154
- else
155
- parameters = parameters[(auth ? 1 : 0)..-1]
154
+
155
+ def add_stub(controller)
156
+ controller.class_eval %-
157
+ def rpc_#{@model_name.underscore}_#{@method_name}
158
+ #{@requires.map{|p|"params.require #{p}"}.join(';')}
159
+ render json: { status: 'ok', data: #{@model_name}.#{@method_name}(#{@parameters.join(', ')}) }
160
+ rescue Exception => e
161
+ render json: { status: 'error', msg: e.to_s }
162
+ end
163
+ -
156
164
  end
157
- if parameters.find{|p|p[0]!=:req}
158
- raise "Error exposing #{m}.#{mn} to appbase engine, appbase does not support rest/optional parameters, use options instead!"
165
+
166
+ private
167
+ def init
168
+ init_parameters do |parameters, need_params|
169
+ @requires = parameters.map{|p|":#{p[1]}"}
170
+ @parameters = @auth ? ['current_user'] : []
171
+ @requires.each { |p| @parameters << "params[#{p}]" }
172
+ if need_params
173
+ @parameters.push "params.except(:action, :controller#{@requires.count > 0 ? ", #{@requires.join(', ')}" : ""})"
174
+ end
175
+ end
159
176
  end
160
- requires = parameters.map{|p|":#{p[1]}"}
161
- parameters = auth ? ['current_user'] : []
162
- requires.each { |p| parameters << "params[#{p}]" }
163
- if need_params
164
- parameters.push "params.except(:action, :controller#{requires.count > 0 ? ", #{requires.join(', ')}" : ""})"
177
+
178
+ def pre_init_parameters(parameters)
179
+ if @auth && (parameters.count == 0 || parameters[0][0] != :req)
180
+ raise "#{@model_name}.#{@method_name} does not accept current user identity as the first parameter. Using `expose_to_appbase :method_name, auth: false` to expose #{@model_name}.#{@method_name} to appbase without user authentication."
181
+ end
165
182
  end
166
- self.class_eval %-
167
- def rpc_#{AppBase.underscore m}_#{mn}
168
- #{requires.map{|p|"params.require #{p}"}.join(';')}
169
- render json: { status: 'ok', data: #{m}.#{mn}(#{parameters.join(', ')}) }
170
- rescue Exception => e
171
- render json: { status: 'error', msg: e.to_s }
183
+
184
+ def post_init_parameters(parameters)
185
+ if parameters.find{|p|p[0]!=:req}
186
+ raise "Error exposing #{@model_name}.#{@method_name} to appbase engine, appbase does not support rest/optional parameters, use options instead!"
172
187
  end
173
- -
188
+ end
189
+
190
+ def init_parameters
191
+ parameters = @bound_method.parameters
192
+ pre_init_parameters(parameters)
193
+
194
+ need_params = false
195
+ if parameters.count > 0 && parameters.last[0] == :opt
196
+ need_params = true
197
+ parameters = parameters[(@auth ? 1 : 0)..-2]
198
+ else
199
+ parameters = parameters[(@auth ? 1 : 0)..-1]
200
+ end
201
+
202
+ post_init_parameters(parameters)
203
+ yield parameters, need_params
204
+ end
174
205
  end
175
206
 
176
207
  end
@@ -3,6 +3,129 @@ require 'active_support'
3
3
  module AppBase
4
4
 
5
5
  module ModelConcern
6
+
7
+ class InvalidUsage < Exception
8
+ end
9
+
10
+ class ModelConcernHelper
11
+
12
+ private
13
+
14
+ def validate_crud(crud)
15
+ if [:create, :update, :delete, :query].index(crud).nil?
16
+ raise "Unsupported crud operation: #{crud}, available options: create, update, delete, query"
17
+ end
18
+ end
19
+
20
+ def model_inject(method_name=nil, &block)
21
+ AppBase::Engine.after_initialized do
22
+ user_identity_attr = "#{AppBase::Engine::UserIdentity.underscore}_id"
23
+ if method_name.nil?
24
+ method_body = block.call(user_identity_attr)
25
+ @model.class_eval method_body
26
+ else
27
+ @model.define_singleton_method method_name.to_sym, &block
28
+ end
29
+ end
30
+ end
31
+
32
+ def show_usage(crud)
33
+ raise %-
34
+ allow_#{crud} usage:
35
+ allow_#{crud} :mine
36
+ allow_#{crud} :#{ crud == :query ? 'within' : 'if' } => :a_singleton_method
37
+ allow_#{crud} :#{ crud == :query ? 'within' : 'if' } do |current_user_identity#{ crud == :query ? '' : ', model_instance' }|
38
+ # #{ crud == :query ? 'return fitlered query, e.g. Note.where(:user_id => current_user_identity.id)' : 'return true if allowed' }
39
+ end
40
+ -
41
+ end
42
+
43
+ def allow_mine(crud)
44
+ model_inject do |user_identity_attr|
45
+ crud == :query ? %-
46
+ def self.accessible_by(user)
47
+ #{@model.name}.where(:#{user_identity_attr} => user.id)
48
+ end
49
+ - : %-
50
+ def self.allow_#{crud}?(user, obj)
51
+ user.id == obj.#{user_identity_attr}
52
+ end
53
+ -
54
+ end
55
+ end
56
+
57
+ def allow_criteria_with_block(crud, block)
58
+ show_usage(crud) if crud == :query && block.parameters.count != 1
59
+ show_usage(crud) if crud != :query && block.parameters.count != 2
60
+ model_inject crud == :query ? :accessible_by : "allow_#{crud}", &block
61
+ end
62
+
63
+ def allow_criteria_with_method_alias(crud, method_name)
64
+ show_usage(crud) if method_name.nil? || !method_name.instance_of?(Symbol)
65
+ model_inject do |user_identity_attr|
66
+ crud == :query ? %-
67
+ def self.accessible_by(user)
68
+ #{@model.name}.#{method_name} user
69
+ end
70
+ - : %-
71
+ def self.allow_#{crud}?(user, obj)
72
+ #{@model.name}.#{method_name} user, obj
73
+ end
74
+ -
75
+ end
76
+ end
77
+
78
+ public
79
+
80
+ def crud_allow(crud, criteria=:mine, &block)
81
+ validate_crud crud
82
+
83
+ if criteria == :mine
84
+ allow_mine crud
85
+ else
86
+ key = crud == :query ? :within : :if
87
+ if criteria.instance_of? Hash
88
+ allow_criteria_with_method_alias(crud, criteria[key])
89
+ else
90
+ show_usage(crud) if criteria != key || !block_given?
91
+ allow_criteria_with_block(crud, block)
92
+ end
93
+ end
94
+ AppBase::Registry.register_crud @model, crud
95
+ end
96
+
97
+ def symbol_array_manipulate(op, source, options)
98
+ raise InvalidUsage if op != :only && op != :except
99
+ if options.has_key? op
100
+ operands = options[op]
101
+ operands = [operands] if operands.instance_of?(String) || operands.instance_of?(Symbol)
102
+ raise InvalidUsage unless operands.instance_of?(Array)
103
+ operands = operands.map {|c|c.to_sym}
104
+ source.send({ only: '&', except: "-" }[op], operands)
105
+ else
106
+ source
107
+ end
108
+ end
109
+
110
+ private
111
+ def initialize(model)
112
+ @model = model
113
+ end
114
+
115
+ class << self
116
+
117
+ def [](model)
118
+ raise "Invalid model" if model.class != Class
119
+ helpers[model] ||= ModelConcernHelper.new(model)
120
+ end
121
+
122
+ private
123
+ def helpers
124
+ @helpers ||= {}
125
+ end
126
+ end
127
+
128
+ end
6
129
 
7
130
  extend ActiveSupport::Concern
8
131
 
@@ -19,120 +142,42 @@ module AppBase
19
142
  end
20
143
  end
21
144
 
22
- def appbase_allow(crud, criteria=:mine, &block)
23
- if [:create, :update, :delete, :query].index(crud).nil?
24
- raise "Unsupported crud operation: #{crud}, available options: create, update, delete, query"
25
- end
26
- model = self
27
- if criteria == :mine
28
- # allow_xxx :mine or simply allow_xxx
29
- AppBase::Engine.after_initialized do
30
- user_identity_attr = "#{AppBase::Engine::UserIdentity.underscore}_id"
31
- model.class_eval crud == :query ? %-
32
- def self.accessible_by(user)
33
- #{model.name}.where(:#{user_identity_attr} => user.id)
34
- end
35
- - : %-
36
- def self.allow_#{crud}?(user, obj)
37
- user.id == obj.#{user_identity_attr}
38
- end
39
- -
40
- end
41
- elsif crud != :query && criteria == :if && block_given? && block.parameters.count == 2
42
- # allow_xxx :if do; end
43
- AppBase::Engine.after_initialized do
44
- user_identity_attr = "#{AppBase::Engine::UserIdentity.underscore}_id"
45
- model.define_singleton_method "allow_#{crud}".to_sym, &block
46
- end
47
- elsif crud == :query && criteria == :within && block_given? && block.parameters.count == 1
48
- # allow_query :within {|current_user| Model.where(...)}
49
- AppBase::Engine.after_initialized do
50
- user_identity_attr = "#{AppBase::Engine::UserIdentity.underscore}_id"
51
- model.define_singleton_method :accessible_by, &block
52
- end
53
- elsif crud != :query && riteria.instance_of?(Hash) && criteria.has_key?(:if) && criteria[:if].instance_of?(Symbol)
54
- # :if => :a_singleton_method
55
- AppBase::Engine.after_initialized do
56
- user_identity_attr = "#{AppBase::Engine::UserIdentity.underscore}_id"
57
- model.class_eval %-
58
- def self.allow_#{crud}?(user, obj)
59
- #{model.name}.#{criteria[:if]} user
60
- end
61
- -
62
- end
63
- elsif crud == :query && criteria.instance_of?(Hash) && criteria.has_key?(:within) && criteria[:within].instance_of?(Symbol)
64
- # allow_query :within => :a_singleton_query_method
65
- AppBase::Engine.after_initialized do
66
- user_identity_attr = "#{AppBase::Engine::UserIdentity.underscore}_id"
67
- model.class_eval %-
68
- def self.accessible_by(user)
69
- #{model.name}.#{criteria[:within]} user
70
- end
71
- -
72
- end
73
- else
74
- raise %-
75
- allow_#{crud} usage:
76
- allow_#{crud} :mine
77
- allow_#{crud} :#{ crud == :query ? 'within' : 'if' } => :a_singleton_method
78
- allow_#{crud} :#{ crud == :query ? 'within' : 'if' } do |current_user_identity#{ crud == :query ? '' : ', model_instance' }|
79
- # #{ crud == :query ? 'return fitlered query, e.g. Note.where(:user_id => current_user_identity.id)' : 'return true if allowed' }
80
- end
81
- -
82
- end
83
- AppBase::Registry.register_crud self, crud
84
- end
85
-
86
145
  def allow_create(criteria=:mine, &block)
87
- appbase_allow(:create, criteria, &block)
146
+ appbase_helper.crud_allow(:create, criteria, &block)
88
147
  end
89
148
 
90
149
  def allow_update(criteria=:mine, &block)
91
- appbase_allow(:update, criteria, &block)
150
+ appbase_helper.crud_allow(:update, criteria, &block)
92
151
  end
93
152
 
94
153
  def allow_delete(criteria=:mine, &block)
95
- appbase_allow(:delete, criteria, &block)
154
+ appbase_helper.crud_allow(:delete, criteria, &block)
96
155
  end
97
156
 
98
157
  def allow_query(criteria=:mine, &block)
99
- appbase_allow(:query, criteria, &block)
158
+ appbase_helper.crud_allow(:query, criteria, &block)
100
159
  end
101
160
 
102
161
  def restrict_query_columns(options={})
103
- show_usage = proc {
104
- raise %-
105
- restrict_query_columns usage:
106
- restrict_query_columns <only | except>: <single_column | column_list>
107
- examples:
108
- restrict_query_columns only: [:user_id, :created_at, :updated_at]
109
- restrict_query_columns only: :updated_at
110
- restrict_query_columns except: [:content]
111
- -
112
- }
113
- show_usage.call if !options || !options.instance_of?(Hash)
162
+ raise InvalidUsage if !options || !options.instance_of?(Hash)
114
163
  columns = self.columns.map{|c|c.name.to_sym}
115
- # on columns
116
- if options.has_key? :only
117
- on_columns = options[:only]
118
- on_columns = [on_columns] if on_columns.instance_of?(String) || on_columns.instance_of?(Symbol)
119
- show_usage.call unless on_columns.instance_of?(Array)
120
- on_columns = on_columns.map {|c|c.to_sym}
121
- columns &= on_columns
122
- end
123
- # except columns
124
- if options.has_key? :except
125
- except_columns = options[:except]
126
- except_columns = [except_columns] if except_columns.instance_of?(String) || except_columns.instance_of?(Symbol)
127
- show_usage.call unless except_columns.instance_of?(Array)
128
- except_columns = except_columns.map {|c|c.to_sym}
129
- columns -= except_columns
130
- end
164
+
165
+ columns = appbase_helper.symbol_array_manipulate :only, columns, options
166
+ columns = appbase_helper.symbol_array_manipulate :except, columns, options
131
167
 
132
168
  self.define_singleton_method :appbase_queryable_columns do
133
169
  columns
134
170
  end
135
171
 
172
+ rescue InvalidUsage
173
+ raise %-
174
+ restrict_query_columns usage:
175
+ restrict_query_columns <only | except>: <single_column | column_list>
176
+ examples:
177
+ restrict_query_columns only: [:user_id, :created_at, :updated_at]
178
+ restrict_query_columns only: :updated_at
179
+ restrict_query_columns except: [:content]
180
+ -
136
181
  end
137
182
 
138
183
  def appbase_queryable_operators
@@ -140,38 +185,13 @@ module AppBase
140
185
  end
141
186
 
142
187
  def restrict_query_operators(*columns)
143
- show_usage = proc {
144
- raise %-
145
- restrict_query_operators usage:
146
- restrict_query_operators :column1, :column2, <only | except>: <:equal | :compare | :in>
147
- examples:
148
- restrict_query_operators :user_id, :created_at, :updated_at, only: [:equal, :compare]
149
- restrict_query_operators :user_id, :created_at, :updated_at, except: :in
150
- restrict_query_operators :title, only: :equal
151
- -
152
- }
153
- show_usage.call if columns.count < 2 || !columns.last.instance_of?(Hash)
188
+ check_before_restrict_query_operators columns
154
189
  *columns, options = columns
155
- show_usage.call unless options.has_key?(:only) || options.has_key?(:except)
156
190
  operators = appbase_queryable_operators
157
191
 
158
192
  set = [:equal, :compare, :in]
159
- # on columns
160
- if options.has_key? :only
161
- allows = options[:only]
162
- allows = [allows] if allows.instance_of?(String) || allows.instance_of?(Symbol)
163
- show_usage.call unless allows.instance_of?(Array)
164
- allows = allows.map {|c|c.to_sym}
165
- set &= allows
166
- end
167
- # except columns
168
- if options.has_key? :except
169
- excepts = options[:except]
170
- excepts = [excepts] if excepts.instance_of?(String) || excepts.instance_of?(Symbol)
171
- show_usage.call unless excepts.instance_of?(Array)
172
- excepts = excepts.map {|c|c.to_sym}
173
- set -= excepts
174
- end
193
+ set = appbase_helper.symbol_array_manipulate :only, set, options
194
+ set = appbase_helper.symbol_array_manipulate :except, set, options
175
195
 
176
196
  columns.each do |c|
177
197
  operators[c.to_sym] = set
@@ -180,10 +200,28 @@ module AppBase
180
200
  self.define_singleton_method :appbase_queryable_operators do
181
201
  operators
182
202
  end
183
-
203
+ rescue InvalidUsage
204
+ raise %-
205
+ restrict_query_operators usage:
206
+ restrict_query_operators :column1, :column2, <only | except>: <:equal | :compare | :in>
207
+ examples:
208
+ restrict_query_operators :user_id, :created_at, :updated_at, only: [:equal, :compare]
209
+ restrict_query_operators :user_id, :created_at, :updated_at, except: :in
210
+ restrict_query_operators :title, only: :equal
211
+ -
184
212
  end
185
213
 
214
+ private
215
+
216
+ def check_before_restrict_query_operators(columns)
217
+ raise InvalidUsage if columns.count < 2 || !columns.last.instance_of?(Hash)
218
+ options = columns.last
219
+ raise InvalidUsage unless options.has_key?(:only) || options.has_key?(:except)
220
+ end
186
221
 
222
+ def appbase_helper
223
+ ModelConcernHelper[self]
224
+ end
187
225
  end
188
226
 
189
227
  end
@@ -11,90 +11,156 @@ module AppBase
11
11
 
12
12
  class << self
13
13
 
14
- initialized = false
15
- config = nil
16
- hooks = []
14
+ class RpcMethodInitializer
15
+
16
+ def initialize(config)
17
+ @model = config[:model]
18
+ @method = config[:method]
19
+ @auth = config[:auth]
20
+ end
21
+
22
+ def init
23
+ pre_init
24
+ add_controller_stub
25
+ add_route
26
+ end
27
+
28
+ private
29
+ def pre_init
30
+ model_name = @model.name
31
+ if !@model.respond_to?(@method)
32
+ raise "#{model_name} does not respond to #{@method}."
33
+ end
34
+ end
35
+
36
+ def add_controller_stub
37
+ bound_method = @model.method @method
38
+ AppBaseController.add_rpc_method_stub(bound_method, @auth)
39
+ end
40
+
41
+ def add_route
42
+ model_name_underscore = AppBase.underscore @model.name
43
+ method_name = @method
44
+ AppBase::Engine.routes.append do
45
+ post "/#{model_name_underscore}/#{method_name}" => "app_base#rpc_#{model_name_underscore}_#{method_name}"
46
+ end
47
+ end
48
+ end
49
+
50
+ class CrudInitializer
51
+
52
+ def initialize(model, op)
53
+ @model = model
54
+ @op = op
55
+ @http_methods = { create: :post, update: :put, delete: :delete, query: :get }
56
+ end
57
+
58
+ def init
59
+ pre_init
60
+ add_controller_stub
61
+ add_route
62
+ end
63
+
64
+ private
65
+ def pre_init
66
+ raise "Unexpected crud operation: #{@op}" if !@http_methods.has_key?(@op)
67
+ end
68
+
69
+ def add_controller_stub
70
+ AppBaseController.send "add_#{@op}_stub".to_sym, @model
71
+ end
72
+
73
+ def add_route
74
+ model_name_underscore = AppBase.underscore @model.name
75
+ url_path = "/#{model_name_underscore}"
76
+ url_path += "/:id" if @op == :update || @op == :delete
77
+ http_method = @http_methods[@op]
78
+ op = @op
79
+ AppBase::Engine.routes.append do
80
+ match url_path, to: "app_base##{op}_#{model_name_underscore}", via: http_method
81
+ end
82
+ end
83
+
84
+ end
17
85
 
18
- define_method :bootstrap do |app_config|
19
- return if initialized
20
- config = app_config.appbase
21
-
22
- # initialize user identity
23
- if config.user_identity.nil?
24
- raise "AppBase configuration error: please use `config.appbase.user_identity = :UserIdentity` to specify the user identity model; and implement UserIdentity.authenticate_by_token(user, token):UserIdentity method."
25
- end
26
- user_identity = Object.const_get config.user_identity.to_sym
27
- if !user_identity.respond_to?(:authenticate_by_token) || user_identity.method(:authenticate_by_token).parameters.count != 2
28
- raise "It's required to implement UserIdentity.authenticate_by_token(user, token):UserIdentity method."
29
- end
30
- AppBase::Engine::UserIdentity = config.user_identity.to_s.extend AppBase::StringExtension
31
- AppBaseController.define_useridentity config.user_identity, config.token_store, config.token_key_user, config.token_key_session
32
-
33
- # initialize crud stubs
34
- AppBase::Registry.each_crud config.models do |model, op|
35
- model_name_underscore = AppBase.underscore model.name
36
- case op
37
- when :create
38
- AppBaseController.add_create_stub(model)
39
- AppBase::Engine.routes.append do
40
- put "/#{model_name_underscore}" => "app_base#create_#{model_name_underscore}"
41
- end
42
- when :update
43
- AppBaseController.add_update_stub(model)
44
- AppBase::Engine.routes.append do
45
- put "/#{model_name_underscore}/:id" => "app_base#update_#{model_name_underscore}"
46
- end
47
- when :delete
48
- AppBaseController.add_delete_stub(model)
49
- AppBase::Engine.routes.append do
50
- delete "/#{model_name_underscore}/:id" => "app_base#delete_#{model_name_underscore}"
51
- end
52
- when :query
53
- AppBaseController.add_query_stub(model)
54
- AppBase::Engine.routes.append do
55
- get "/#{model_name_underscore}" => "app_base#query_#{model_name_underscore}"
56
- end
86
+ class AppBaseEngineInitializer
87
+
88
+ def initialize
89
+ @initialized = false
90
+ @hooks = []
91
+ end
92
+
93
+ def bootstrap(app_config)
94
+ return if @initialized
95
+ @config = app_config.appbase
96
+ initialize_user_identity
97
+ initialize_crud_stubs
98
+ initialize_rpc_stubs
99
+ finilize_routes
100
+ post_initialize
101
+ @initialized = true
102
+ end
103
+
104
+ def after_initialized(&block)
105
+ if @initialized
106
+ block.call
57
107
  else
58
- raise "Unexpected crud operation: #{op}"
108
+ @hooks << block
59
109
  end
60
110
  end
61
111
 
62
- # initialize rpc stubs
63
- AppBase::Registry.each_rpc do |r|
64
- if !r[:model].respond_to? r[:method]
65
- raise "#{r[:model].name} does not respond to #{r[:method]}."
112
+ private
113
+
114
+ def pre_init_user_identity
115
+ if @config.user_identity.nil?
116
+ raise "AppBase configuration error: please use `config.appbase.user_identity = :UserIdentity` to specify the user identity model; and implement UserIdentity.authenticate_by_token(user, token):UserIdentity method."
66
117
  end
67
- bound_method = r[:model].method r[:method]
68
- AppBaseController.add_rpc_method_stub(bound_method, r[:auth])
69
- AppBase::Engine.routes.append do
70
- post "/#{AppBase.underscore r[:model].name}/#{r[:method]}" => "app_base#rpc_#{AppBase.underscore r[:model].name}_#{r[:method]}"
118
+ user_identity = Object.const_get @config.user_identity.to_sym
119
+ if !user_identity.respond_to?(:authenticate_by_token) || user_identity.method(:authenticate_by_token).parameters.count != 2
120
+ raise "It's required to implement UserIdentity.authenticate_by_token(user, token):UserIdentity method."
71
121
  end
72
122
  end
73
123
 
74
- # finalize appbase routes
75
- AppBase::Engine.routes.draw do
76
- get "/appbase_version" => "app_base#version"
124
+ def initialize_user_identity
125
+ pre_init_user_identity
126
+ AppBase::Engine.const_set :UserIdentity, @config.user_identity.to_s.extend(AppBase::StringExtension)
127
+ AppBaseController.define_useridentity @config.user_identity, @config.token_store, @config.token_key_user, @config.token_key_session
77
128
  end
78
129
 
79
- # after initialized
80
- blocks, hooks = hooks, []
81
- blocks.each do |block|
82
- block.call
130
+ def initialize_crud_stubs
131
+ AppBase::Registry.each_crud @config.models do |model, op|
132
+ CrudInitializer.new(model, op).init
133
+ end
83
134
  end
84
- initialized = true
85
135
 
136
+ def initialize_rpc_stubs
137
+ AppBase::Registry.each_rpc do |r|
138
+ RpcMethodInitializer.new(r).init
139
+ end
140
+ end
141
+
142
+ def finilize_routes
143
+ AppBase::Engine.routes.draw do
144
+ get "/appbase_version" => "app_base#version"
145
+ end
146
+ end
147
+
148
+ def post_initialize
149
+ blocks, @hooks = @hooks, []
150
+ blocks.each do |block|
151
+ block.call
152
+ end
153
+ end
86
154
  end
87
155
 
88
- define_method :after_initialized do |&block|
89
- if initialized
90
- block.call
91
- else
92
- hooks << block
93
- end
156
+ def bootstrap(config)
157
+ @initializer = AppBaseEngineInitializer.new if !@initializer
158
+ @initializer.bootstrap(config)
94
159
  end
95
160
 
96
- define_method :config do
97
- config
161
+ def after_initialized(&block)
162
+ @initializer = AppBaseEngineInitializer.new if !@initializer
163
+ @initializer.after_initialized(&block)
98
164
  end
99
165
 
100
166
  end
@@ -102,26 +168,35 @@ module AppBase
102
168
  end
103
169
 
104
170
  class Railtie < Rails::Railtie
105
-
106
- # default values for appbase configuration
107
- config.appbase = ActiveSupport::OrderedOptions.new
108
- config.appbase.enabled = false
109
- config.appbase.mount = "/appbase"
110
- config.appbase.user_identity = nil
111
- config.appbase.token_store = :cookies # :cookies, :headers, :params
112
- config.appbase.token_key_user = :u
113
- config.appbase.token_key_session = :s
114
- config.appbase.models = []
115
171
 
116
- initializer "appbase.configure_route", :after => :add_routing_paths do |app|
117
-
172
+ class << self
173
+ private
174
+ def setup_default(config)
175
+ return if config.respond_to? :appbase
176
+ # default values for appbase configuration
177
+ config.appbase = ActiveSupport::OrderedOptions.new
178
+ config.appbase.enabled = false
179
+ config.appbase.mount = "/appbase"
180
+ config.appbase.user_identity = nil
181
+ config.appbase.token_store = :cookies # :cookies, :headers, :params
182
+ config.appbase.token_key_user = :u
183
+ config.appbase.token_key_session = :s
184
+ config.appbase.models = []
185
+ end
186
+ end
187
+
188
+ def enabled
118
189
  if File.basename(ENV['_']) == 'rake'
119
190
  puts "Running with `rake #{$*.join(' ')}`"
120
191
  end
121
-
122
- if config.appbase.enabled && (File.basename(ENV['_']) != 'rake' || $*[0] == 'routes')
192
+ config.appbase.enabled && (File.basename(ENV['_']) != 'rake' || $*[0] == 'routes')
193
+ end
194
+
195
+ setup_default config
196
+
197
+ initializer "appbase.configure_route", :after => :add_routing_paths do |app|
198
+ if enabled
123
199
  AppBase::Engine.bootstrap app.config
124
-
125
200
  app.routes.append do
126
201
  mount AppBase::Engine => Rails.application.config.appbase.mount
127
202
  end
@@ -23,36 +23,64 @@ module AppBase
23
23
  # used once upon rails startup, cannot be reloaded by spring.
24
24
  class << Registry
25
25
 
26
- rpc_methods = []
27
- crud_permissions = []
28
-
29
- define_method :register_rpc do |model, method_name, options={}|
30
- model = Object.const_get(model.to_sym) if model.instance_of?(String) || model.instance_of?(Symbol)
31
- method_name = method_name.to_sym
32
- auth = options.has_key?(:auth) ? options[:auth] : true
33
- if rpc_methods.find{ |r| r[:model] == model && r[:method] == method_name }.nil?
34
- rpc_methods << { model: model, method: method_name, auth: auth }
35
- else
36
- raise "#{model}.#{method_name} has already been registered"
26
+ class RegistryTable
27
+
28
+ def initialize
29
+ @rpc_methods = []
30
+ @crud_permissions = []
31
+ end
32
+
33
+ def contains_rpc_registry(item)
34
+ !@rpc_methods.find{ |r| r[:model] == item[:model] && r[:method] == item[:method] }.nil?
35
+ end
36
+
37
+ def register_rpc(model, method_name, options={})
38
+ rpc_registry_item = {
39
+ model: (model.instance_of?(String) || model.instance_of?(Symbol)) ? Object.const_get(model.to_sym) : model,
40
+ method: method_name.to_sym,
41
+ auth: options.has_key?(:auth) ? options[:auth] : true
42
+ }
43
+ raise "#{model}.#{method_name} has already been registered" if contains_rpc_registry(rpc_registry_item)
44
+ @rpc_methods << rpc_registry_item
45
+ end
46
+
47
+ def register_crud(model, crud)
48
+ if @crud_permissions.find{ |r| r[:model] == model && r[:crud] == crud }.nil?
49
+ @crud_permissions << { model: model, crud: crud }
50
+ end
51
+ end
52
+
53
+ def each_rpc(&block)
54
+ @rpc_methods.each(&block)
55
+ end
56
+
57
+ def each_crud(*models, &block)
58
+ models = models.flatten.map { |model| (model.instance_of?(Symbol) || model.instance_of?(String)) ? Object.const_get(model) : model }
59
+ @crud_permissions.each do |r|
60
+ block.call r[:model], r[:crud] if models.index(r[:model])
61
+ end
37
62
  end
38
63
  end
39
64
 
40
- define_method :each_rpc do |&block|
41
- rpc_methods.each &block
65
+ def register_rpc(model, method_name, options={})
66
+ instance.register_rpc(model, method_name, options)
42
67
  end
43
68
 
44
- define_method :register_crud do |model, crud|
45
- if crud_permissions.find{ |r| r[:model] == model && r[:crud] == crud }.nil?
46
- crud_permissions << { model: model, crud: crud }
47
- end
69
+ def register_crud(model, crud)
70
+ instance.register_crud(model, crud)
48
71
  end
49
72
 
50
- define_method :each_crud do |*models, &block|
51
- models = models[0] if models.count == 1 && models.instance_of?(Array)
52
- models = models.map { |model| (model.instance_of?(Symbol) || model.instance_of?(String)) ? Object.const_get(model) : model }
53
- crud_permissions.each do |r|
54
- block.call r[:model], r[:crud] if models.index(r[:model])
55
- end
73
+ def each_rpc(&block)
74
+ instance.each_rpc(&block)
75
+ end
76
+
77
+ def each_crud(*models, &block)
78
+ instance.each_crud(*models, &block)
79
+ end
80
+
81
+ private
82
+ def instance
83
+ @instance ||= RegistryTable.new
56
84
  end
57
85
 
58
86
  end
@@ -1,3 +1,3 @@
1
1
  module AppBase
2
- VERSION = '0.0.2'
2
+ VERSION = '0.0.3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appbase
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - bestmike007
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-19 00:00:00.000000000 Z
11
+ date: 2014-12-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails