welltreat-store-framework 0.2.0

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