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
data/lib/smooth/cache.rb
CHANGED
data/lib/smooth/command.rb
CHANGED
|
@@ -1,35 +1,131 @@
|
|
|
1
|
-
require 'smooth/ext/mutations'
|
|
2
|
-
require 'smooth/command/instrumented'
|
|
3
|
-
|
|
4
1
|
class Smooth::Command < Mutations::Command
|
|
5
2
|
include Instrumented
|
|
6
3
|
|
|
4
|
+
def self.as(current_user)
|
|
5
|
+
require 'smooth/command/run_proxy' unless defined?(RunProxy)
|
|
6
|
+
RunProxy.new(current_user, self)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# DSL Improvements English
|
|
10
|
+
def self.params(*args, &block)
|
|
11
|
+
send(:required, *args, &block)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.interface(*args, &block)
|
|
15
|
+
send(:required, *args, &block)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.input_argument_names
|
|
19
|
+
required_inputs.keys + optional_inputs.keys
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Commands are aware of who is running them
|
|
23
|
+
attr_accessor :current_user
|
|
24
|
+
|
|
7
25
|
class_attribute :resource_name,
|
|
8
26
|
:command_action,
|
|
9
|
-
:event_namespace
|
|
27
|
+
:event_namespace,
|
|
28
|
+
:model_class,
|
|
29
|
+
:base_scope,
|
|
30
|
+
:parent_resource
|
|
10
31
|
|
|
11
|
-
def self.
|
|
12
|
-
|
|
32
|
+
def self.base_scope
|
|
33
|
+
@base_scope || :all
|
|
13
34
|
end
|
|
14
35
|
|
|
15
|
-
def
|
|
16
|
-
|
|
36
|
+
def parent_api
|
|
37
|
+
self.class.parent_api
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def parent_resource
|
|
41
|
+
self.class.parent_resource
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.belongs_to_resource(resource)
|
|
45
|
+
self.parent_resource = resource
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.parent_api
|
|
49
|
+
parent_resource.api
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Returns the model scope for this command. If a scope method
|
|
53
|
+
# is set on this command, it will make sure to scope the model
|
|
54
|
+
# by that method. It will pass whatever arguments you pass to scope
|
|
55
|
+
# to the scope method. if you pass no args, and the scope requires one,
|
|
56
|
+
# we will assume the user wants us to pass the current user of the command
|
|
57
|
+
def scope(*args)
|
|
58
|
+
@scope ||= begin
|
|
59
|
+
meth = model_class.send(:method, self.class.base_scope)
|
|
60
|
+
|
|
61
|
+
if meth.arity.abs >= 1
|
|
62
|
+
args.push(current_user) if args.empty?
|
|
63
|
+
model_class.send(self.class.base_scope, *args)
|
|
64
|
+
else
|
|
65
|
+
model_class.send(self.class.base_scope)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def scope=(new_scope)
|
|
71
|
+
@scope = new_scope || scope
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.scope(setting = nil)
|
|
75
|
+
self.base_scope = setting if setting
|
|
76
|
+
base_scope || :all
|
|
17
77
|
end
|
|
18
78
|
|
|
19
79
|
def self.event_namespace
|
|
20
|
-
@event_namespace || "#{ command_action }.#{
|
|
80
|
+
@event_namespace || "#{ command_action }.#{ resource_alias }".downcase
|
|
21
81
|
end
|
|
22
82
|
|
|
23
|
-
def
|
|
83
|
+
def self.resource_alias
|
|
84
|
+
resource_name.singularize.underscore
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def self.resource_name
|
|
88
|
+
value = @resource_name.to_s
|
|
89
|
+
|
|
90
|
+
if value.empty? && model_class
|
|
91
|
+
value = model_class.to_s
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
value
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.object_path
|
|
98
|
+
resource_name.downcase + '.' + command_action
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def event_namespace
|
|
102
|
+
self.class.event_namespace
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def object_path
|
|
106
|
+
self.class.object_path
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def resource_name
|
|
110
|
+
self.class.resource_name
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def resource_alias
|
|
114
|
+
self.class.resource_alias
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def model_class
|
|
118
|
+
self.class.model_class
|
|
119
|
+
end
|
|
24
120
|
|
|
25
121
|
# DSL Hooks
|
|
26
122
|
#
|
|
27
123
|
#
|
|
28
|
-
def self.configure
|
|
124
|
+
def self.configure(dsl_config_object, resource = nil)
|
|
29
125
|
resource ||= Smooth.current_resource
|
|
30
|
-
klass = define_or_open(
|
|
126
|
+
klass = define_or_open(dsl_config_object, resource)
|
|
31
127
|
|
|
32
|
-
Array(
|
|
128
|
+
Array(dsl_config_object.blocks).each do |blk|
|
|
33
129
|
klass.class_eval(&blk)
|
|
34
130
|
end
|
|
35
131
|
|
|
@@ -41,15 +137,168 @@ class Smooth::Command < Mutations::Command
|
|
|
41
137
|
base = Smooth.command
|
|
42
138
|
|
|
43
139
|
name = options.name.to_s.camelize
|
|
44
|
-
klass = "#{ name }#{
|
|
140
|
+
klass = "#{ name }#{ resource.model_class }".gsub(/\s+/, '')
|
|
141
|
+
|
|
142
|
+
apply_options = lambda do |k|
|
|
143
|
+
k.model_class ||= resource.model_class if resource.model_class
|
|
144
|
+
|
|
145
|
+
k.belongs_to_resource(resource)
|
|
146
|
+
|
|
147
|
+
k.resource_name = resource.name.to_s
|
|
148
|
+
k.command_action = options.name.to_s
|
|
149
|
+
end
|
|
45
150
|
|
|
46
151
|
if command_klass = Object.const_get(klass) rescue nil
|
|
47
|
-
return command_klass
|
|
152
|
+
return command_klass.tap(&apply_options)
|
|
48
153
|
end
|
|
49
154
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
155
|
+
parent_klass = Class.new(base)
|
|
156
|
+
|
|
157
|
+
begin
|
|
158
|
+
Object.const_set(klass, parent_klass).tap(&apply_options)
|
|
159
|
+
rescue => ex
|
|
160
|
+
puts ex.message
|
|
161
|
+
puts "Error setting #{ klass } #{ base }. klass is a #{ klass.class }"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
parent_klass
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Interface Documentation
|
|
168
|
+
#
|
|
169
|
+
def interface_for(filter)
|
|
170
|
+
self.class.interface_description.filters.send(filter)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def self.interface_description
|
|
174
|
+
interface_documentation
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def self.interface_documentation
|
|
178
|
+
optional_inputs = input_filters.optional_inputs
|
|
179
|
+
required_inputs = input_filters.required_inputs
|
|
180
|
+
|
|
181
|
+
data = {
|
|
182
|
+
required: required_inputs.keys,
|
|
183
|
+
optional: optional_inputs.keys,
|
|
184
|
+
filters: {}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
blk = lambda do |memo, parts, required|
|
|
188
|
+
key, filter = parts
|
|
189
|
+
|
|
190
|
+
type = filter.class.name[/^Mutations::([a-zA-Z]*)Filter$/, 1].underscore
|
|
191
|
+
options = filter.options.merge(required: required)
|
|
192
|
+
|
|
193
|
+
value = memo[key] = {
|
|
194
|
+
type: type,
|
|
195
|
+
options: options.reject { |_k, v| v.nil? },
|
|
196
|
+
description: input_descriptions[key]
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if options[:faker]
|
|
200
|
+
value[:example] = Smooth.faker(options[:faker])
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
memo
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
required_inputs.reduce(data[:filters]) do |memo, parts|
|
|
207
|
+
blk.call(memo, parts, true)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
optional_inputs.reduce(data[:filters]) do |memo, parts|
|
|
211
|
+
blk.call(memo, parts, false)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
data.to_mash
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def self.filter_for_param(param)
|
|
218
|
+
optional_inputs[param] || required_inputs[param]
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def self.filter_options_for_param(param)
|
|
222
|
+
filter_for_param(param).try(:options)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def self.response_class
|
|
226
|
+
Smooth::Response
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
# Creates a new instance of the Smooth::Command::Response
|
|
230
|
+
# class in response to a request from the Router. It is
|
|
231
|
+
# assumed that a request object responds to: user, and params
|
|
232
|
+
def self.respond_to_request(request_object, options = {})
|
|
233
|
+
klass = self
|
|
234
|
+
|
|
235
|
+
outcome = options.fetch(:outcome) do
|
|
236
|
+
klass.as(request_object.user).run(request_object.params)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
response_class.new(outcome, serializer_options).tap do |response|
|
|
240
|
+
response.request_headers = request_object.headers
|
|
241
|
+
response.serializer = find_serializer_for(request_object)
|
|
242
|
+
response.event_namespace = event_namespace
|
|
243
|
+
response.command_action = command_action
|
|
244
|
+
response.current_user = request_object.user
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def self.find_serializer_for(_request_object)
|
|
249
|
+
resource = Smooth.resource(resource_name)
|
|
250
|
+
resource ||= Smooth.resource("#{ resource_name }".pluralize)
|
|
251
|
+
|
|
252
|
+
# TODO
|
|
253
|
+
# We can make the preferred format something you can
|
|
254
|
+
# specify via a header or parameter. We can also restrict
|
|
255
|
+
# certain serializers from certain policies.
|
|
256
|
+
preferred_format = :default
|
|
257
|
+
|
|
258
|
+
resource.fetch(:serializer, preferred_format)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def self.serializer_options
|
|
262
|
+
{}
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# Allows for defining common execution pattern methods
|
|
266
|
+
# mostly for standard CRUD against scoped models
|
|
267
|
+
def self.execute(execution_pattern = nil, &block)
|
|
268
|
+
send :define_method, :execute, (block || get_execution_pattern(execution_pattern))
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
Patterns = {}
|
|
272
|
+
|
|
273
|
+
Patterns[:update] = lambda do
|
|
274
|
+
scoped_find_object.update_attributes(inputs)
|
|
275
|
+
scoped_find_object
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
Patterns[:create] = lambda do
|
|
279
|
+
scope.create(inputs)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
Patterns[:destroy] = lambda do
|
|
283
|
+
scoped_find_object.destroy
|
|
284
|
+
scoped_find_object
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def scoped_find_object
|
|
288
|
+
@scoped_find ||= if scope.respond_to?(:find) && found = (scope.find(id) rescue nil)
|
|
289
|
+
found
|
|
290
|
+
else
|
|
291
|
+
add_error(:id, :not_found, "could not find a #{ resource_name } model with that id")
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def self.get_execution_pattern(pattern_name)
|
|
296
|
+
if respond_to?("#{ pattern_name }_execution_pattern")
|
|
297
|
+
return method("#{ pattern_name }_execution_pattern").to_proc
|
|
298
|
+
elsif Patterns.key?(pattern_name.to_sym)
|
|
299
|
+
Patterns.fetch(pattern_name.to_sym)
|
|
300
|
+
else
|
|
301
|
+
return method(:execute).to_proc
|
|
53
302
|
end
|
|
54
303
|
end
|
|
55
304
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Smooth
|
|
2
|
+
class Command::AsyncWorker
|
|
3
|
+
unless Smooth.config.async_provider
|
|
4
|
+
fail 'Must specify an async provider. e.g. Sidekiq::Worker on Smooth.config.async_provider'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.options(*args)
|
|
8
|
+
send(:sidekiq_options, *args) if defined?(Sidekiq)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def perform(serialized_payload)
|
|
12
|
+
if hash = memory_store.read(serialized_payload)
|
|
13
|
+
api, object_path, payload = hash.values_at('api', 'object_path', 'payload')
|
|
14
|
+
current_user = payload['current_user'] || hash['current_user']
|
|
15
|
+
|
|
16
|
+
chain = Smooth(api).lookup_object_by(object_path)
|
|
17
|
+
chain = chain.as(current_user) if current_user
|
|
18
|
+
|
|
19
|
+
chain.run(payload)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def memory_store
|
|
24
|
+
Smooth.config.memory_store
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -29,15 +29,17 @@ module Smooth
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def run_with_instrumentation
|
|
32
|
+
def run_with_instrumentation(event_prefix = nil)
|
|
33
33
|
outcome = run_with_outcome
|
|
34
34
|
|
|
35
|
+
event_prefix = "#{ event_prefix }." if event_prefix
|
|
36
|
+
|
|
35
37
|
if outcome.success?
|
|
36
38
|
result = outcome.result
|
|
37
|
-
track_event("#{ event_namespace }", result: result, inputs: inputs)
|
|
38
|
-
|
|
39
|
+
track_event("#{ event_prefix }#{ event_namespace }", result: result, inputs: inputs, current_user: current_user)
|
|
40
|
+
outcome
|
|
39
41
|
else
|
|
40
|
-
track_event("errors/#{ event_namespace }", errors: outcome.errors, inputs: inputs)
|
|
42
|
+
track_event("errors/#{ event_prefix }#{ event_namespace }", errors: outcome.errors, inputs: inputs, current_user: current_user)
|
|
41
43
|
outcome
|
|
42
44
|
end
|
|
43
45
|
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Internal class to provide current user awareness to the
|
|
2
|
+
module Smooth
|
|
3
|
+
class Command < Mutations::Command
|
|
4
|
+
class RunProxy
|
|
5
|
+
attr_accessor :current_user, :cmd
|
|
6
|
+
|
|
7
|
+
def initialize(current_user, cmd)
|
|
8
|
+
@current_user = current_user
|
|
9
|
+
@cmd = cmd
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def run!(*args)
|
|
13
|
+
cmd.new(*args).tap { |c| c.current_user = current_user }.run!
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def run(*args)
|
|
17
|
+
cmd.new(*args).tap { |c| c.current_user = current_user }.run
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/smooth/configuration.rb
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
require 'singleton'
|
|
2
|
-
|
|
3
1
|
module Smooth
|
|
4
2
|
class Configuration
|
|
5
3
|
include Singleton
|
|
@@ -7,18 +5,75 @@ module Smooth
|
|
|
7
5
|
cattr_accessor :query_class,
|
|
8
6
|
:command_class,
|
|
9
7
|
:serializer_class,
|
|
10
|
-
:
|
|
8
|
+
:object_path_separator,
|
|
9
|
+
:enable_events,
|
|
10
|
+
:definition_folders,
|
|
11
|
+
:eager_load_app_folders,
|
|
12
|
+
:active_record_config,
|
|
13
|
+
:models_path,
|
|
14
|
+
:schema_file,
|
|
15
|
+
:migrations_path,
|
|
16
|
+
:root,
|
|
17
|
+
:include_root_in_json,
|
|
18
|
+
:auth_token_column,
|
|
19
|
+
:enable_factories,
|
|
20
|
+
:async_provider,
|
|
21
|
+
:memory_store,
|
|
22
|
+
:embed_relationships_as
|
|
23
|
+
|
|
24
|
+
@@query_class = Smooth::Query
|
|
25
|
+
@@command_class = Smooth::Command
|
|
26
|
+
@@serializer_class = defined?(ApplicationSerializer) ? ApplicationSerializer : Smooth::Serializer
|
|
27
|
+
@@enable_events = true
|
|
28
|
+
@@eager_load_app_folders = true
|
|
29
|
+
@@models_path = 'app/models'
|
|
30
|
+
@@object_path_separator = '.'
|
|
31
|
+
@@definition_folders = %w(app/models app/apis app/queries app/commands app/serializers app/resources)
|
|
32
|
+
@@include_root_in_json = true
|
|
33
|
+
@@enable_factories = true
|
|
11
34
|
|
|
12
|
-
@@
|
|
13
|
-
@@
|
|
14
|
-
@@
|
|
15
|
-
@@
|
|
35
|
+
@@active_record_config = 'config/database.yml'
|
|
36
|
+
@@schema_file = 'db/schema.rb'
|
|
37
|
+
@@migrations_path = 'db/migrate'
|
|
38
|
+
@@root = Dir.pwd
|
|
39
|
+
@@auth_token_column = :authentication_token
|
|
40
|
+
@@async_provider = Sidekiq::Worker if defined?(Sidekiq)
|
|
41
|
+
@@memory_store = Smooth.cache
|
|
42
|
+
|
|
43
|
+
@@embed_relationships_as = :ids
|
|
44
|
+
|
|
45
|
+
def active_record
|
|
46
|
+
return active_record_config if active_record_config.is_a?(Hash)
|
|
47
|
+
file = root.join(active_record_config)
|
|
48
|
+
fail 'The config file does not exist at ' + file.to_s unless file.exist?
|
|
49
|
+
YAML.load(file.open).fetch(Smooth.env)
|
|
50
|
+
end
|
|
16
51
|
|
|
17
52
|
def enable_event_tracking?
|
|
18
53
|
!!@@enable_events
|
|
19
54
|
end
|
|
20
55
|
|
|
21
|
-
def
|
|
56
|
+
def root
|
|
57
|
+
Pathname(@@root)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def app_folder_paths
|
|
61
|
+
Array(definition_folders).map { |f| root.join(f) }
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def models_path
|
|
65
|
+
root.join(@@models_path)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def method_missing(meth, *args, &block)
|
|
69
|
+
if meth.to_s.match(/(\w+)\?$/)
|
|
70
|
+
!!(send(Regexp.last_match[1], *args, &block)) if respond_to?(Regexp.last_match[1])
|
|
71
|
+
else
|
|
72
|
+
super
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def self.method_missing(meth, *args, &block)
|
|
22
77
|
instance.send(meth, *args, &block)
|
|
23
78
|
end
|
|
24
79
|
end
|