atd 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 58bc7fc139c91e5ac91f51cf29e1c8638484bef7
4
- data.tar.gz: a2956310bdbe71f6abb96cc840fad813815e0d5a
3
+ metadata.gz: e4b052a0c402077fa55a5c00e96db96c1963430a
4
+ data.tar.gz: 487ab2f6ce28280effbf0a1faff0d9b9959cd389
5
5
  SHA512:
6
- metadata.gz: dce06c37ffcd1b2265052fc3b8149003f7a9e8e05e478f6e8a887496b34a3d0877d90c37040db783f226b3e3c28edd8b341b256e6022d188fbd173193588df17
7
- data.tar.gz: d92f10cdc008a8f848178f36be680831786f738dfa759325d39bb24b4b7603cb5a64a5fb5072c2194304731cc3dddb132171c57cd925571f2e0c9482c8d48a84
6
+ metadata.gz: db837886aa4f434403f51f8f1d6cf796c6cfd0cc1e4ef095c336b967a0c5d22dc15f6d93e20afe7e3f8f897da6f7659d0e13be366a5fb4b73730c886f4996640
7
+ data.tar.gz: 4075dd51b6e64f6977c13b6d6d684ab66c5abca0c992b5efa0752c07b251835bd78e13984716c1fb7c3b1dbfee7cd90a04b851813da7b291a4b1fb53e222e7be
data/.gitignore CHANGED
@@ -7,7 +7,8 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
  .DS_Store
10
- /.idea/
10
+ .idea
11
11
  coverage
12
12
  /*.gem
13
13
  /updated_README.md
14
+ .dev-rubocop.yml
data/.gitlab-ci.yml CHANGED
@@ -10,6 +10,10 @@ test:
10
10
  script:
11
11
  - bundle exec rake test
12
12
 
13
+ rubocop:
14
+ script:
15
+ - rubocop
16
+
13
17
  pages:
14
18
  only:
15
19
  - master
data/.rubocop.yml CHANGED
@@ -12,4 +12,16 @@ Style/ParallelAssignment:
12
12
  Enabled: false
13
13
 
14
14
  Style/Documentation:
15
+ Enabled: false
16
+
17
+ Style/ModuleFunction:
18
+ Enabled: false
19
+
20
+ Style/ClassAndModuleChildren:
21
+ Enabled: false
22
+
23
+ Metrics:
24
+ Enabled: false
25
+
26
+ Lint/UnifiedInteger:
15
27
  Enabled: false
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --exclude lib/extensions/
data/CHANGELOG CHANGED
@@ -1,3 +1,13 @@
1
+ Current Repo Version:
2
+
3
+ v0.4.0
4
+ - Fixed an issue where routes without blocks wouldn't return status codes (#9)
5
+ - Allowed inline compilation as an alternative to the currently not working live compilation (#13), new inline version allows a hacky alternative (#17)
6
+ - Added new spaced syntax instead of dotted (`get post put "/", "Hello World"` instead of `get.post.put "/", "Hello World"`) (#10)
7
+ - Allowed the return value of the block to be the output if none is given (#15)
8
+ - Added Rack::Response to the @http variable (#13)
9
+ - Removed the `#is_file_string?` method in favor of simply checking if the file exists (#8)
10
+
1
11
  v0.3.2:
2
12
  - Really began using Gitlab issues
3
13
  - Synchronized development branch with master
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [![build status][build status badge]][build status link] [![coverage report][coverage report badge]][coverage report link] [![gem version][gem version badge]][gem version link] [![documentation coverage][documentation coverage badge]][documentation coverage link]
2
2
 
3
- [documentation coverage badge]: https://img.shields.io/badge/YARD%20coverage-93.18%-green.svg?style=flat-square
3
+ [documentation coverage badge]: https://img.shields.io/badge/YARD%20coverage-100%-brightgreen.svg?style=flat-square
4
4
  [documentation coverage link]: http://izwick-schachter.gitlab.io/atd/YARD/coverage
5
5
 
6
6
  [build status badge]: https://gitlab.com/izwick-schachter/atd/badges/master/build.svg?style=flat-square
@@ -19,6 +19,7 @@
19
19
  - [Setup](#setup)
20
20
  - [Routing](#routing)
21
21
  - [Basic Routing](#basic-routing)
22
+ - [Options Hash](#options-hash)
22
23
  - [Serving Files](#serving-files)
23
24
  - [Advanced Routing](#advanced-routing)
24
25
  - [DefaultApp](#defaultapp)
@@ -37,6 +38,7 @@
37
38
  - [Development](#development)
38
39
  - [Contributing](#contributing)
39
40
 
41
+
40
42
  # ATD
41
43
 
42
44
  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.
@@ -125,6 +127,19 @@ Or, a simpler way would be with `:ignore`:
125
127
  request "/", "Hello World", ignore: :delete
126
128
  ```
127
129
 
130
+ #### Options Hash
131
+
132
+ You can pass various options through the options hash. The options hash is put as the last arguemtn when creating a route. For example: `request "/", "Hello World", option: value, other-option: value`
133
+
134
+ Here is a list of the option which are currently valid and default values:
135
+
136
+ ```ruby
137
+ status: 200 # Integer > 99 and < 1000. This will be the status code returned unless it is overridden by
138
+ status_code: 200 # Same as status, but overrides. A slightly more verbose syntax.
139
+ respond_to: nil # A list of HTTP methods as lowercase symbols which the route should respond to.
140
+ ignore: nil # A list of HTTP methods as lowercase symbols which the route should not respond to.
141
+ ```
142
+
128
143
  #### Serving Files
129
144
 
130
145
  All files that you want to serve must be in the `assets` directory if they are, then it is simple to just create a route, and put the filename as the output. For example this will serve `assets/index.html`:
@@ -293,6 +308,22 @@ end
293
308
 
294
309
  The compilation works by going through the file extensions from last to first and running the compilations for each extension in that order. For example `file.html.erb` will first be compiled by the ERB compiler, then the output of the ERB compiler will be compiled by the HTML compiler.
295
310
 
311
+ When you include a file with then `request "/route", "file.ext` it will be precompiled, but not compiled. If you want live compilation there are a few options. If you want live compilation and precompilation you will have to use the following syntax:
312
+
313
+ ```ruby
314
+ request "/", "file.ext" do
315
+ live_compilation_method @http[:output]
316
+ end
317
+ ```
318
+
319
+ If you don't need precompilation and just want live compilation (the ususal use case) then you can just use the following format:
320
+
321
+ ```ruby
322
+ request "/" do
323
+ live_compilation_method File.read("/assets/file.ext")
324
+ end
325
+ ```
326
+
296
327
  ## Design Paradigms
297
328
 
298
329
  ATD is designed to fit into many different design paradigms, and to allow each person to adopt their own styles while leaving code readable to everyone. Do do this, the code was left fairly unstructured, but [here are a few examples from well known frameworks](https://gitlab.com/izwick-schachter/atd-examples.git).
@@ -309,4 +340,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
309
340
 
310
341
  ## Contributing
311
342
 
312
- 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.
343
+ 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.
344
+
345
+ ### Contribution Policies
346
+
347
+ Every constribution should correspond to a relevent issue which you keep up to date with notes on what you are working on. Each issues gets branched off of development and is named issue/<issue number>. When you are ready to merege it back in, make sure it passes both rubocop and all the tests. Each issue should get additional test if necessary.
data/atd.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["izwick.schachter@gmail.com"]
11
11
 
12
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"
13
+ spec.homepage = "https://gitlab.com/izwick-schachter/atd"
14
14
  spec.license = "MIT"
15
15
 
16
16
  # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
data/lib/atd/routes.rb CHANGED
@@ -16,53 +16,45 @@ module ATD
16
16
  module Compiler
17
17
  extend self
18
18
 
19
- # Lists all file extenstions which have defined compiler methods
19
+ # Lists all file extentions which have defined compiler methods
20
20
  def filetypes
21
21
  instance_methods(true) - [:filetypes]
22
22
  end
23
23
  end
24
24
 
25
- # This method is responsible for live compilation.
25
+ # This method is responsible for live compilation. It takes an ATD::Route as input, and returns either
26
+ # the filename if Route.output is a file or the Route.output string if Route.output is a string.
27
+ # It will also take the file and call the corresponding compilation method on it.
26
28
  def self.compile(name, contents)
27
- return contents if name.nil? && !contents.is_a?(File)
28
- name = File.basename(contents) if contents.is_a?(File)
29
- name = name.split(".")
30
- extensions = name - [name.first]
31
- extensions.each do |extension|
32
- contents = Compiler.send(extension, contents) if Compiler.filetypes.include? extension.to_sym
33
- end
34
- contents
29
+ return contents if name.nil?
30
+ contents = File.read(contents) if contents.is_a? File
31
+ parse(Compiler, name, contents)
35
32
  end
36
33
 
37
- # This method is responsible for precompilation
38
- def self.pre_parse(route)
39
- output = route.output
40
- name = output
41
- return nil if output.nil?
42
- if output.include?(".") || output.is_a?(File)
43
- name = (output.is_a?(File) ? File.basename(output) : output)
44
- file = read_file(output)
45
- return name if file.nil?
46
- file = precompile(name, file)
47
- route.output = file
34
+ # This method is responsible for precompilation. It takes an ATD::Route as input, and returns either
35
+ # the filename if Route.output is a file or the Route.output string if Route.output is a string.
36
+ # It will also take the file and call the corresponding precompilation method on it.
37
+ # route.output is either a full, expanded file path, a file, or a string
38
+ def self.precompile(route, *opts)
39
+ return nil if route.output.nil?
40
+ if route.output.is_a?(File)
41
+ name = route.output.is_a?(File) ? File.basename(route.output) : route.output.dup
42
+ file = route.output.is_a?(File) ? route.output.dup : File.new(route.output)
43
+ route.output = parse(Precompiler, name, File.read(file)) if opts[0].nil? || opts[0]
44
+ return name
48
45
  end
49
- name
46
+ route.output
50
47
  end
51
48
 
52
49
  class << self
53
50
  private
54
51
 
55
- def read_file(output)
56
- return File.read(File.join("assets/#{output}")) if output.is_a?(String) && File.exist?("assets/#{output}")
57
- return File.read(output) if output.is_a? File
58
- end
59
-
60
- def precompile(name, contents)
52
+ def parse(type, name, contents)
61
53
  name = name.split(".")
62
54
  extensions = name - [name.first]
63
55
  extensions.each do |extension|
64
- if Precompiler.filetypes.include? extension.to_sym
65
- contents = Precompiler.send(extension, contents)
56
+ if type.filetypes.include? extension.to_sym
57
+ contents = type.send(extension, contents)
66
58
  extensions -= [extension]
67
59
  end
68
60
  end
@@ -71,3 +63,7 @@ module ATD
71
63
  end
72
64
  end
73
65
  end
66
+
67
+ class Object
68
+ include ATD::Compilation::Compiler
69
+ end
data/lib/atd/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ATD
2
- VERSION = "0.3.2".freeze # The current version number of {ATD}.
2
+ VERSION = "0.4.0".freeze # The current version number of {ATD}.
3
3
  end
data/lib/atd.rb CHANGED
@@ -4,7 +4,7 @@ require "webrick"
4
4
  require_relative "atd/builtin_class_modifications"
5
5
  require_relative "atd/routes"
6
6
  # Extension packs
7
- require_relative "extensions/precompilers"
7
+ # require_relative "extensions/precompilers"
8
8
 
9
9
  # The assistant technical director of your website. It does the dirty work so you can see the big picture.
10
10
  module ATD
@@ -20,10 +20,11 @@ module ATD
20
20
  # So called because each instance stores a route, and will be called if that route is reached.
21
21
  # A route for the purposes of {ATD} is a parser that will be fed env in {ATD::App#call the rack app}.
22
22
  class Route
23
- attr_accessor :args, :method, :block, :path, :output, :app, :actions
23
+ attr_accessor :args, :method, :block, :path, :output, :app, :actions, :status_code
24
24
 
25
25
  # The first two arguments must me the path and the output.
26
26
  def initialize(*args, &block)
27
+ @status_code = 200
27
28
  @method = [:get, :post, :put, :patch, :delete]
28
29
  @method = [] if args.last.is_a?(Hash) && !(args.last[:respond_to].nil? || args.last[:ignore].nil?)
29
30
  @app = :DefaultApp
@@ -66,6 +67,17 @@ module ATD
66
67
 
67
68
  [:get, :post, :put, :delete, :patch].each do |method|
68
69
  define_method(method) do |*args, &block|
70
+ # This conditional allows the syntax get post put "/", "Hello" because it passes
71
+ # the variables up through the different method calls.
72
+ if args.first.is_a?(ATD::Route)
73
+ @method = args.first.method
74
+ @output = args.first.output
75
+ @path = args.first.path
76
+ @args = args.first.args
77
+ @block = args.first.block
78
+ @app = args.first.app
79
+ @actions = args.first.actions
80
+ end
69
81
  @method = [method] if @method.length == 5
70
82
  @method += [method]
71
83
  @method.uniq!
@@ -81,6 +93,7 @@ module ATD
81
93
  routes[@path] = {}
82
94
  routes[@path][@method] = {}
83
95
  routes[@path][@method] = {
96
+ status_code: @status_code,
84
97
  output: @output,
85
98
  block: @block,
86
99
  args: @args,
@@ -91,22 +104,41 @@ module ATD
91
104
 
92
105
  private
93
106
 
94
- # This should also manage @message at some point
107
+ # This should also manage @method at some point
95
108
  def parse_args(*args, &block)
96
109
  args.compact!
97
110
  args.flatten!
98
- args.reject! { |arg| arg.is_a?(File) ? false : arg.empty? } # File doesn't respond to empty
111
+ args.reject! { |arg| arg.is_a?(File) || arg.is_a?(Proc) || arg ? false : arg.empty? } # File doesn't respond to empty
99
112
  @block = block
113
+ # This requires the format ATD::Route.new(path, route, args)
100
114
  @path ||= args.shift
101
115
  @output ||= args.shift
102
116
  @args = Array(@args).concat(args) unless args.nil?
117
+ # @output should be whatever the input is unless the input is a controller/action or the input is_file_string?
103
118
  if @output =~ /^\w*#\w*$/ # Check if @path is a controller#action combo
104
119
  controller, action = @output.split("#")
105
120
  @action = Object.const_get(controller.to_sym).method(action.to_sym)
106
121
  @output = @action.call
107
122
  end
108
- @method += Array(args.last[:respond_to]) if args.last.is_a?(Hash) && !args.last[:respond_to].nil?
109
- @method -= Array(args.last[:ignore]) if args.last.is_a?(Hash) && !args.last[:ignore].nil?
123
+ # TODO: Choose one! They all work... I think...
124
+ # Method 1:
125
+ target_location = []
126
+ caller_locations.each do |caller_location|
127
+ target_dir = File.dirname(caller_location.absolute_path.to_s)
128
+ target_location.push(target_dir) unless target_dir.include?(__dir__)
129
+ end
130
+ # Method 2:
131
+ target_location = caller_locations.reject do |caller_location|
132
+ File.dirname(caller_location.absolute_path.to_s).include? __dir__
133
+ end
134
+ output_full_path = "#{File.dirname(target_location[0].absolute_path)}/assets/#{@output}"
135
+ @output = File.new(output_full_path) if File.exist?(output_full_path) && !Dir.exist?(output_full_path)
136
+ if args.is_a?(Hash) || args.last.is_a?(Hash)
137
+ @method += Array(args.last[:respond_to]) unless args.last[:respond_to].nil?
138
+ @method -= Array(args.last[:ignore]) unless args.last[:ignore].nil?
139
+ @status_code = args.last[:status] unless args.last[:status].nil?
140
+ @status_code = args.last[:status_code] unless args.last[:status_code].nil?
141
+ end
110
142
  self
111
143
  end
112
144
  end
@@ -129,7 +161,7 @@ module ATD
129
161
 
130
162
  [:get, :post, :put, :patch, :delete].each do |i|
131
163
  define_method(i) do |*args, &block|
132
- request.send(i, *args, &block)
164
+ request.send(i, *args, &block) # Makes get == r.get, post == r.post, etc.
133
165
  end
134
166
  end
135
167
 
@@ -162,20 +194,25 @@ module ATD
162
194
  def initialize(routes = [])
163
195
  @routes = {}
164
196
  Array(routes + self.class.routes).each do |route|
165
- filename = ATD::Compilation.pre_parse(route) if route.args.last.nil? || route.args.last[:precompile].nil? || route.args.last[:precompile]
197
+ route = route.clone
198
+ filename = ATD::Compilation.precompile(route, (route.args.last.is_a?(Hash) ? route.args.last[:precompile] : nil))
166
199
  route_hash = route.to_h
167
200
  current_route = route_hash[route.path][route.method]
168
201
  current_route[:filename] = filename
169
202
  block = current_route[:block]
203
+ # An instance method must be defined from the block make it the same as the controller actions. We don't want to
204
+ # convert the controller actions to blocks because if we did that, we would have to take them out of scope to allow
205
+ # them to use the @http variables.
170
206
  current_route[:block] = define_singleton_method(block.object_id.to_s.tr("0-9", "a-j").to_sym, &block) unless block.nil?
171
207
  current_route[:block] = route.actions unless route.actions.nil?
172
208
  @routes = @routes.to_h.deep_merge(route_hash)
173
209
  end
174
210
  end
175
211
 
212
+ # Allows instance method route creation. Just another way of creating routes.
176
213
  def request(*args, &block)
177
214
  route = ATD::Route.new(*args, &block)
178
- filename = ATD::Compilation.pre_parse(route) if route.args.last.nil? || route.args.last[:precompile].nil? || route.args.last[:precompile]
215
+ filename = ATD::Compilation.precompile(route, (route.args.last.is_a?(Hash) ? route.args.last[:precompile] : nil))
179
216
  route_hash = route.to_h
180
217
  route_hash[route.path][route.method][:filename] = filename
181
218
  @routes = @routes.to_h.deep_merge(route_hash)
@@ -198,10 +235,12 @@ module ATD
198
235
  @http = nil
199
236
  route = route(env)
200
237
  return error(404) if route.nil?
201
- route[:output] = ATD::Compilation.compile(route[:filename], route[:output])
238
+ route[:output] = Compilation.compile(route[:filename], route[:output]) unless !route[:args].nil? && !route[:args].empty? && route[:args][0].is_a?(Hash) && route[:args][0][:compile] == false
202
239
  return [route[:status_code].to_i, Hash(route[:headers]), Array(route[:output])] if route[:block].nil?
203
- http output: route[:output], request: Rack::Request.new(env), method: env["REQUEST_METHOD"]
204
- run_block(route[:block])
240
+ http output: route[:output], request: Rack::Request.new(env), method: env["REQUEST_METHOD"], response: Rack::Response.new(env)
241
+ return_val = method(route[:block]).call
242
+ @http[:output] = return_val if @http[:output].nil?
243
+ [@http[:status_code].to_i, Hash(@http[:headers]), Array(@http[:output])]
205
244
  end
206
245
 
207
246
  private
@@ -212,11 +251,6 @@ module ATD
212
251
  @routes[env["PATH_INFO"]].include_in_key?(env["REQUEST_METHOD"].downcase.to_sym)
213
252
  end
214
253
 
215
- def run_block(block)
216
- method(block).call
217
- [@http[:status_code].to_i, Hash(@http[:headers]), Array(@http[:output])]
218
- end
219
-
220
254
  def http(additional_params)
221
255
  @http = { status_code: 200, headers: {} }.merge(additional_params)
222
256
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ACecretMaster
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-10-12 00:00:00.000000000 Z
11
+ date: 2016-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -160,6 +160,7 @@ files:
160
160
  - ".gitignore"
161
161
  - ".gitlab-ci.yml"
162
162
  - ".rubocop.yml"
163
+ - ".yardopts"
163
164
  - CHANGELOG
164
165
  - CODE_OF_CONDUCT.md
165
166
  - Gemfile
@@ -174,7 +175,7 @@ files:
174
175
  - lib/atd/routes.rb
175
176
  - lib/atd/version.rb
176
177
  - lib/extensions/precompilers.rb
177
- homepage: https://rubygems.org/gems/atd
178
+ homepage: https://gitlab.com/izwick-schachter/atd
178
179
  licenses:
179
180
  - MIT
180
181
  metadata:
@@ -195,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
195
196
  version: '0'
196
197
  requirements: []
197
198
  rubyforge_project:
198
- rubygems_version: 2.5.1
199
+ rubygems_version: 2.5.2
199
200
  signing_key:
200
201
  specification_version: 4
201
202
  summary: The assistant technical director of your website. It does the dirty work