atd 0.0.0.TEST.GITLAB1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.gitlab-ci.yml +26 -0
- data/.rubocop.yml +15 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/README.md +112 -0
- data/Rakefile +10 -0
- data/atd.gemspec +36 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/atd/builtin_class_modifications.rb +32 -0
- data/lib/atd/middleware.rb +30 -0
- data/lib/atd/routes.rb +41 -0
- data/lib/atd/version.rb +3 -0
- data/lib/atd.rb +194 -0
- metadata +188 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 55fd5c613ac662fb3807855676374824a6518643
|
4
|
+
data.tar.gz: c22fb02f2ae650c95e05443ec818584bb6aba054
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 20ada93c439759ab6bb4b15b4bb0702d082299930afb869fe4cb1fe13bc902640beb78ccd5e5ddc5edc873196b213016623ada0d3b5d284ef04925342b814548
|
7
|
+
data.tar.gz: 480cec1cef0db4daf1475ea1ed7ee7eb17ae38fab0199d91924a954c675fb42682b87d7498ccc2162e8ed34505eda724ebc1c61bfd459b2e81015d9334a2f3ea
|
data/.gitignore
ADDED
data/.gitlab-ci.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
image: ruby:2.3.1
|
2
|
+
|
3
|
+
before_script:
|
4
|
+
- ruby -v
|
5
|
+
- which ruby
|
6
|
+
- gem install bundler --no-ri --no-rdoc
|
7
|
+
- bundle install --jobs $(nproc) "${FLAGS[@]}"
|
8
|
+
|
9
|
+
test:
|
10
|
+
script:
|
11
|
+
- bundle exec rake test
|
12
|
+
|
13
|
+
pages:
|
14
|
+
only:
|
15
|
+
- master
|
16
|
+
script:
|
17
|
+
- gem install yard
|
18
|
+
- bundle exec yard
|
19
|
+
- bundle exec rake test
|
20
|
+
- mkdir public
|
21
|
+
- mv /builds/izwick-schachter/atd/coverage public/coverage
|
22
|
+
- mv /builds/izwick-schachter/atd/doc public/YARD
|
23
|
+
- ls -R -a --ignore .git
|
24
|
+
artifacts:
|
25
|
+
paths:
|
26
|
+
- public
|
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, and in the interest of
|
4
|
+
fostering an open and welcoming community, we pledge to respect all people who
|
5
|
+
contribute through reporting issues, posting feature requests, updating
|
6
|
+
documentation, submitting pull requests or patches, and other activities.
|
7
|
+
|
8
|
+
We are committed to making participation in this project a harassment-free
|
9
|
+
experience for everyone, regardless of level of experience, gender, gender
|
10
|
+
identity and expression, sexual orientation, disability, personal appearance,
|
11
|
+
body size, race, ethnicity, age, religion, or nationality.
|
12
|
+
|
13
|
+
Examples of unacceptable behavior by participants include:
|
14
|
+
|
15
|
+
* The use of sexualized language or imagery
|
16
|
+
* Personal attacks
|
17
|
+
* Trolling or insulting/derogatory comments
|
18
|
+
* Public or private harassment
|
19
|
+
* Publishing other's private information, such as physical or electronic
|
20
|
+
addresses, without explicit permission
|
21
|
+
* Other unethical or unprofessional conduct
|
22
|
+
|
23
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
24
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
25
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
26
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
27
|
+
threatening, offensive, or harmful.
|
28
|
+
|
29
|
+
By adopting this Code of Conduct, project maintainers commit themselves to
|
30
|
+
fairly and consistently applying these principles to every aspect of managing
|
31
|
+
this project. Project maintainers who do not follow or enforce the Code of
|
32
|
+
Conduct may be permanently removed from the project team.
|
33
|
+
|
34
|
+
This code of conduct applies both within project spaces and in public spaces
|
35
|
+
when an individual is representing the project or its community.
|
36
|
+
|
37
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
38
|
+
reported by contacting a project maintainer at admin@developingtechnician.com All
|
39
|
+
complaints will be reviewed and investigated and will result in a response that
|
40
|
+
is deemed necessary and appropriate to the circumstances. Maintainers are
|
41
|
+
obligated to maintain confidentiality with regard to the reporter of an
|
42
|
+
incident.
|
43
|
+
|
44
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
45
|
+
version 1.3.0, available at
|
46
|
+
[http://contributor-covenant.org/version/1/3/0/][version]
|
47
|
+
|
48
|
+
[homepage]: http://contributor-covenant.org
|
49
|
+
[version]: http://contributor-covenant.org/version/1/3/0/
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
# ATD
|
2
|
+
|
3
|
+
ATD is a new web development backend framework for Ruby. It is built on top of rack, and is meant to be small easy and light. That is why it provides a very minimalist way of writing your backend. It treats a request as a request, without splitting it based on the HTTP method.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'atd', , :git => 'git://gitlab.com/izwick-schachter/atd.git'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ git clone https://gitlab.com/izwick-schachter/atd.git
|
20
|
+
$ cd atd
|
21
|
+
$ bundle exec rake install
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### Setup
|
26
|
+
|
27
|
+
Setup is as easy as `require "atd"` at the top of whatever file you need it in
|
28
|
+
|
29
|
+
### Routing
|
30
|
+
|
31
|
+
#### Basic Routing
|
32
|
+
|
33
|
+
On the lowest level it can be used serve files or any strings when a path is requested (and optionally when a specific HTTP method is used). Here is a basic route that will serve `Hello World` when `/` is sent a HTTP request:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
request "/", "Hello World"
|
37
|
+
```
|
38
|
+
|
39
|
+
The `request` method is also alias to `req` and `r` for better code readability if you prefer. Here is how you could use the same basic routing syntax to return `Hello World` for a basic HTTP GET request to `/`:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
req.get "/", "Hello World"
|
43
|
+
```
|
44
|
+
|
45
|
+
This will only respond to HTTP GET requests, whereas the first example will respond to any HTTP request.
|
46
|
+
|
47
|
+
#### Advanced Routing
|
48
|
+
|
49
|
+
You can also add blocks to the basic routing methods to execute code when they are reached, and customize the response to the incoming request. Here is an example that will return the HTTP method used to request `/`:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
r "/" do
|
53
|
+
@http[:output] = @http[:method]
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
This example uses the `@http` variable which is provided to the route when called. You could also run some complex method created outside the route. This route is called in the same scope as any block you were to declare. Here is an example:
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
r "/", "I'm computing a complex function" do
|
61
|
+
complex_function
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
##### @http
|
66
|
+
|
67
|
+
The `@http` instance variable can be used to work with the http request the the route is parsing. Here are some ways you can use the `@http` variable:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
@http[:status_code] = 200 # By default the status code is 200. You can manipulate this.
|
71
|
+
@http[:headers] = {} # By defualt there are no headers. You can add whatever you want.
|
72
|
+
@http[:method] = env["REQUEST_METHOD"] # Writing to this does nothing. Just a way for you to see the request method.
|
73
|
+
@http[:output] # This is set to the output you give in the args for request
|
74
|
+
@http[:request] # The associated Rack::Request for the request.
|
75
|
+
```
|
76
|
+
|
77
|
+
### Apps
|
78
|
+
|
79
|
+
ATD also allows you to use different "apps". Each app is independent of the others and lives is a class with the same name as the app. A file can have any number of apps, each of which can have it's own settings, files, and routes. By default, adding routes to `main` will make them a part of the app `DefaultApp`, which will work fine if you only need one app.
|
80
|
+
|
81
|
+
#### App Creation
|
82
|
+
|
83
|
+
To create a route you can use `ATD.new("AppName")`. It is important to note that *ATD.new is not a construtor*. It simply behaves like one because you can use it to "construct" a new app. The app creation process creates a new class which you can open anywhere in your app file, with the name you pass. The name must be a string or symbol, and must be a valid class name. You must call the constructor before you begin adding routes to the class, or open the class at all.
|
84
|
+
|
85
|
+
#### App Routing
|
86
|
+
|
87
|
+
To add routes to an app, you simply must call the standard routing method inside the app class. For example, to create and add routes to an app called `Name` I would use the following code:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
ATD.new(:Name)
|
91
|
+
class Name
|
92
|
+
request "/", "Hello World"
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
### Logging
|
97
|
+
|
98
|
+
Currently there is no specified logging interface. Just use `puts` or `p` to log to `STDOUT`.
|
99
|
+
|
100
|
+
### Middleware
|
101
|
+
|
102
|
+
Middleware is currently used inside the app with the `ATD::Middleware` module. Currently use this with caution, backwards compatibility may be broken. It is for use only internally for now. For documentation, look to the comments.
|
103
|
+
|
104
|
+
## Development
|
105
|
+
|
106
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
107
|
+
|
108
|
+
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).
|
109
|
+
|
110
|
+
## Contributing
|
111
|
+
|
112
|
+
Bug reports and pull requests are welcome on GitLab at https://gitlab.com/izwick-schachter/atd/issues. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/Rakefile
ADDED
data/atd.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'atd/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "atd"
|
8
|
+
spec.version = ATD::VERSION
|
9
|
+
spec.authors = ["ACecretMaster"]
|
10
|
+
spec.email = ["izwick.schachter@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = 'The assistant technical director of your website. It does the dirty work so you can see the big picture.'
|
13
|
+
spec.homepage = "https://rubygems.org/gems/atd"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes." unless spec.respond_to?(:metadata)
|
19
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
20
|
+
|
21
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }#+"test/assets/test.html"
|
22
|
+
spec.bindir = "exe"
|
23
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
24
|
+
spec.require_paths = ["lib"]
|
25
|
+
|
26
|
+
spec.add_runtime_dependency "rack", "~> 2.0"
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
29
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
30
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
31
|
+
spec.add_development_dependency "minitest-reporters", "~> 1.1"
|
32
|
+
spec.add_development_dependency "rubocop", "~> 0"
|
33
|
+
spec.add_development_dependency "yard", "~> 0.9"
|
34
|
+
spec.add_development_dependency "rack-test", "~> 0.6"
|
35
|
+
spec.add_development_dependency "simplecov", "~> 0.12"
|
36
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "atd"
|
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,32 @@
|
|
1
|
+
# @!visibility private
|
2
|
+
class Hash
|
3
|
+
# Not only merges two hashes, but also merges the hashes that may be nested in.
|
4
|
+
#
|
5
|
+
# For example:
|
6
|
+
# {a: {b: "c"}}
|
7
|
+
# Is a nested hash
|
8
|
+
def deep_merge(second)
|
9
|
+
merger = proc do |_, v1, v2|
|
10
|
+
if v1.is_a?(Hash) && v2.is_a?(Hash) then v1.merge(v2, &merger)
|
11
|
+
elsif v1.is_a?(Array) && v2.is_a?(Array) then v1 | v2
|
12
|
+
elsif [:undefined, nil, :nil].include?(v2) then v1
|
13
|
+
else v2
|
14
|
+
end
|
15
|
+
end
|
16
|
+
merge(second.to_h, &merger)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# This method only exists for the test suite, specifically {ATDTest#test_route_creation}.
|
21
|
+
# @!visibility private
|
22
|
+
class Object
|
23
|
+
# Checks if two objects are instances of the same class and that they have the same instance variables
|
24
|
+
def same_properties_as?(other_class)
|
25
|
+
other_class.class == self.class && class_instance_variables == other_class.class_instance_variables
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns the instance variables of a class
|
29
|
+
def class_instance_variables
|
30
|
+
instance_variables.map { |var| [var, instance_variable_get(var)] }.to_h
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# All middleware must respond_to?("setup")
|
2
|
+
# To register middleware, after the class call ATD::Middleware.register(Your::Middleware)
|
3
|
+
module ATD
|
4
|
+
module Middleware
|
5
|
+
@middleware = {}
|
6
|
+
@sources = []
|
7
|
+
|
8
|
+
def self.register(source)
|
9
|
+
@sources.push source
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.run(target = nil)
|
13
|
+
return nil if @middleware[target.class].nil?
|
14
|
+
@middleware[target.class].each do |action|
|
15
|
+
action.call(target)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.create(source, target)
|
20
|
+
@middleware[target] = [] if @middleware[target].nil?
|
21
|
+
@middleware[target].push(source)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.setup(target)
|
25
|
+
# At some point, target should be used so that middleware are only setup on one target.
|
26
|
+
@sources.each(&:setup)
|
27
|
+
target
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/atd/routes.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
module ATD
|
3
|
+
module Compilation
|
4
|
+
def compile
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.precompile(route)
|
8
|
+
output = route.output
|
9
|
+
name = output
|
10
|
+
return nil if output.nil?
|
11
|
+
if output.include?(".") || output.is_a?(File)
|
12
|
+
file = File.read(File.join("./assets/#{output}")) if output.class.is_a? String
|
13
|
+
file = File.read(output) if output.is_a? File
|
14
|
+
return nil if file.nil?
|
15
|
+
unless output.is_a? File
|
16
|
+
output = output.split(".")
|
17
|
+
name = output.shift
|
18
|
+
output.each do |extension|
|
19
|
+
file = Precompiler.send(extension, file)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
route.output = file
|
23
|
+
end
|
24
|
+
name
|
25
|
+
end
|
26
|
+
|
27
|
+
module Precompiler
|
28
|
+
module_function
|
29
|
+
|
30
|
+
def html(file)
|
31
|
+
file
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.setup
|
36
|
+
ATD::Middleware.create(ATD::Compilation.method(:precompile), ATD::Route)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
ATD::Middleware.register(ATD::Compilation)
|
data/lib/atd/version.rb
ADDED
data/lib/atd.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
require_relative "atd/version"
|
2
|
+
require "rack"
|
3
|
+
require_relative "atd/builtin_class_modifications"
|
4
|
+
require_relative "atd/middleware"
|
5
|
+
require_relative "atd/routes"
|
6
|
+
|
7
|
+
# The assistant technical director of your website. It does the dirty work so you can see the big picture.
|
8
|
+
module ATD
|
9
|
+
# Creates a new ATD App based on the template of {ATD::App}.
|
10
|
+
# @return [ATD::App]
|
11
|
+
# @param [Symbol] name The name of the new app and new class generated.
|
12
|
+
def new(name)
|
13
|
+
app = Class.new(App)
|
14
|
+
Object.const_set(name.to_sym, app)
|
15
|
+
app
|
16
|
+
end
|
17
|
+
|
18
|
+
# So called because each instance stores a route, and will be called if that route is reached.
|
19
|
+
# A route for the purposes of {ATD} is a parser that ***will be fed env in {ATD::App#call the rack app}***.
|
20
|
+
class Route
|
21
|
+
attr_accessor :args, :method, :block, :path, :output, :app
|
22
|
+
|
23
|
+
# The first two arguments must me the path and the output. ***Until this code is updated it is impossible to specify output in a block***
|
24
|
+
def initialize(*args, &block)
|
25
|
+
args -= [nil]
|
26
|
+
args.reject!(&:empty?)
|
27
|
+
@block = block
|
28
|
+
@path = args.shift
|
29
|
+
@output = args.shift
|
30
|
+
@args = args
|
31
|
+
@app = :DefaultApp
|
32
|
+
end
|
33
|
+
|
34
|
+
# This works differently from a standard setter because is makes sure that a {Route} can belong to only one {App}.
|
35
|
+
def app=(app_name)
|
36
|
+
old_app = Object.const_get(@app)
|
37
|
+
new_app = Object.const_get(app_name.to_sym)
|
38
|
+
old_app.routes -= self if old_app.routes.is_a?(Array) && old_app.routes.include?(self)
|
39
|
+
new_app.routes.nil? ? new_app.routes = Array(self) : new_app.routes += Array(self)
|
40
|
+
@app = app_name
|
41
|
+
end
|
42
|
+
|
43
|
+
# @!method get(path = nil,*args)
|
44
|
+
# @param [String] path The path at which the route should receive from.
|
45
|
+
# @return ATD::Route
|
46
|
+
# Sets route to receive a get request to path and execute the block provided (if one is provided)
|
47
|
+
|
48
|
+
# @!method post(path = nil,*args)
|
49
|
+
# @param [String] path The path at which the route should receive from.
|
50
|
+
# @return ATD::Route
|
51
|
+
# Sets route to receive a post request to path and execute the block provided (if one is provided)
|
52
|
+
|
53
|
+
# @!method put(path = nil,*args)
|
54
|
+
# @param [String] path The path at which the route should receive from.
|
55
|
+
# @return ATD::Route
|
56
|
+
# Sets route to receive a put request to path and execute the block provided (if one is provided)
|
57
|
+
|
58
|
+
# @!method patch(path = nil,*args)
|
59
|
+
# @param [String] path The path at which the route should receive from.
|
60
|
+
# @return ATD::Route
|
61
|
+
# Sets route to receive a patch request to path and execute the block provided (if one is provided)
|
62
|
+
|
63
|
+
# @!method delete(path = nil,*args)
|
64
|
+
# @param [String] path The path at which the route should receive from.
|
65
|
+
# @return ATD::Route
|
66
|
+
# Sets route to receive a delete request to path and execute the block provided (if one is provided)
|
67
|
+
|
68
|
+
[:get, :post, :put, :delete, :patch].each do |method|
|
69
|
+
define_method(method) do |path = nil, *args, &block|
|
70
|
+
@block = block
|
71
|
+
@method = method
|
72
|
+
@output = args.shift if @output.nil?
|
73
|
+
@path = path if @path.nil?
|
74
|
+
@args = @args.concat(args) - [nil] unless args.nil?
|
75
|
+
self
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Converts an instance of {ATD::Route} into it's Hash representation.
|
80
|
+
# The format for the Hash is listed {ATD::App#initialize here}
|
81
|
+
# @api private
|
82
|
+
def to_h
|
83
|
+
routes = {}
|
84
|
+
routes[@path] = {}
|
85
|
+
routes[@path][@method] = {}
|
86
|
+
routes[@path][@method] = {
|
87
|
+
output: @output,
|
88
|
+
block: @block,
|
89
|
+
args: @args,
|
90
|
+
route: self
|
91
|
+
}
|
92
|
+
routes
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# A template {App} that all Apps extend. When a new App is created with {ATD.new ATD.new} it extends this class.
|
97
|
+
class App
|
98
|
+
class << self
|
99
|
+
attr_accessor :routes # An array of instances of {ATD::Route} that belong to this {App}.
|
100
|
+
attr_accessor :http
|
101
|
+
|
102
|
+
# Generates an instance of {ATD::Route}.
|
103
|
+
# Passes all arguments and the block to {Route.new the constructor} and sets the app where it was called from.
|
104
|
+
def request(*args, &block)
|
105
|
+
route = ATD::Route.new(*args, &block)
|
106
|
+
route.app = (self == Object || self == ATD::App ? :DefaultApp : name.to_sym)
|
107
|
+
route
|
108
|
+
end
|
109
|
+
alias req request
|
110
|
+
alias r request
|
111
|
+
end
|
112
|
+
|
113
|
+
# Sets up the @routes instance variable from the {.routes} class instance variable.
|
114
|
+
# Can be passed an array of instances of {ATD::Route} and they will be added to @routes.
|
115
|
+
# The format of the new @routes instance variable is:
|
116
|
+
# {"/" => {
|
117
|
+
# get: {output: "Hello World",
|
118
|
+
# block: Proc.new},
|
119
|
+
# post: {output: "Hello World",
|
120
|
+
# block: Proc.new}
|
121
|
+
# },
|
122
|
+
# "/hello" => {
|
123
|
+
# get: {output: "Hello World",
|
124
|
+
# block: Proc.new},
|
125
|
+
# post: {output: "Hello World",
|
126
|
+
# block: Proc.new
|
127
|
+
# }
|
128
|
+
# }
|
129
|
+
# }
|
130
|
+
# @param [Array] routes An array of instances of {ATD::Route}.
|
131
|
+
def initialize(routes = [])
|
132
|
+
Middleware.setup(ATD::Route)
|
133
|
+
routes.each do |route|
|
134
|
+
Middleware.run(route)
|
135
|
+
end
|
136
|
+
routes += self.class.routes
|
137
|
+
@routes = {}
|
138
|
+
routes.each do |route|
|
139
|
+
Middleware.run(route)
|
140
|
+
@routes = @routes.to_h.deep_merge(route.to_h)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Starts the rack server
|
145
|
+
# @param [Class] server The server that you would like to use.
|
146
|
+
# @param [Fixnum] port The port you would like the server to run on.
|
147
|
+
def start(server = WEBrick, port = 3150)
|
148
|
+
Rack::Server.start(app: self, server: server, Port: port)
|
149
|
+
end
|
150
|
+
|
151
|
+
# This is the method which responds to .call, as the Rack spec requires.
|
152
|
+
# It will return status code 200 and whatever output corresponds the that route if it exists, and if it doesn't
|
153
|
+
# it will return status code 404 and the message "Error 404"
|
154
|
+
def call(env)
|
155
|
+
route = route(env)
|
156
|
+
return error(404) if route.nil?
|
157
|
+
return [route[:status_code].to_i, Hash(route[:headers]), Array(route[:output])] if route[:block].nil?
|
158
|
+
http output: route[:output], request: Rack::Request.new(env), method: env["REQUEST_METHOD"]
|
159
|
+
run_block(route[:block])
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def route(env)
|
165
|
+
return nil if @routes[env["PATH_INFO"]].nil?
|
166
|
+
return @routes[env["PATH_INFO"]][nil] unless @routes[env["PATH_INFO"]][nil].nil?
|
167
|
+
@routes[env["PATH_INFO"]][env["REQUEST_METHOD"].downcase.to_sym]
|
168
|
+
end
|
169
|
+
|
170
|
+
def run_block(block)
|
171
|
+
block.call
|
172
|
+
Middleware.run(self)
|
173
|
+
[self.class.http[:status_code].to_i, Hash(self.class.http[:headers]), Array(self.class.http[:output])]
|
174
|
+
end
|
175
|
+
|
176
|
+
def http(additional_params)
|
177
|
+
self.class.http = { status_code: 200, headers: {} }.merge(additional_params)
|
178
|
+
end
|
179
|
+
|
180
|
+
def error(number)
|
181
|
+
[number, {}, ["Error #{number}"]]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
module_function :new
|
185
|
+
end
|
186
|
+
|
187
|
+
# @return [ATD::Route]
|
188
|
+
def request(*args, &block)
|
189
|
+
ATD::App.request(args, block)
|
190
|
+
end
|
191
|
+
alias req request
|
192
|
+
alias r request
|
193
|
+
|
194
|
+
ATD.new("DefaultApp")
|
metadata
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: atd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0.TEST.GITLAB1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- ACecretMaster
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.12'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.12'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest-reporters
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
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: yard
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.9'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.9'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rack-test
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.6'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.6'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: simplecov
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.12'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.12'
|
139
|
+
description:
|
140
|
+
email:
|
141
|
+
- izwick.schachter@gmail.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".gitignore"
|
147
|
+
- ".gitlab-ci.yml"
|
148
|
+
- ".rubocop.yml"
|
149
|
+
- ".travis.yml"
|
150
|
+
- CODE_OF_CONDUCT.md
|
151
|
+
- Gemfile
|
152
|
+
- README.md
|
153
|
+
- Rakefile
|
154
|
+
- atd.gemspec
|
155
|
+
- bin/console
|
156
|
+
- bin/setup
|
157
|
+
- lib/atd.rb
|
158
|
+
- lib/atd/builtin_class_modifications.rb
|
159
|
+
- lib/atd/middleware.rb
|
160
|
+
- lib/atd/routes.rb
|
161
|
+
- lib/atd/version.rb
|
162
|
+
homepage: https://rubygems.org/gems/atd
|
163
|
+
licenses:
|
164
|
+
- MIT
|
165
|
+
metadata:
|
166
|
+
allowed_push_host: https://rubygems.org
|
167
|
+
post_install_message:
|
168
|
+
rdoc_options: []
|
169
|
+
require_paths:
|
170
|
+
- lib
|
171
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 1.3.1
|
181
|
+
requirements: []
|
182
|
+
rubyforge_project:
|
183
|
+
rubygems_version: 2.5.1
|
184
|
+
signing_key:
|
185
|
+
specification_version: 4
|
186
|
+
summary: The assistant technical director of your website. It does the dirty work
|
187
|
+
so you can see the big picture.
|
188
|
+
test_files: []
|