mgt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5ed60468779ffe05f949250a541d765fec20331a
4
+ data.tar.gz: de379142d86b4b891e21ec5973545e9601035f08
5
+ SHA512:
6
+ metadata.gz: d648450251b71d28e45e9799b192d0b0770b7e6a026acdc24d71eb4742a83fc353cc86f2cef8ee5af4d4d86db54f47d2f87732fd3903e025507c2da708197a3b
7
+ data.tar.gz: 49f29892a4ab741d05bbcac78e495be526234f196bff6c80d2d7efd3b8dfcd4789f74669391d0376d88b82be3cacf1cc7cc543661f7a42e159befc39c5b9e73c
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ repo_token: uixkIv8ZhuXrS2BQYHUsiBH5H4U77boI7
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /coverage
data/.hound.yml ADDED
@@ -0,0 +1,2 @@
1
+ ruby:
2
+ config_file: .rubocop.yml
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,241 @@
1
+ AllCops:
2
+ Exclude:
3
+ - "vendor/**/*"
4
+ - "db/schema.rb"
5
+ UseCache: false
6
+ Style/CollectionMethods:
7
+ Description: Preferred collection methods.
8
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#map-find-select-reduce-size
9
+ Enabled: true
10
+ PreferredMethods:
11
+ collect: map
12
+ collect!: map!
13
+ find: detect
14
+ find_all: select
15
+ reduce: inject
16
+ Style/DotPosition:
17
+ Description: Checks the position of the dot in multi-line method calls.
18
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide
19
+ Enabled: true
20
+ EnforcedStyle: trailing
21
+ SupportedStyles:
22
+ - leading
23
+ - trailing
24
+ Style/FileName:
25
+ Description: Use snake_case for source file names.
26
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#snake-case-files
27
+ Enabled: false
28
+ Exclude: []
29
+ Style/GuardClause:
30
+ Description: Check for conditionals that can be replaced with guard clauses
31
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
32
+ Enabled: false
33
+ MinBodyLength: 1
34
+ Style/IfUnlessModifier:
35
+ Description: Favor modifier if/unless usage when you have a single-line body.
36
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#if-as-a-modifier
37
+ Enabled: false
38
+ MaxLineLength: 80
39
+ Style/OptionHash:
40
+ Description: Don't use option hashes when you can use keyword arguments.
41
+ Enabled: false
42
+ Style/PercentLiteralDelimiters:
43
+ Description: Use `%`-literal delimiters consistently
44
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#percent-literal-braces
45
+ Enabled: false
46
+ PreferredDelimiters:
47
+ "%": "()"
48
+ "%i": "()"
49
+ "%q": "()"
50
+ "%Q": "()"
51
+ "%r": "{}"
52
+ "%s": "()"
53
+ "%w": "()"
54
+ "%W": "()"
55
+ "%x": "()"
56
+ Style/PredicateName:
57
+ Description: Check the names of predicate methods.
58
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#bool-methods-qmark
59
+ Enabled: true
60
+ NamePrefix:
61
+ - is_
62
+ - has_
63
+ - have_
64
+ NamePrefixBlacklist:
65
+ - is_
66
+ Exclude:
67
+ - spec/**/*
68
+ Style/RaiseArgs:
69
+ Description: Checks the arguments passed to raise/fail.
70
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#exception-class-messages
71
+ Enabled: false
72
+ EnforcedStyle: exploded
73
+ SupportedStyles:
74
+ - compact
75
+ - exploded
76
+ Style/SignalException:
77
+ Description: Checks for proper usage of fail and raise.
78
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#fail-method
79
+ Enabled: false
80
+ EnforcedStyle: semantic
81
+ SupportedStyles:
82
+ - only_raise
83
+ - only_fail
84
+ - semantic
85
+ Style/SingleLineBlockParams:
86
+ Description: Enforces the names of some block params.
87
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#reduce-blocks
88
+ Enabled: false
89
+ Methods:
90
+ - reduce:
91
+ - a
92
+ - e
93
+ - inject:
94
+ - a
95
+ - e
96
+ Style/SingleLineMethods:
97
+ Description: Avoid single-line methods.
98
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-single-line-methods
99
+ Enabled: false
100
+ AllowIfMethodIsEmpty: true
101
+ Style/StringLiterals:
102
+ Description: Checks if uses of quotes match the configured preference.
103
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#consistent-string-literals
104
+ Enabled: true
105
+ EnforcedStyle: double_quotes
106
+ SupportedStyles:
107
+ - single_quotes
108
+ - double_quotes
109
+ Style/StringLiteralsInInterpolation:
110
+ Description: Checks if uses of quotes inside expressions in interpolated strings
111
+ match the configured preference.
112
+ Enabled: true
113
+ EnforcedStyle: single_quotes
114
+ SupportedStyles:
115
+ - single_quotes
116
+ - double_quotes
117
+ Style/TrailingCommaInLiteral:
118
+ Description: Checks for trailing comma in parameter lists and literals.
119
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
120
+ Enabled: false
121
+ EnforcedStyleForMultiline: no_comma
122
+ SupportedStyles:
123
+ - comma
124
+ - no_comma
125
+ Style/TrailingCommaInArguments:
126
+ Description: Checks for trailing comma in parameter lists and literals.
127
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-trailing-array-commas
128
+ Enabled: false
129
+ EnforcedStyleForMultiline: no_comma
130
+ SupportedStyles:
131
+ - comma
132
+ - no_comma
133
+ Metrics/AbcSize:
134
+ Description: A calculated magnitude based on number of assignments, branches, and
135
+ conditions.
136
+ Enabled: false
137
+ Max: 15
138
+ Metrics/ClassLength:
139
+ Description: Avoid classes longer than 100 lines of code.
140
+ Enabled: false
141
+ CountComments: false
142
+ Max: 100
143
+ Metrics/ModuleLength:
144
+ CountComments: false
145
+ Max: 100
146
+ Description: Avoid modules longer than 100 lines of code.
147
+ Enabled: false
148
+ Metrics/CyclomaticComplexity:
149
+ Description: A complexity metric that is strongly correlated to the number of test
150
+ cases needed to validate a method.
151
+ Enabled: false
152
+ Max: 6
153
+ Metrics/MethodLength:
154
+ Description: Avoid methods longer than 10 lines of code.
155
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
156
+ Enabled: false
157
+ CountComments: false
158
+ Max: 10
159
+ Metrics/ParameterLists:
160
+ Description: Avoid parameter lists longer than three or four parameters.
161
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#too-many-params
162
+ Enabled: false
163
+ Max: 5
164
+ CountKeywordArgs: true
165
+ Metrics/PerceivedComplexity:
166
+ Description: A complexity metric geared towards measuring complexity for a human
167
+ reader.
168
+ Enabled: false
169
+ Max: 7
170
+ Lint/AssignmentInCondition:
171
+ Description: Don't use assignment in conditions.
172
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#safe-assignment-in-condition
173
+ Enabled: false
174
+ AllowSafeAssignment: true
175
+ Style/InlineComment:
176
+ Description: Avoid inline comments.
177
+ Enabled: false
178
+ Style/AccessorMethodName:
179
+ Description: Check the naming of accessor methods for get_/set_.
180
+ Enabled: false
181
+ Style/Alias:
182
+ Description: Use alias_method instead of alias.
183
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#alias-method
184
+ Enabled: false
185
+ Style/Documentation:
186
+ Description: Document classes and non-namespace modules.
187
+ Enabled: false
188
+ Style/DoubleNegation:
189
+ Description: Checks for uses of double negation (!!).
190
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-bang-bang
191
+ Enabled: false
192
+ Style/EachWithObject:
193
+ Description: Prefer `each_with_object` over `inject` or `reduce`.
194
+ Enabled: false
195
+ Style/EmptyLiteral:
196
+ Description: Prefer literals to Array.new/Hash.new/String.new.
197
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#literal-array-hash
198
+ Enabled: false
199
+ Style/ModuleFunction:
200
+ Description: Checks for usage of `extend self` in modules.
201
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#module-function
202
+ Enabled: false
203
+ Style/OneLineConditional:
204
+ Description: Favor the ternary operator(?:) over if/then/else/end constructs.
205
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#ternary-operator
206
+ Enabled: false
207
+ Style/PerlBackrefs:
208
+ Description: Avoid Perl-style regex back references.
209
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-perl-regexp-last-matchers
210
+ Enabled: false
211
+ Style/Send:
212
+ Description: Prefer `Object#__send__` or `Object#public_send` to `send`, as `send`
213
+ may overlap with existing methods.
214
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#prefer-public-send
215
+ Enabled: false
216
+ Style/SpecialGlobalVars:
217
+ Description: Avoid Perl-style global variables.
218
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#no-cryptic-perlisms
219
+ Enabled: false
220
+ Style/VariableInterpolation:
221
+ Description: Don't interpolate global, instance and class variables directly in
222
+ strings.
223
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#curlies-interpolate
224
+ Enabled: false
225
+ Style/WhenThen:
226
+ Description: Use when x then ... for one-line cases.
227
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#one-line-cases
228
+ Enabled: false
229
+ Lint/EachWithObjectArgument:
230
+ Description: Check for immutable argument given to each_with_object.
231
+ Enabled: true
232
+ Lint/HandleExceptions:
233
+ Description: Don't suppress exception.
234
+ StyleGuide: https://github.com/bbatsov/ruby-style-guide#dont-hide-exceptions
235
+ Enabled: false
236
+ Lint/LiteralInCondition:
237
+ Description: Checks of literals used in conditions.
238
+ Enabled: false
239
+ Lint/LiteralInInterpolation:
240
+ Description: Checks for literals used in interpolation.
241
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
4
+ before_install: gem install bundler -v 1.11.2
5
+ script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+ gem "simplecov", require: false, group: :test
3
+ gem "sqlite3"
4
+ gem "codeclimate-test-reporter", group: :test, require: nil
5
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 TODO: Write your name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,172 @@
1
+ [![Build Status](https://travis-ci.org/andela-oosiname/mgt.svg?branch=master)](https://travis-ci.org/andela-oosiname/mgt)
2
+ [![Code Climate](https://codeclimate.com/github/andela-oosiname/mgt/badges/gpa.svg)](https://codeclimate.com/github/andela-oosiname/mgt)
3
+ [![Coverage Status](https://coveralls.io/repos/github/andela-oosiname/mgt/badge.svg?branch=master)](https://coveralls.io/github/andela-oosiname/mgt?branch=master)
4
+
5
+
6
+ # Mgt
7
+
8
+ Mgt is a MVC mini-framework, modeled after rails. Like Rails, Mgt is built using Ruby. The framework also comes with a minified ORM.
9
+
10
+ Mgt is ligthweight and hence fit for simple and quick applications. It makes available some of the great features of rails.
11
+
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ gem 'mgt'
19
+ ```
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install mgt
28
+
29
+ ## Usage
30
+
31
+ When creating a new Mgt app, a few things need to be setup and a few rules adhered to. Mgt basically follows the same folder structure as a typical rails app with all of the model, view and controller code packed inside of an app folder, configuration based code placed inside a config folder and the main database file in a db folder.
32
+
33
+ View a sample app built using mgt framework [Here](https://github.com/andela-oosiname/neski)
34
+
35
+ ## Key Features
36
+
37
+ ### Routing
38
+ Routing with Mgt deals with directing requests to the appropriate controllers. A sample route file is:
39
+
40
+ mgt supports GET, DELETE, PATCH, POST, PUT requests.
41
+
42
+ ```ruby
43
+ TodoApplication.routes.draw do
44
+ get "/users", to: "users#index"
45
+ get "/users/new", to: "users#new"
46
+ post "/users", to: "users#create"
47
+ get "/users/:id", to: "users#show"
48
+ get "/users/:id/edit", to: "users#edit"
49
+ patch "/users/:id", to: "users#update"
50
+ put "/users/:id", to: "users#update"
51
+ delete "/users/:id", to: "users#destroy"
52
+ end
53
+ ```
54
+
55
+ ### Models
56
+ All models to be used with the Hemp framework are to inherit from the ActiveRecord class provided by Mgt, in order to access the rich ORM functionalities provided. The ActiveRecord class acts as an interface between the model class and its database representation. A sample model file is provided below:
57
+
58
+ ```ruby
59
+ class Fellow < Hemp::BaseRecord
60
+ table :users
61
+ property :id, type: :integer, primary_key: true
62
+ property :first_name, type: :text, nullable: false
63
+ property :email, type: :boolean, nullable: false
64
+
65
+ create_table
66
+ end
67
+ ```
68
+ The `table` method provided stores the table name used while creating the table record in the database.
69
+
70
+ The `property` method is provided to declare table columns, and their attributes. The first argument to `property` is the column name, while subsequent hash arguments are used to provide information about attributes.
71
+
72
+ The `type` argument represents the data type of the column. Supported data types by Hemp are:
73
+
74
+ * integer (for numeric values)
75
+ * boolean (for boolean values [true or false])
76
+ * text (for alphanumeric values)
77
+
78
+ The `primary_key` argument is used to specify that the column should be used as the primary key of the table. If this is an integer, the value is auto-incremented by the database.
79
+
80
+ The `nullable` argument is used to specify whether a column should have null values, or not.
81
+
82
+ While creating models, the id property declaration is optional. If this is is not provided, the Hemp ORM adds it automatically, and sets it as the primary key. Thus, it should only be set if you'd like to use a different type as the primary key.
83
+
84
+ On passing in the table name, and its properties, a call should be made to the `create_table` method to persist the model to database by creating the table.
85
+
86
+
87
+ ### Controllers
88
+ Controllers are key to the MVC structure, as they handle receiving requests, interacting with the database, and providing responses. Controllers are placed in the controllers folder, which is nested in the app folder.
89
+
90
+ All controllers should inherit from the BaseController class provided by Hemp to inherit methods which simplify accessing request parameters and returning responses by rendering views.
91
+
92
+ A sample structure for a controller file is:
93
+
94
+ ```ruby
95
+ class UsersController < Mgt::BaseController
96
+ def index
97
+ @users = User.all
98
+ end
99
+
100
+ def new
101
+ end
102
+
103
+ def show
104
+ fellow
105
+ render :show_full
106
+ end
107
+
108
+ def destroy
109
+ fellow.destroy
110
+ redirect_to "/"
111
+ end
112
+ end
113
+ ```
114
+
115
+ Instance variables set by the controllers are passed to the routes while rendering responses.
116
+
117
+ Explicitly calling `render` to render template files is optional. If it's not called by the controller action, then it's done automatically by the framework with an argument that's the same name as the action. Thus, you can decide to call `render` explicitly when you want to render a view with a name different from the action.
118
+
119
+
120
+ ### Views
121
+ Currently, view templates are handled through the Tilt gem, with the Erubis template engine. See https://github.com/rtomayko/tilt for more details.
122
+
123
+ View templates are mapped to controller actions and must assume the same nomenclature as their respective actions.Erbuis is used as the templating engine and files which are views are required to have the .erb file extension after the .html extension. Views are placed inside the `app/views` folder. A view to be rendered for the new action in the UsersController for example is saved as `new.html.erb` in the users folder, nested in the views folder.
124
+
125
+ ### External Dependencies
126
+ The Hemp framework has a few dependencies. These are listed below, with links to source pages for each.
127
+
128
+ * sqlite3 - https://github.com/sparklemotion/sqlite3-ruby
129
+ * erubis - https://rubygems.org/gems/erubis
130
+ * bundler - https://github.com/bundler/bundler
131
+ * rake - https://github.com/ruby/rake
132
+ * rack - https://github.com/rack/rack
133
+ * rack-test - https://github.com/brynary/rack-test
134
+ * rspec - https://github.com/rspec/rspec
135
+ * tilt - https://github.com/rtomayko/tilt
136
+
137
+ ## Running the tests
138
+
139
+ Test files are placed inside the spec folder and have been split into two sub folders, one for unit tests and the other for integration tests. You can run the tests from your command line client by typing `rspec spec`
140
+
141
+ ## Development
142
+
143
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
144
+
145
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
146
+
147
+ Limitations
148
+
149
+ This version of the gem does not
150
+
151
+ support model relationships.
152
+ implement callbacks.
153
+ support migration generation.
154
+ generate a schema.
155
+
156
+ ## Contributing
157
+
158
+ To contribute to this work:
159
+
160
+ 1. Fork it ( https://github.com/[andela-oosiname]/mgt )
161
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
162
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
163
+ 4. Push to the branch (`git push origin my-new-feature`)
164
+ 5. Create a new Pull Request
165
+ 6. Wait
166
+
167
+
168
+
169
+ ## License
170
+
171
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
172
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task default: :spec
data/app.db ADDED
Binary file
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "mgt"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,47 @@
1
+ require "tilt"
2
+
3
+ module Mgt
4
+ class BaseController
5
+ attr_reader :request
6
+
7
+ def params
8
+ request.params
9
+ end
10
+
11
+ def response(body, status = 200, header = {})
12
+ @response = Rack::Response.new(body, status, header)
13
+ end
14
+
15
+ def get_response
16
+ @response
17
+ end
18
+
19
+ def render(*args)
20
+ response(render_template(*args))
21
+ end
22
+
23
+ def render_template(view_name, locals = {})
24
+ template = Tilt::ERBTemplate.new(
25
+ File.join(APP_ROOT, "app", "views",
26
+ controller_name, "#{view_name}.html.erb"))
27
+ template.render(self, locals.merge(get_instance_variables))
28
+ end
29
+
30
+ def redirect_to(url)
31
+ @response = Rack::Response.new({}, 302, "location" => url)
32
+ end
33
+
34
+ def get_instance_variables
35
+ vars = {}
36
+ instance_variables.each do |var|
37
+ key = var.to_s.delete("@").to_sym
38
+ vars[key] = instance_variable_get(var)
39
+ end
40
+ vars
41
+ end
42
+
43
+ def controller_name
44
+ self.class.to_s.gsub(/Controller$/, "").to_snake_case
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,6 @@
1
+ class Object
2
+ def self.const_missing(const)
3
+ require const.to_s.to_snake_case
4
+ Object.const_get(const)
5
+ end
6
+ end
data/lib/mgt/util.rb ADDED
@@ -0,0 +1,33 @@
1
+ class String
2
+ def to_snake_case
3
+ gsub!("::", "/")
4
+ gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
5
+ gsub!(/([a-z\d])([A-Z])/, '\1_\2')
6
+ tr!("-", "_")
7
+ downcase!
8
+ self
9
+ end
10
+
11
+ def to_camel_case
12
+ return self if self !~ /_/ && self =~ /[A-Z]+.*/
13
+ split("_").map(&:capitalize).join
14
+ end
15
+
16
+ def to_constant
17
+ Object.const_get(self)
18
+ end
19
+
20
+ def to_plural
21
+ gsub!(/([^aeiouy]|qu)y$/i, '\1ies')
22
+ gsub!(/(ss|z|ch|sh|x)$/i, '\1es')
23
+ gsub!(/(is)$/i, "es")
24
+ gsub!(/(f|fe)$/i, "ves")
25
+ gsub!(/(ex|ix)$/i, "ices")
26
+ gsub!(/(a)$/i, "ae")
27
+ gsub!(/(um|on)$/i, "a")
28
+ gsub!(/(us)$/i, "i")
29
+ gsub!(/(eau)$/i, "eaux")
30
+ gsub!(/([^saeix])$/i, '\1s')
31
+ self
32
+ end
33
+ end
@@ -0,0 +1,3 @@
1
+ module Mgt
2
+ VERSION = "0.1.0".freeze
3
+ end
data/lib/mgt.rb ADDED
@@ -0,0 +1,35 @@
1
+ require "mgt/version"
2
+ require "mgt/util"
3
+ require "mgt/dependencies"
4
+ require "mgt/base_controller"
5
+ require "routing/router"
6
+ require "routing/route"
7
+ require "routing/mapper"
8
+ require "orm/active_record"
9
+ require "orm/database"
10
+ require "orm/query_generator"
11
+
12
+ module Mgt
13
+ class Application
14
+ attr_reader :routes
15
+
16
+ def initialize
17
+ @routes = Routing::Router.new
18
+ end
19
+
20
+ def call(env)
21
+ @request = Rack::Request.new(env)
22
+ route = mapper.map_to_route(@request)
23
+
24
+ if route
25
+ route.dispatch
26
+ else
27
+ [404, {}, ["Page not found"]]
28
+ end
29
+ end
30
+
31
+ def mapper
32
+ @mapper ||= Routing::Mapper.new(routes.endpoints)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,104 @@
1
+ require "sqlite3"
2
+
3
+ module Mgt
4
+ class ActiveRecord
5
+ def self.table(table_name)
6
+ @table = table_name
7
+ end
8
+
9
+ def self.table_name
10
+ @table
11
+ end
12
+
13
+ def self.attribute(column_name, args)
14
+ @attributes ||= {}
15
+ @attributes[column_name] = args
16
+ end
17
+
18
+ def self.create_table
19
+ all_attributes = []
20
+ @attributes.each do |key, value|
21
+ attributes ||= []
22
+ attributes << key.to_s
23
+ value.each do |name, type|
24
+ attributes << send("#{name.downcase}_query", type)
25
+ end
26
+ all_attributes << attributes.join(" ")
27
+ end
28
+ query = "CREATE TABLE
29
+ IF NOT EXISTS #{@table} (#{all_attributes.join(', ')})"
30
+ Database.execute(query)
31
+ make_methods
32
+ end
33
+
34
+ def self.make_methods
35
+ mtds = @attributes.keys.map(&:to_sym)
36
+ mtds.each { |mtd| attr_accessor mtd }
37
+ end
38
+
39
+ def self.primary_key_query(value = false)
40
+ "PRIMARY KEY AUTOINCREMENT" if value
41
+ end
42
+
43
+ def self.nullable_query(value = true)
44
+ "NOT NULL" unless value
45
+ end
46
+
47
+ def self.type_query(value)
48
+ value.to_s
49
+ end
50
+
51
+ def self.attributes_keys
52
+ @attributes.keys
53
+ end
54
+
55
+ def self.map_object(row)
56
+ model_name = new
57
+ @attributes.each_key.with_index do |value, index|
58
+ model_name.send("#{value}=", row[index])
59
+ end
60
+ model_name
61
+ end
62
+
63
+ def get_columns
64
+ columns = self.class.attributes_keys
65
+ columns.delete(:id)
66
+ columns.join(",")
67
+ end
68
+
69
+ def get_values
70
+ attributes = self.class.attributes_keys
71
+ attributes.delete(:id)
72
+ attributes.map { |method| send(method) }
73
+ end
74
+
75
+ def new_record_value
76
+ get_values
77
+ end
78
+
79
+ def update_records
80
+ get_values << send(:id)
81
+ end
82
+
83
+ def update_values(params)
84
+ params.values << id
85
+ end
86
+
87
+ def new_record_placeholders
88
+ attributes = self.class.attributes_keys
89
+ (["?"] * (attributes.size - 1)).join(",")
90
+ end
91
+
92
+ def update_values_placeholders(params)
93
+ columns = params.keys
94
+ columns.delete(:id)
95
+ columns.map { |col| "#{col}=?" }.join(",")
96
+ end
97
+
98
+ def update_records_placeholders
99
+ columns = self.class.attributes_keys
100
+ columns.delete(:id)
101
+ columns.map { |col| "#{col}=?" }.join(",")
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,16 @@
1
+ module Mgt
2
+ class Database
3
+ class << self
4
+ attr_accessor :db
5
+ def connect
6
+ @db = SQLite3::Database.new File.join "app.db"
7
+ end
8
+
9
+ def execute(query, args = nil)
10
+ @db ||= connect
11
+ return @db.execute(query, args) if args
12
+ @db.execute(query)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,75 @@
1
+ module Mgt
2
+ class ActiveRecord
3
+ def self.find_by(finder)
4
+ key = finder.keys[0].to_s
5
+ value = finder.values[0].to_s
6
+ row = Database.execute("SELECT #{attributes_keys.join(',')}
7
+ FROM #{@table} WHERE #{key} = ?", value).first
8
+ map_object(row)
9
+ end
10
+
11
+ def self.all
12
+ data = Database.execute "SELECT #{attributes_keys.join(',')}
13
+ FROM #{@table} ORDER BY id DESC"
14
+ data.map do |row|
15
+ map_object(row)
16
+ end
17
+ end
18
+
19
+ def self.where(query_pattern, value)
20
+ data = Database.execute "SELECT #{attributes_keys.join(',')} FROM
21
+ #{@table} WHERE #{query_pattern}", value
22
+ data.map do |row|
23
+ map_object(row)
24
+ end
25
+ end
26
+
27
+ def self.last
28
+ query = "SELECT * FROM #{@table} ORDER BY id DESC LIMIT 1"
29
+ row = (Database.execute query).first
30
+ map_object(row)
31
+ end
32
+
33
+ def self.first
34
+ query = "SELECT * FROM #{@table} ORDER BY id LIMIT 1"
35
+ row = (Database.execute query).first
36
+ map_object(row)
37
+ end
38
+
39
+ def self.find(id)
40
+ row = Database.execute("SELECT #{attributes_keys.join(',')}
41
+ FROM #{@table} WHERE id = ?", id).first
42
+ map_object(row)
43
+ end
44
+
45
+ def self.destroy(id)
46
+ Database.execute "DELETE FROM #{table_name} WHERE id = ?", id
47
+ end
48
+
49
+ def save
50
+ table_name = self.class.table_name
51
+ if id
52
+ Database.execute "UPDATE #{table_name} SET
53
+ #{update_records_placeholders} WHERE id = ?", update_records
54
+ else
55
+ Database.execute "INSERT INTO #{table_name} (#{get_columns})
56
+ VALUES (#{new_record_placeholders})", new_record_value
57
+ end
58
+ end
59
+
60
+ def update(params)
61
+ table_name = self.class.table_name
62
+ Database.execute "UPDATE #{table_name} SET
63
+ #{update_values_placeholders(params)} WHERE id=?", update_values(params)
64
+ end
65
+
66
+ def destroy
67
+ table_name = self.class.table_name
68
+ Database.execute "DELETE FROM #{table_name} WHERE id = ?", id
69
+ end
70
+
71
+ def self.destroy_all
72
+ Database.execute "DELETE FROM #{@table}"
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,30 @@
1
+ module Mgt
2
+ module Routing
3
+ class Mapper
4
+ def initialize(endpoints)
5
+ @endpoints = endpoints
6
+ end
7
+
8
+ def map_to_route(request)
9
+ @request = request
10
+ path = request.path_info
11
+ method = request.request_method.downcase.to_sym
12
+ result = @endpoints[method].detect do |endpoint|
13
+ match_path_with_pattern path, endpoint
14
+ end
15
+ return Route.new(@request, result[:klass_and_method]) if result
16
+ end
17
+
18
+ def match_path_with_pattern(path, endpoint)
19
+ regexp, placeholders = endpoint[:pattern]
20
+ if path =~ regexp
21
+ match_data = Regexp.last_match
22
+ placeholders.each do |placeholder|
23
+ @request.update_param(placeholder, match_data[placeholder])
24
+ end
25
+ true
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,23 @@
1
+ require "mgt/util"
2
+ module Mgt
3
+ module Routing
4
+ class Route
5
+ attr_reader :controller_name, :request, :action
6
+ def initialize(request, class_and_method)
7
+ @controller_name, @action = class_and_method
8
+ @request = request
9
+ end
10
+
11
+ def controller_class
12
+ controller_name.to_constant
13
+ end
14
+
15
+ def dispatch
16
+ controller = controller_class.new(request)
17
+ controller.send(action)
18
+ controller.render(action) unless controller.get_response
19
+ controller.get_response
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,49 @@
1
+ module Mgt
2
+ module Routing
3
+ class Router
4
+ attr_accessor :endpoints
5
+ def draw(&block)
6
+ instance_eval &block
7
+ end
8
+
9
+ def root(to)
10
+ get "/", to: to
11
+ end
12
+
13
+ def endpoints
14
+ @endpoints ||= Hash.new { |hash, key| hash[key] = [] }
15
+ end
16
+
17
+ private
18
+
19
+ def pattern(path)
20
+ placeholders = []
21
+ path.gsub!(/(:\w+)/) do |match|
22
+ placeholders << match[1..-1].freeze
23
+ "(?<#{placeholders.last}>[^/?#]+)"
24
+ end
25
+ [/^#{path}$/, placeholders]
26
+ end
27
+
28
+ def controller_and_action_for(path_to)
29
+ controller_path, action = path_to.split("#")
30
+ controller = "#{controller_path.capitalize}Controller"
31
+ [controller, action.to_sym]
32
+ end
33
+
34
+ http_verbs = [:get, :post, :put, :patch, :delete]
35
+
36
+ http_verbs.each do |method_name|
37
+ define_method(method_name) do |path, to:|
38
+ path = "/#{path}" unless path[0] = "/"
39
+ klass_and_method = controller_and_action_for(to)
40
+ @route_data = { path: path,
41
+ pattern: pattern(path),
42
+ klass_and_method: klass_and_method
43
+ }
44
+ endpoints[method_name] << @route_data
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
data/mgt.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "mgt/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mgt"
8
+ spec.version = Mgt::VERSION
9
+ spec.authors = ["Olumuyiwa Osiname"]
10
+ spec.email = ["olumuyiwa.osiname@andela.com"]
11
+
12
+ spec.summary = ["A simple mvc framework"]
13
+ spec.description = ["A simple mvc rack framework"]
14
+ spec.homepage = "https://github.com/andela-oosiname/mastermind_sname"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.11"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "rspec"
25
+ spec.add_development_dependency "rack-test", "~> 0.6"
26
+ spec.add_development_dependency "coveralls"
27
+ spec.add_development_dependency "capybara"
28
+ spec.add_development_dependency "faker"
29
+
30
+ spec.add_runtime_dependency "rack"
31
+ spec.add_runtime_dependency "pry"
32
+ spec.add_runtime_dependency "tilt"
33
+ end
metadata ADDED
@@ -0,0 +1,209 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mgt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Olumuyiwa Osiname
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack-test
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coveralls
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: capybara
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: faker
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rack
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: tilt
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: '["A simple mvc rack framework"]'
154
+ email:
155
+ - olumuyiwa.osiname@andela.com
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - ".coveralls.yml"
161
+ - ".gitignore"
162
+ - ".hound.yml"
163
+ - ".rspec"
164
+ - ".rubocop.yml"
165
+ - ".travis.yml"
166
+ - Gemfile
167
+ - LICENSE.txt
168
+ - README.md
169
+ - Rakefile
170
+ - app.db
171
+ - bin/console
172
+ - bin/setup
173
+ - lib/mgt.rb
174
+ - lib/mgt/base_controller.rb
175
+ - lib/mgt/dependencies.rb
176
+ - lib/mgt/util.rb
177
+ - lib/mgt/version.rb
178
+ - lib/orm/active_record.rb
179
+ - lib/orm/database.rb
180
+ - lib/orm/query_generator.rb
181
+ - lib/routing/mapper.rb
182
+ - lib/routing/route.rb
183
+ - lib/routing/router.rb
184
+ - mgt.gemspec
185
+ homepage: https://github.com/andela-oosiname/mastermind_sname
186
+ licenses:
187
+ - MIT
188
+ metadata: {}
189
+ post_install_message:
190
+ rdoc_options: []
191
+ require_paths:
192
+ - lib
193
+ required_ruby_version: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ version: '0'
198
+ required_rubygems_version: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ requirements: []
204
+ rubyforge_project:
205
+ rubygems_version: 2.4.6
206
+ signing_key:
207
+ specification_version: 4
208
+ summary: '["A simple mvc framework"]'
209
+ test_files: []