appbase 0.0.2 → 0.0.3

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