welltreat-store-framework 0.2.0
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.
- data/README.md +25 -0
- data/lib/generators/flexi_model/install/install_generator.rb +20 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_collections.rb +17 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_collections_fields.rb +11 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_fields.rb +18 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_records.rb +12 -0
- data/lib/generators/flexi_model/install/templates/create_flexi_model_values.rb +18 -0
- data/lib/welltreat_store_framework/configuration.rb +17 -0
- data/lib/welltreat_store_framework/controller.rb +131 -0
- data/lib/welltreat_store_framework/core.rb +66 -0
- data/lib/welltreat_store_framework/haml_renderer/lorem_helper.rb +29 -0
- data/lib/welltreat_store_framework/haml_renderer/partial.rb +31 -0
- data/lib/welltreat_store_framework/haml_renderer/paths.rb +51 -0
- data/lib/welltreat_store_framework/haml_renderer/tags_helper.rb +74 -0
- data/lib/welltreat_store_framework/haml_renderer.rb +163 -0
- data/lib/welltreat_store_framework/rack_server.rb +56 -0
- data/lib/welltreat_store_framework/store_app.rb +282 -0
- data/lib/welltreat_store_framework.rb +9 -0
- data/sample/hello-store/assets/javascripts/app.js +1 -0
- data/sample/hello-store/controllers/home.rb +15 -0
- data/sample/hello-store/controllers/products.rb +18 -0
- data/sample/hello-store/models/product.rb +9 -0
- data/sample/hello-store/mount.rb +0 -0
- data/sample/hello-store/views/home/index.haml +14 -0
- data/sample/hello-store/views/layouts/default.html.haml +10 -0
- data/sample/hello-store/views/products/_product.html.haml +1 -0
- data/sample/hello-store/views/products/index.haml +4 -0
- data/sample/hello-store/views/products/show.html.haml +10 -0
- data/spec/fixtures/schema.rb +78 -0
- data/spec/lib/welltreat_store_framework/configuration_spec.rb +5 -0
- data/spec/lib/welltreat_store_framework/core_spec.rb +190 -0
- data/spec/lib/welltreat_store_framework/haml_renderer/context_spec.rb +73 -0
- data/spec/lib/welltreat_store_framework/store_app_spec.rb +85 -0
- data/spec/lib/welltreat_store_framework_spec.rb +5 -0
- data/spec/sample/controllers/products_spec.rb +140 -0
- data/spec/spec_helper/active_record.rb +8 -0
- data/spec/spec_helper/models.rb +0 -0
- data/spec/spec_helper/rspec.rb +3 -0
- data/spec/spec_helper.rb +19 -0
- metadata +129 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
module WelltreatStoreFramework
|
2
|
+
class RackServer
|
3
|
+
class AppObj
|
4
|
+
attr_accessor :id
|
5
|
+
|
6
|
+
def initialize(id)
|
7
|
+
self.id = id
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :store_name, :partition_id, :app
|
12
|
+
|
13
|
+
def initialize(store_name, partition_id)
|
14
|
+
self.store_name = store_name
|
15
|
+
self.partition_id = partition_id
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(env)
|
19
|
+
_store = _find_store(env)
|
20
|
+
if _store
|
21
|
+
_store.call(env)
|
22
|
+
else
|
23
|
+
raise "Store - #{self.store_name} for partition - #{self.partition_id} not found."
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def _find_store(env)
|
30
|
+
request = Rack::Request.new(env)
|
31
|
+
if 'development' == ENV['ENVIRONMENT'] || 'true' == request.params['reload']
|
32
|
+
puts "Reloading application..."
|
33
|
+
|
34
|
+
if self.app
|
35
|
+
puts "Previous base module id #<#{self.app.base.object_id}>"
|
36
|
+
self.app = nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
self.app ||= _load_store
|
41
|
+
end
|
42
|
+
|
43
|
+
def _load_store
|
44
|
+
store = WelltreatStoreFramework::Core.
|
45
|
+
find_store_by_name(self.store_name, AppObj.new(self.partition_id))
|
46
|
+
|
47
|
+
return store if store.nil?
|
48
|
+
|
49
|
+
store.tap do |_s|
|
50
|
+
_s.start
|
51
|
+
WelltreatStoreFramework::Core.connect_database!
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
module WelltreatStoreFramework
|
2
|
+
class StoreApp
|
3
|
+
|
4
|
+
# Declare exceptions
|
5
|
+
class ControllerNotFound < StandardError
|
6
|
+
attr_accessor :controller_name
|
7
|
+
|
8
|
+
def initialize(_c_name)
|
9
|
+
super "Controller - #{_c_name} not found."
|
10
|
+
self.controller_name = _c_name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ActionNotFound < StandardError
|
15
|
+
attr_accessor :action_name, :controller_name
|
16
|
+
|
17
|
+
def initialize(_a_name, _c_name)
|
18
|
+
super "Action - #{_a_name} from controller - #{_c_name} not found."
|
19
|
+
self.action_name = _a_name
|
20
|
+
self.controller_name = _c_name
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class ExecutionError < StandardError;
|
25
|
+
end
|
26
|
+
|
27
|
+
class TemplateNotFound < StandardError
|
28
|
+
attr_accessor :file
|
29
|
+
|
30
|
+
def initialize(_file)
|
31
|
+
super "Template - #{_file} not found."
|
32
|
+
self.file = _file
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class TemplateRenderingError < StandardError;
|
37
|
+
end
|
38
|
+
|
39
|
+
# Include haml support
|
40
|
+
if defined?(Haml)
|
41
|
+
require 'welltreat_store_framework/haml_renderer'
|
42
|
+
include WelltreatStoreFramework::HamlRenderer
|
43
|
+
else
|
44
|
+
raise "No such haml found. Use gem 'haml' in your Gemfile"
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# Declare attribute accessors
|
49
|
+
attr_accessor :name, :path, :config_path, :routes_path,
|
50
|
+
:controllers_path, :models_path, :views_path, :assets_path,
|
51
|
+
:views, :started, :partition_object
|
52
|
+
|
53
|
+
# Default constructor with attribute hash, if attribute hash is passed
|
54
|
+
# it will set value through setter accessors
|
55
|
+
def initialize(attrs = { })
|
56
|
+
if attrs.present?
|
57
|
+
attrs.each do |k, v|
|
58
|
+
self.send(:"#{k}=", v)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Start application
|
64
|
+
# Return true if successful otherwise false
|
65
|
+
def start
|
66
|
+
_bootstrap!
|
67
|
+
self.started = true
|
68
|
+
end
|
69
|
+
|
70
|
+
# Dispose and stop application
|
71
|
+
# Return true if successful otherwise false
|
72
|
+
def stop
|
73
|
+
if self.started
|
74
|
+
_dispose!
|
75
|
+
self.started = false
|
76
|
+
true
|
77
|
+
else
|
78
|
+
false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Stop and start application
|
83
|
+
def restart
|
84
|
+
if self.started
|
85
|
+
self.stop
|
86
|
+
self.start
|
87
|
+
true
|
88
|
+
else
|
89
|
+
false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def base;
|
94
|
+
_base_module
|
95
|
+
end
|
96
|
+
|
97
|
+
def models
|
98
|
+
base::Models
|
99
|
+
end
|
100
|
+
|
101
|
+
def controllers
|
102
|
+
base::Controllers
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
# Handle request for the specified path and request
|
107
|
+
# Return status and html content string
|
108
|
+
def dispatch(path, request, response, options)
|
109
|
+
if WelltreatStoreFramework::Core.configuration.auto_reload
|
110
|
+
restart
|
111
|
+
end
|
112
|
+
|
113
|
+
begin
|
114
|
+
case path
|
115
|
+
when '/'
|
116
|
+
_execute_action(:Home, :index, request, response, options)
|
117
|
+
else
|
118
|
+
_controller_name, _action, _id = self.send(:_extract_path, path)
|
119
|
+
request.send(:set_param, :id, _id)
|
120
|
+
|
121
|
+
_execute_action(_controller_name, _action, request, response, options)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Handle 404
|
125
|
+
rescue WelltreatStoreFramework::StoreApp::ControllerNotFound
|
126
|
+
_execute_action(:Home, :not_found, request, response, options)
|
127
|
+
|
128
|
+
rescue WelltreatStoreFramework::StoreApp::ActionNotFound
|
129
|
+
_execute_action(:Home, :not_found, request, response, options)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Make it rack compatible
|
134
|
+
def call(env)
|
135
|
+
request = WelltreatStoreFramework::Controller::Request.initialize_from_env(env)
|
136
|
+
response = WelltreatStoreFramework::Controller::Response.new
|
137
|
+
options = {
|
138
|
+
session: env['rack.session']
|
139
|
+
}
|
140
|
+
|
141
|
+
dispatch request.path, request, response, options
|
142
|
+
render! request, response, options
|
143
|
+
|
144
|
+
[response.status, response.headers, [response.content]]
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
def _execute_action(_controller_name, _action, request, response, options)
|
149
|
+
_controller_inst = _find_controller_inst(_controller_name)
|
150
|
+
_check_action_existence!(_controller_inst, _action)
|
151
|
+
|
152
|
+
# Set default template
|
153
|
+
response.template = _action
|
154
|
+
response.controller_name = _controller_name
|
155
|
+
|
156
|
+
# Execute action
|
157
|
+
_controller_inst.send(_action, request, response, options)
|
158
|
+
end
|
159
|
+
|
160
|
+
def _check_action_existence!(_controller_inst, _action)
|
161
|
+
raise ActionNotFound.new(_action, _controller_inst.class.name) unless _controller_inst.respond_to?(_action)
|
162
|
+
end
|
163
|
+
|
164
|
+
def _find_controller_inst(controller_name)
|
165
|
+
_check_controller_existence!(controller_name)
|
166
|
+
_singleton_instance(_base_module::Controllers::const_get(controller_name))
|
167
|
+
end
|
168
|
+
|
169
|
+
def _check_controller_existence!(controller_name)
|
170
|
+
_controller = _all_controllers.select { |c| c == controller_name }.first
|
171
|
+
raise ControllerNotFound.new(controller_name) if _controller.nil?
|
172
|
+
end
|
173
|
+
|
174
|
+
def _singleton_instance(clazz)
|
175
|
+
@_instances ||= { }
|
176
|
+
@_instances[clazz.name] ||= clazz.new(self)
|
177
|
+
end
|
178
|
+
|
179
|
+
def _all_controllers
|
180
|
+
@_all_controllers ||= _base_module::Controllers.constants
|
181
|
+
end
|
182
|
+
|
183
|
+
def _all_controllers=(v)
|
184
|
+
@_all_controllers = v
|
185
|
+
end
|
186
|
+
|
187
|
+
def _extract_path(path)
|
188
|
+
_parts = path.split('/')[1..9999]
|
189
|
+
|
190
|
+
_controller_name = _parts.first.to_s.camelize.to_sym
|
191
|
+
_action = if _parts.length > 1
|
192
|
+
_parts[1]
|
193
|
+
else
|
194
|
+
:index
|
195
|
+
end
|
196
|
+
|
197
|
+
_id = if _parts.length > 2
|
198
|
+
_parts.last
|
199
|
+
else
|
200
|
+
nil
|
201
|
+
end
|
202
|
+
|
203
|
+
[_controller_name, _action, _id]
|
204
|
+
end
|
205
|
+
|
206
|
+
def _dispose!
|
207
|
+
@_instances = nil
|
208
|
+
self.class.send(:remove_const, self.send(:_base_module_name))
|
209
|
+
self._base_module = nil
|
210
|
+
self._all_controllers = nil
|
211
|
+
end
|
212
|
+
|
213
|
+
def _bootstrap!
|
214
|
+
_base_module
|
215
|
+
end
|
216
|
+
|
217
|
+
def _base_module
|
218
|
+
@_base_module ||= _create_base_module
|
219
|
+
end
|
220
|
+
|
221
|
+
def _base_module=(mod)
|
222
|
+
@_base_module = mod
|
223
|
+
end
|
224
|
+
|
225
|
+
def _base_module_name
|
226
|
+
self.send(:_base_module).name.split('::').last
|
227
|
+
end
|
228
|
+
|
229
|
+
def _create_base_module
|
230
|
+
mod_name = "#{self.name.capitalize}AppStack".underscore.classify
|
231
|
+
base_const = eval <<-CODE, nil, "dynamic/#{mod_name}", __LINE__ + 1
|
232
|
+
module #{mod_name}
|
233
|
+
|
234
|
+
module Controllers
|
235
|
+
AppStack.load_classes(self, "#{self.controllers_path}")
|
236
|
+
end
|
237
|
+
|
238
|
+
module Models
|
239
|
+
AppStack.load_classes(self, "#{self.models_path}")
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
#{mod_name}
|
244
|
+
CODE
|
245
|
+
|
246
|
+
AppStack.generate_partition_object_getter(self, [base_const::Models])
|
247
|
+
|
248
|
+
base_const
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
# Provide utilities for bootstrapping new app stack
|
253
|
+
class AppStack
|
254
|
+
class << self
|
255
|
+
|
256
|
+
def generate_partition_object_getter(store, _modules)
|
257
|
+
if store.partition_object
|
258
|
+
_modules.each do |_mod|
|
259
|
+
_mod.constants.each do |_const|
|
260
|
+
_class = _mod.const_get(_const)
|
261
|
+
if _class.respond_to?(:set_flexi_partition_id)
|
262
|
+
_class.send(:set_flexi_partition_id, store.partition_object.id)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
def load_classes(_mod, _path)
|
270
|
+
if _path.match(/\.rb$/)
|
271
|
+
_mod.module_eval File.read(_path), _path, 0
|
272
|
+
else
|
273
|
+
Dir.glob(File.join(_path, "*.rb")).each do |_file|
|
274
|
+
_mod.module_eval File.read(_file), _file, 0
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
282
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
require 'welltreat_store_framework/store_app'
|
3
|
+
require 'welltreat_store_framework/configuration'
|
4
|
+
require 'welltreat_store_framework/core'
|
5
|
+
require 'welltreat_store_framework/controller'
|
6
|
+
|
7
|
+
module WelltreatStoreFramework
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
alert('Hi there');
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Home
|
2
|
+
include WelltreatStoreFramework::Controller
|
3
|
+
|
4
|
+
def index(request, response)
|
5
|
+
response.set :title, "Hello World"
|
6
|
+
response.set :name, "Hasan"
|
7
|
+
|
8
|
+
response.set :products, app.models::Product.all
|
9
|
+
end
|
10
|
+
|
11
|
+
def not_found(request, response)
|
12
|
+
response.content = "<h1>Page Not found</h1>"
|
13
|
+
response.status = 404
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Products
|
2
|
+
include WelltreatStoreFramework::Controller
|
3
|
+
|
4
|
+
class ProductNotFound < StandardError; end
|
5
|
+
|
6
|
+
def index(request, response)
|
7
|
+
response.set :products, [{name: 'Product 1'}, {name: 'Product 2'}]
|
8
|
+
end
|
9
|
+
|
10
|
+
def show(request, response)
|
11
|
+
if request[:id].present?
|
12
|
+
response.set :product, app.models::Product.find(request[:id])
|
13
|
+
response.set :title, response.get(:product).name
|
14
|
+
else
|
15
|
+
raise ProductNotFound
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
%h4 Hi there #{get :name}
|
2
|
+
|
3
|
+
- if present?(:products)
|
4
|
+
%h5 List of products
|
5
|
+
.product
|
6
|
+
- get(:products).each do |product|
|
7
|
+
%h6= product.name
|
8
|
+
%small= product.price
|
9
|
+
%p= product.description
|
10
|
+
- if product.available?
|
11
|
+
It's in stock
|
12
|
+
- else
|
13
|
+
It's outta stock
|
14
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
%strong= get_local(:prod)[:name]
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended to check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(:version => 20120318055757) do
|
15
|
+
|
16
|
+
create_table "flexi_model_collections", :force => true do |t|
|
17
|
+
t.string 'name'
|
18
|
+
t.string 'singular_label'
|
19
|
+
t.string 'plural_label'
|
20
|
+
t.string 'namespace'
|
21
|
+
t.integer 'partition_id'
|
22
|
+
|
23
|
+
t.datetime "created_at"
|
24
|
+
t.datetime "updated_at"
|
25
|
+
end
|
26
|
+
|
27
|
+
add_index "flexi_model_collections", [:namespace, :name]
|
28
|
+
add_index "flexi_model_collections", [:namespace, :name, :partition_id],
|
29
|
+
name: 'index_ns_name_pi', unique: true
|
30
|
+
|
31
|
+
create_table 'flexi_model_fields', :force => true do |t|
|
32
|
+
t.string 'name'
|
33
|
+
t.string 'singular_label'
|
34
|
+
t.string 'plural_label'
|
35
|
+
t.string 'namespace'
|
36
|
+
t.integer 'partition_id'
|
37
|
+
|
38
|
+
t.string 'field_type'
|
39
|
+
t.text 'default_value'
|
40
|
+
end
|
41
|
+
|
42
|
+
add_index 'flexi_model_fields', [:namespace, :name]
|
43
|
+
add_index 'flexi_model_fields', [:namespace, :name, :field_type]
|
44
|
+
add_index 'flexi_model_fields', [:namespace, :name, :field_type, :partition_id],
|
45
|
+
unique: true,
|
46
|
+
name: 'index_ns_name_ft_pi'
|
47
|
+
|
48
|
+
create_table 'flexi_model_collections_fields', :force => true, :id => false do |t|
|
49
|
+
t.integer 'collection_id'
|
50
|
+
t.integer 'field_id'
|
51
|
+
end
|
52
|
+
|
53
|
+
add_index 'flexi_model_collections_fields', [:collection_id]
|
54
|
+
add_index 'flexi_model_collections_fields', [:field_id]
|
55
|
+
|
56
|
+
create_table 'flexi_model_records', :force => true do |t|
|
57
|
+
t.integer 'collection_id'
|
58
|
+
t.string 'namespace'
|
59
|
+
t.datetime "created_at"
|
60
|
+
t.datetime "updated_at"
|
61
|
+
end
|
62
|
+
|
63
|
+
add_index 'flexi_model_records', [:namespace, :collection_id]
|
64
|
+
|
65
|
+
create_table 'flexi_model_values', :force => true do |t|
|
66
|
+
t.integer 'record_id'
|
67
|
+
t.integer 'field_id'
|
68
|
+
t.boolean 'bool_value'
|
69
|
+
t.integer 'int_value'
|
70
|
+
t.decimal 'dec_value'
|
71
|
+
t.string 'str_value'
|
72
|
+
t.text 'txt_value'
|
73
|
+
t.datetime 'dt_value'
|
74
|
+
end
|
75
|
+
|
76
|
+
add_index 'flexi_model_values', [:record_id, :field_id]
|
77
|
+
|
78
|
+
end
|