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.
Files changed (40) hide show
  1. data/README.md +25 -0
  2. data/lib/generators/flexi_model/install/install_generator.rb +20 -0
  3. data/lib/generators/flexi_model/install/templates/create_flexi_model_collections.rb +17 -0
  4. data/lib/generators/flexi_model/install/templates/create_flexi_model_collections_fields.rb +11 -0
  5. data/lib/generators/flexi_model/install/templates/create_flexi_model_fields.rb +18 -0
  6. data/lib/generators/flexi_model/install/templates/create_flexi_model_records.rb +12 -0
  7. data/lib/generators/flexi_model/install/templates/create_flexi_model_values.rb +18 -0
  8. data/lib/welltreat_store_framework/configuration.rb +17 -0
  9. data/lib/welltreat_store_framework/controller.rb +131 -0
  10. data/lib/welltreat_store_framework/core.rb +66 -0
  11. data/lib/welltreat_store_framework/haml_renderer/lorem_helper.rb +29 -0
  12. data/lib/welltreat_store_framework/haml_renderer/partial.rb +31 -0
  13. data/lib/welltreat_store_framework/haml_renderer/paths.rb +51 -0
  14. data/lib/welltreat_store_framework/haml_renderer/tags_helper.rb +74 -0
  15. data/lib/welltreat_store_framework/haml_renderer.rb +163 -0
  16. data/lib/welltreat_store_framework/rack_server.rb +56 -0
  17. data/lib/welltreat_store_framework/store_app.rb +282 -0
  18. data/lib/welltreat_store_framework.rb +9 -0
  19. data/sample/hello-store/assets/javascripts/app.js +1 -0
  20. data/sample/hello-store/controllers/home.rb +15 -0
  21. data/sample/hello-store/controllers/products.rb +18 -0
  22. data/sample/hello-store/models/product.rb +9 -0
  23. data/sample/hello-store/mount.rb +0 -0
  24. data/sample/hello-store/views/home/index.haml +14 -0
  25. data/sample/hello-store/views/layouts/default.html.haml +10 -0
  26. data/sample/hello-store/views/products/_product.html.haml +1 -0
  27. data/sample/hello-store/views/products/index.haml +4 -0
  28. data/sample/hello-store/views/products/show.html.haml +10 -0
  29. data/spec/fixtures/schema.rb +78 -0
  30. data/spec/lib/welltreat_store_framework/configuration_spec.rb +5 -0
  31. data/spec/lib/welltreat_store_framework/core_spec.rb +190 -0
  32. data/spec/lib/welltreat_store_framework/haml_renderer/context_spec.rb +73 -0
  33. data/spec/lib/welltreat_store_framework/store_app_spec.rb +85 -0
  34. data/spec/lib/welltreat_store_framework_spec.rb +5 -0
  35. data/spec/sample/controllers/products_spec.rb +140 -0
  36. data/spec/spec_helper/active_record.rb +8 -0
  37. data/spec/spec_helper/models.rb +0 -0
  38. data/spec/spec_helper/rspec.rb +3 -0
  39. data/spec/spec_helper.rb +19 -0
  40. 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
@@ -0,0 +1,9 @@
1
+ class Product
2
+ include FlexiModel
3
+
4
+ flexi_field :name, :string
5
+ flexi_field :description, :text
6
+ flexi_field :price, :float
7
+ flexi_field :available, :boolean
8
+
9
+ 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,10 @@
1
+ !!!5
2
+ %html
3
+ %head
4
+ %title= get :title
5
+ %script{type: 'text/javascript', src: javascript_path('app')}
6
+
7
+ %body
8
+ %h1 Basic Layout
9
+ %blockquote
10
+ = get :body
@@ -0,0 +1 @@
1
+ %strong= get_local(:prod)[:name]
@@ -0,0 +1,4 @@
1
+ %h5 Hi it's from products index
2
+
3
+ - get(:products).each do |prod|
4
+ = partial '_product', prod: prod
@@ -0,0 +1,10 @@
1
+ %h1= get :title
2
+
3
+ .product_details
4
+ %h4= get(:product).name
5
+ %small= get(:product).price
6
+ %p= get(:product).description
7
+ - if get(:product).available?
8
+ It's in stock
9
+ - else
10
+ It's outta stock
@@ -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
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe WelltreatStoreFramework::Configuration do
4
+
5
+ end