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