smooth 2.0.1 → 2.0.2
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 +4 -4
- data/.gitignore +7 -0
- data/Gemfile +1 -2
- data/README.md +150 -5
- data/Rakefile +16 -0
- data/app/assets/javascripts/smooth/index.js +5152 -0
- data/bin/smooth +9 -0
- data/{app/assets/javascripts/smooth → developer-tools}/.keep +0 -0
- data/developer-tools/bower.json +8 -0
- data/developer-tools/config.ru +3 -0
- data/developer-tools/dist/08d606864d3ad3f0b98660d391f5a1c2.gif +0 -0
- data/developer-tools/dist/2d66bcdc27cd89f71068e98a7a929712.gif +0 -0
- data/developer-tools/dist/3e9816417b11485d454f9b3662b06e7b.eot +0 -0
- data/developer-tools/dist/47de617fd1d745ad120ccb9e2924b98c.gif +0 -0
- data/developer-tools/dist/5ae23ad29b67289a1375d2043e289c52.eot +0 -0
- data/developer-tools/dist/60c2a8500e63bf211b7df9608f7613ea.svg +450 -0
- data/developer-tools/dist/645f50ba6c1e56f078fa018855d97eb0.gif +0 -0
- data/developer-tools/dist/71ab514d1cedda303417ad7a06472fea.ttf +0 -0
- data/developer-tools/dist/8cca2f02b0af2da365ff4d1755f29146.ttf +0 -0
- data/developer-tools/dist/939cf252f0eb4efbd2d170c974411c49.gif +0 -0
- data/developer-tools/dist/9af25aaeb6ca6d08d213b04841813eb5.gif +0 -0
- data/developer-tools/dist/b683029bafe0305ac2234038a03e1541.woff +0 -0
- data/developer-tools/dist/c9dec22105ad9330c811599b8b6464f8.woff +0 -0
- data/developer-tools/dist/ca279c55a51ab2641c4712a333633581.gif +0 -0
- data/developer-tools/dist/client.js +5152 -0
- data/developer-tools/dist/f5b27137d3f5e9b1d91b16b37386dd03.gif +0 -0
- data/developer-tools/dist/f99a231ed57ee113b50b1c3e9f9fcdc3.svg +399 -0
- data/developer-tools/dist/index.html +18 -0
- data/developer-tools/dist/inspector.js +38432 -0
- data/developer-tools/dist/jquery.min.js +9190 -0
- data/developer-tools/package.json +39 -0
- data/developer-tools/server.js +14 -0
- data/developer-tools/src/client.coffee +21 -0
- data/developer-tools/src/client/collection.coffee +14 -0
- data/developer-tools/src/client/model.coffee +11 -0
- data/developer-tools/src/client/resource.coffee +132 -0
- data/{app/controllers/.keep → developer-tools/src/client/runner.coffee} +0 -0
- data/developer-tools/src/dependencies.coffee +7 -0
- data/developer-tools/src/inspector.cjsx +49 -0
- data/developer-tools/src/inspector/models/interface_collection.coffee +31 -0
- data/developer-tools/src/inspector/pages/index.cjsx +31 -0
- data/developer-tools/src/inspector/pages/resources.cjsx +5 -0
- data/developer-tools/src/inspector/views/grid_sort.cjsx +23 -0
- data/developer-tools/src/inspector/views/icon_heading.cjsx +15 -0
- data/developer-tools/src/inspector/views/resource_card.cjsx +34 -0
- data/developer-tools/src/inspector/views/sidebar.cjsx +12 -0
- data/developer-tools/src/inspector/views/toolbar.cjsx +17 -0
- data/developer-tools/src/styles/index.scss +136 -0
- data/developer-tools/src/styles/views.scss +13 -0
- data/developer-tools/src/util.coffee +48 -0
- data/developer-tools/webpack.config.js +56 -0
- data/developer-tools/webpack.hot.config.js +65 -0
- data/lib/smooth.rb +209 -28
- data/lib/smooth/active_record/adapter.rb +24 -0
- data/lib/smooth/api.rb +272 -18
- data/lib/smooth/api/policy.rb +2 -2
- data/lib/smooth/api/tracking.rb +4 -4
- data/lib/smooth/application.rb +66 -0
- data/lib/smooth/cache.rb +1 -1
- data/lib/smooth/command.rb +267 -18
- data/lib/smooth/command/async_worker.rb +27 -0
- data/lib/smooth/command/instrumented.rb +6 -4
- data/lib/smooth/command/run_proxy.rb +21 -0
- data/lib/smooth/configuration.rb +63 -8
- data/lib/smooth/documentation.rb +3 -6
- data/lib/smooth/dsl.rb +1 -36
- data/lib/smooth/dsl_adapter.rb +34 -0
- data/lib/smooth/event.rb +8 -4
- data/lib/smooth/event/proxy.rb +9 -0
- data/lib/smooth/event/relay.rb +38 -0
- data/lib/smooth/example.rb +1 -1
- data/lib/smooth/ext/core.rb +16 -0
- data/lib/smooth/model_adapter.rb +31 -0
- data/lib/smooth/query.rb +143 -13
- data/lib/smooth/resource.rb +227 -52
- data/lib/smooth/resource/router.rb +217 -0
- data/lib/smooth/resource/templating.rb +62 -0
- data/lib/smooth/resource/tracking.rb +1 -1
- data/lib/smooth/response.rb +73 -0
- data/lib/smooth/serializer.rb +102 -11
- data/lib/smooth/user_adapter.rb +83 -0
- data/lib/smooth/util.rb +17 -0
- data/lib/smooth/version.rb +1 -1
- data/smooth.gemspec +6 -2
- data/spec/acceptance/books_routes_spec.rb +50 -0
- data/spec/acceptance/embedded_relationships_spec.rb +26 -0
- data/spec/dummy/app/apis/application_api.rb +8 -3
- data/spec/dummy/app/commands/create_book.rb +5 -0
- data/spec/dummy/app/models/book.rb +1 -0
- data/spec/dummy/app/models/library.rb +2 -0
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/app/queries/book_query.rb +13 -0
- data/spec/dummy/app/resources/{books.rb → books_definition.rb} +37 -12
- data/spec/dummy/db/migrate/20140824215902_create_users.rb +10 -0
- data/spec/dummy/db/migrate/20140826193259_create_libraries.rb +10 -0
- data/spec/dummy/db/schema.rb +8 -1
- data/spec/lib/smooth/api/async_spec.rb +21 -0
- data/spec/lib/smooth/api_spec.rb +8 -0
- data/spec/lib/smooth/command_spec.rb +87 -6
- data/spec/lib/smooth/configuration_spec.rb +4 -0
- data/spec/lib/smooth/event/relay_spec.rb +33 -0
- data/spec/lib/smooth/event_spec.rb +5 -8
- data/spec/lib/smooth/query_spec.rb +42 -0
- data/spec/lib/smooth/resource/router_spec.rb +14 -0
- data/spec/lib/smooth/resource_spec.rb +33 -1
- data/spec/lib/smooth/serializer_spec.rb +20 -0
- data/spec/lib/smooth/templating_spec.rb +23 -0
- data/spec/lib/smooth/util_spec.rb +22 -0
- data/spec/spec_helper.rb +1 -1
- metadata +151 -17
- data/app/helpers/.keep +0 -0
- data/app/mailers/.keep +0 -0
- data/app/models/.keep +0 -0
- data/app/views/.keep +0 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Smooth
|
|
2
|
+
module AR
|
|
3
|
+
class Adapter
|
|
4
|
+
class << self
|
|
5
|
+
def configure
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def in_use?
|
|
9
|
+
connection.in_use?
|
|
10
|
+
rescue ActiveRecord::ConnectionNotEstablished
|
|
11
|
+
false
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def connection
|
|
15
|
+
ActiveRecord::Base.connection
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def establish_connection
|
|
19
|
+
@connection = ActiveRecord::Base.establish_connection(Smooth.config.active_record)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/smooth/api.rb
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# The Smooth API
|
|
2
|
+
#
|
|
3
|
+
# An API is a collection of resources. A Resource is a collection of data models, and the API
|
|
4
|
+
# allows us to run queries against those data models or to run commands that express an intent
|
|
5
|
+
# to mutate the data models.
|
|
6
|
+
#
|
|
7
|
+
# An API provides different methods of authentication, and different policies for authorizations.
|
|
8
|
+
#
|
|
9
|
+
# An API is very easy to put a rest interface in front of, but can also work in other scenarios
|
|
10
|
+
# that speak JSON since the interface pretty well encapsulates the behavior.
|
|
3
11
|
module Smooth
|
|
4
12
|
class Api
|
|
13
|
+
# Being able to inspect an API and produce data suitable for generating interface
|
|
14
|
+
# documentation, and automated tests, among other things, is a key feature of the gem.
|
|
5
15
|
include Smooth::Documentation
|
|
6
16
|
|
|
7
17
|
def self.default
|
|
8
|
-
@default ||= Smooth::Api.new
|
|
18
|
+
@default ||= Smooth::Api.new(:default)
|
|
9
19
|
end
|
|
10
20
|
|
|
11
21
|
attr_accessor :name,
|
|
@@ -13,20 +23,231 @@ module Smooth
|
|
|
13
23
|
:_resources,
|
|
14
24
|
:_policies
|
|
15
25
|
|
|
16
|
-
def initialize(name, options={})
|
|
17
|
-
@name = name
|
|
26
|
+
def initialize(name, options = {})
|
|
27
|
+
@name = name.to_s
|
|
18
28
|
@options = options
|
|
19
29
|
|
|
20
30
|
@_resources = {}
|
|
21
31
|
@_policies = {}
|
|
22
32
|
end
|
|
23
33
|
|
|
24
|
-
|
|
34
|
+
# The Smooth API is a gateway for the commands and queries
|
|
35
|
+
# that can be run by users against its resources
|
|
36
|
+
def lookup(path)
|
|
37
|
+
lookup_object_by(path)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# The Smooth API Provides a Rack Compatible interface
|
|
41
|
+
# so we can mount in sinatra or rails or whatever
|
|
42
|
+
def call(env)
|
|
43
|
+
sinatra.call(env)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# All Actions taken against the Smooth API are run 'as'
|
|
47
|
+
# some current user. Example:
|
|
48
|
+
#
|
|
49
|
+
# Running a command:
|
|
50
|
+
#
|
|
51
|
+
# api.as(jonathan).i_would_like_to
|
|
52
|
+
# .run_command("books.create").with(title:'Sup boo')
|
|
53
|
+
#
|
|
54
|
+
# Running a query
|
|
55
|
+
#
|
|
56
|
+
# api.as(soederpop).i_would_like_to
|
|
57
|
+
# .query("books").with(subject:"how to...")
|
|
58
|
+
#
|
|
59
|
+
def as(current_user, &block)
|
|
60
|
+
proxy = DslProxy.new(current_user, self)
|
|
61
|
+
proxy.instance_eval(&block) if block_given?
|
|
62
|
+
proxy
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# The Smooth API generates a sinatra app to be able to
|
|
66
|
+
# the various resources and run commands, queries, etc.
|
|
67
|
+
def sinatra
|
|
68
|
+
app = @sinatra_application_klass ||= Class.new(Sinatra::Base)
|
|
69
|
+
|
|
70
|
+
@sinatra ||= begin
|
|
71
|
+
_resources.each do |_name, resource|
|
|
72
|
+
resource.router && resource.router.apply_to(app)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
expose_interface_documentation_via(app)
|
|
76
|
+
|
|
77
|
+
app
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def inspect
|
|
82
|
+
"Smooth API: #{ name } Resources: #{ resource_names }"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# The API will rely on the configured authentication method
|
|
86
|
+
# to determine who the user is. Given some request params
|
|
87
|
+
# and request headers
|
|
88
|
+
def lookup_current_user(params, headers)
|
|
89
|
+
auth_strategy, key = authentication_strategy
|
|
90
|
+
|
|
91
|
+
case
|
|
92
|
+
when auth_strategy == :param && parts = params[key]
|
|
93
|
+
user_class.find_for_token_authentication(parts)
|
|
94
|
+
when auth_strategy == :header && parts = headers[key]
|
|
95
|
+
user_class.find_for_token_authentication(parts)
|
|
96
|
+
else
|
|
97
|
+
user_class.anonymous(params, headers)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# The Policy will provide an ability file that we can
|
|
102
|
+
# run a user though. The Policy can be overridden by the
|
|
103
|
+
# resource, too. A policy will pass an object path
|
|
104
|
+
def lookup_policy(_params, _headers)
|
|
105
|
+
{}.to_mash
|
|
106
|
+
# TODO
|
|
107
|
+
#
|
|
108
|
+
# Implement:
|
|
109
|
+
#
|
|
110
|
+
# I think Smooth replaces too much of cancan to rely on it.
|
|
111
|
+
#
|
|
112
|
+
# I think the model where the resource inherits from the api, and
|
|
113
|
+
# the api policy just white lists or black lists commands for given
|
|
114
|
+
# user roles, will be sufficient
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# The Smooth API provides an Asynchronous interface.
|
|
118
|
+
def perform_async(object_path, payload = {})
|
|
119
|
+
worker.perform_async serialize_for_async(object_path, payload)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Takes a request to do something and serializes the arguments in
|
|
123
|
+
# the memory store. The request will be dispatched to the background job
|
|
124
|
+
# handler and then resumed with the same arguments.
|
|
125
|
+
#
|
|
126
|
+
# Note: Rails Global ID will be a good replacement for this
|
|
127
|
+
def serialize_for_async(object_path, payload)
|
|
128
|
+
key = "#{ name }".parameterize + ":cmd:#{ String.random_token(16) }"
|
|
129
|
+
|
|
130
|
+
request = {
|
|
131
|
+
api: name,
|
|
132
|
+
object_path: object_path,
|
|
133
|
+
payload: payload
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
Smooth.config.memory_store.write(key, request)
|
|
137
|
+
|
|
138
|
+
key
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Look up object by path. Used to route requests to
|
|
142
|
+
# commands or queries.
|
|
143
|
+
#
|
|
144
|
+
# Example:
|
|
145
|
+
#
|
|
146
|
+
# lookup('books.create') #=> CreateBook
|
|
147
|
+
def lookup_object_by(path)
|
|
148
|
+
path = path.to_s
|
|
149
|
+
resource_name, object_name = path.split(Smooth.config.object_path_separator)
|
|
150
|
+
|
|
151
|
+
resource_object = resource(resource_name)
|
|
152
|
+
|
|
153
|
+
case
|
|
154
|
+
when object_name == 'query' || object_name == 'serializer'
|
|
155
|
+
resource_object.fetch(object_name.to_sym, :default)
|
|
156
|
+
when object_name.nil?
|
|
157
|
+
resource_object
|
|
158
|
+
else
|
|
159
|
+
resource_object.fetch(:command, object_name)
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def resource_keys
|
|
164
|
+
_resources.keys
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def resource_names
|
|
168
|
+
_resources.values.map(&:resource_name).compact
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def resource_group_names
|
|
172
|
+
_resources.values.map(&:group_description).compact
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def documentation_base
|
|
176
|
+
{
|
|
177
|
+
api_meta: {
|
|
178
|
+
resource_names: resource_names,
|
|
179
|
+
resource_groups: resource_group_names
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def interface_documentation
|
|
185
|
+
resource_keys.reduce(documentation_base) do |memo, key|
|
|
186
|
+
memo.tap do
|
|
187
|
+
if resource = resource(key)
|
|
188
|
+
memo[resource.resource_name || key.to_s] = resource.interface_documentation
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def expose_interface_documentation_via(sinatra)
|
|
195
|
+
api = self
|
|
196
|
+
|
|
197
|
+
sinatra.send :get, '/interface' do
|
|
198
|
+
api.interface_documentation.to_json
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
sinatra.send :get, '/interface/:resource_name' do
|
|
202
|
+
docs = api.interface_documentation[params[:resource_name]]
|
|
203
|
+
docs.to_json
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def version(config = nil)
|
|
25
208
|
@_version_config = config if config
|
|
26
209
|
@_version_config
|
|
27
210
|
end
|
|
28
211
|
|
|
29
|
-
def
|
|
212
|
+
def user_class(user_klass = nil, &block)
|
|
213
|
+
@user_class = user_klass if user_klass.present?
|
|
214
|
+
@user_class || User
|
|
215
|
+
@user_class.class_eval(&block) if block_given?
|
|
216
|
+
@user_class
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def authentication_strategy(option = nil, key = nil)
|
|
220
|
+
return @authentication_strategy || [:header, 'X-AUTH-TOKEN'] if option.nil?
|
|
221
|
+
|
|
222
|
+
unless option.nil?
|
|
223
|
+
key = case
|
|
224
|
+
when key.present?
|
|
225
|
+
key
|
|
226
|
+
when option.to_sym == :param
|
|
227
|
+
:auth_token
|
|
228
|
+
when option.to_sym == :header
|
|
229
|
+
'X-AUTH-TOKEN'
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
@authentication_strategy = [option, key]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def worker(&block)
|
|
237
|
+
worker_name = "#{ name }".camelize + 'Worker'
|
|
238
|
+
|
|
239
|
+
if worker_klass = Smooth::Api.const_get(worker_name) rescue nil
|
|
240
|
+
@worker_klass = worker_klass
|
|
241
|
+
else
|
|
242
|
+
Object.const_get(worker_name, @worker_klass = Class.new(Smooth::Command::AsyncWorker))
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
@worker_klass.instance_eval(&block)
|
|
246
|
+
|
|
247
|
+
@worker_klass
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def policy(policy_name, options = {}, &block)
|
|
30
251
|
if obj = _policies[policy_name.to_sym]
|
|
31
252
|
obj.apply_options(options) unless options.empty?
|
|
32
253
|
obj.instance_eval(&block) if block_given?
|
|
@@ -37,22 +258,23 @@ module Smooth
|
|
|
37
258
|
|
|
38
259
|
elsif block_given?
|
|
39
260
|
obj = Smooth::Api::Policy.new(policy_name, options, &block)
|
|
40
|
-
|
|
261
|
+
_policies[policy_name.to_sym] = obj
|
|
41
262
|
end
|
|
42
263
|
end
|
|
43
264
|
|
|
44
|
-
def has_resource?
|
|
45
|
-
resources.
|
|
265
|
+
def has_resource?(resource_name)
|
|
266
|
+
resources.key?(resource_name.to_sym)
|
|
46
267
|
end
|
|
47
268
|
|
|
48
|
-
def resource
|
|
49
|
-
api_name =
|
|
269
|
+
def resource(resource_name, options = {}, &block)
|
|
270
|
+
api_name = name
|
|
50
271
|
|
|
51
|
-
|
|
272
|
+
existing = _resources[resource_name.to_s.downcase]
|
|
273
|
+
|
|
274
|
+
if existing
|
|
52
275
|
existing.apply_options(options) unless options.empty?
|
|
53
276
|
existing.instance_eval(&block) if block_given?
|
|
54
277
|
existing
|
|
55
|
-
|
|
56
278
|
elsif options.empty? && !block_given?
|
|
57
279
|
existing = nil
|
|
58
280
|
|
|
@@ -61,12 +283,44 @@ module Smooth
|
|
|
61
283
|
obj.api_name = api_name
|
|
62
284
|
end
|
|
63
285
|
|
|
64
|
-
_resources[resource_name.
|
|
286
|
+
_resources[resource_name.to_s.downcase] = created
|
|
65
287
|
end
|
|
66
288
|
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
class DslProxy
|
|
292
|
+
def initialize(current_user, api)
|
|
293
|
+
@current_user = current_user
|
|
294
|
+
@api = api
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def i_would_like_to
|
|
298
|
+
self
|
|
299
|
+
end
|
|
67
300
|
|
|
301
|
+
def lemme
|
|
302
|
+
self
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def imll
|
|
306
|
+
self
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def query(resource_name, *args)
|
|
310
|
+
params = args.extract_options!
|
|
311
|
+
query_name = args.first || :default
|
|
312
|
+
runner = @api.resource(resource_name).fetch(:query, query_name).as(@current_user)
|
|
313
|
+
runner.async? ? perform_async(runner.object_path, params) : runner.run(params)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def run_command(resource_name, *args)
|
|
317
|
+
params = args.extract_options!
|
|
318
|
+
command_name = args.first
|
|
319
|
+
path = resource_name if command_name.nil?
|
|
320
|
+
path = "#{ resource_name }.#{ command_name }" if command_name.present?
|
|
321
|
+
|
|
322
|
+
runner = @api.lookup_object_by(path).as(@current_user)
|
|
323
|
+
runner.async? ? perform_async(runner.object_path, params) : runner.run(params)
|
|
324
|
+
end
|
|
68
325
|
end
|
|
69
326
|
end
|
|
70
|
-
|
|
71
|
-
require 'smooth/api/tracking'
|
|
72
|
-
require 'smooth/api/policy'
|
data/lib/smooth/api/policy.rb
CHANGED
|
@@ -5,12 +5,12 @@ module Smooth
|
|
|
5
5
|
|
|
6
6
|
attr_accessor :name
|
|
7
7
|
|
|
8
|
-
def initialize
|
|
8
|
+
def initialize(name, options = {})
|
|
9
9
|
@name = name
|
|
10
10
|
@options = options
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def apply_options
|
|
13
|
+
def apply_options(*opts)
|
|
14
14
|
@options.send(:merge!, *opts)
|
|
15
15
|
end
|
|
16
16
|
end
|
data/lib/smooth/api/tracking.rb
CHANGED
|
@@ -5,7 +5,7 @@ module Smooth
|
|
|
5
5
|
@@apis ||= {}
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
-
def fetch_api
|
|
8
|
+
def fetch_api(name, &block)
|
|
9
9
|
existing = apis[name.to_sym]
|
|
10
10
|
|
|
11
11
|
if existing.nil? && block_given?
|
|
@@ -16,15 +16,15 @@ module Smooth
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def current_api
|
|
19
|
-
apis[current_api_name] ||= Smooth::Api.default
|
|
19
|
+
apis[current_api_name] ||= Smooth::Api.default
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def current_api_name=
|
|
22
|
+
def current_api_name=(value)
|
|
23
23
|
@@current_api_name = value
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def current_api_name
|
|
27
|
-
(@@current_api_name
|
|
27
|
+
(@@current_api_name ||= :default).to_sym
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Smooth
|
|
2
|
+
class Application
|
|
3
|
+
attr_reader :options
|
|
4
|
+
|
|
5
|
+
class User < Hashie::Mash
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def initialize(options = {}, &block)
|
|
9
|
+
@options = options
|
|
10
|
+
instance_eval(&block) if block_given?
|
|
11
|
+
|
|
12
|
+
config do
|
|
13
|
+
self.root = options[:root]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
boot unless options[:defer]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def config(&block)
|
|
20
|
+
Smooth.config(&block)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def console
|
|
24
|
+
require 'pry'
|
|
25
|
+
Pry.start(self, {})
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def system_user
|
|
29
|
+
@system_user ||= User.new(email: 'system@smooth.io', role: 'system')
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def api
|
|
33
|
+
@api ||= Smooth(options[:api] || :default)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def smooth
|
|
37
|
+
@smooth ||= api.as(system_user)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def resource(*args, &_block)
|
|
41
|
+
api.send(:resource, *args)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def query(*args)
|
|
45
|
+
smooth.send(:query, *args)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def command(*args)
|
|
49
|
+
smooth.send(:run_command, *args)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def load_models
|
|
53
|
+
Dir[config.models_path.join('**/*.rb')].each do |f|
|
|
54
|
+
require config.models_path.join(f)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def boot
|
|
59
|
+
@boot ||= begin
|
|
60
|
+
Smooth.active_record.establish_connection
|
|
61
|
+
load_models
|
|
62
|
+
Smooth.eager_load_from_app_folders
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|