rabl-extend-compiler 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: 6800322e724c36b879faea17b54b57e974a17e8b
4
+ data.tar.gz: 47df4dec247d5afd65f5a937f3d1a59eddf23dfd
5
+ SHA512:
6
+ metadata.gz: a3bf09a07f4065b4d09a0b969987baa7765e9a2c98c796fe8b5e84c64572f0ee8b139093325ceb98466f0c4506696c6bc63e9b185e3d01b6e8cf3748ac4751a2
7
+ data.tar.gz: 208cba9d955087baf5d463b93f6aab6c821c5153aa7ec43c2eb626e2c3b69d151b19514706b200023be3c4f03c4cb1a6d0f286d8426b338458cdb4aaaebbb698
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ .ruby*
2
+ *.lock
3
+ /.bundle/
4
+ /.yardoc
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.0
5
+ before_install: gem install bundler -v 1.16.2
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in rabl-extend-compiler.gemspec
6
+ gemspec
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Rabl::Extend::Compiler
2
+ ## Installation
3
+
4
+ Add this line to your application's Gemfile:
5
+
6
+ ```ruby
7
+ gem 'rabl-extend-compiler'
8
+ ```
9
+
10
+ And then execute:
11
+
12
+ $ bundle
13
+
14
+ Or install it yourself as:
15
+
16
+ $ gem install rabl-extend-compiler
17
+
18
+ ## Usage
19
+
20
+ When using [Rabl](https://github.com/nesquena/rabl) there is a DSL method called `extend` which embeds another template in the current template and serves as a
21
+ mechanism to be DRY and maintain object definitions in a single place.
22
+
23
+ One signficant downsie of such a pattern is that the template rendering for large number of collections can be significantly lower (we have measured from 10-25% slower on collections up to 1000 objects)
24
+
25
+ In order to help facilitate still using Rabl (it's a great library) we dediced to write a few rake tasks that allow us the benefits of then extension system
26
+ without the drawbacks. Attempting to emulate something like what is mentioned in this [issue](https://github.com/nesquena/rabl/issues/500) and running rake tasks to verify or compile the extensions before moving to production.
27
+
28
+ This gem merely outlines the components and they may be used as you see fit at varying times in your infrastructure (we run the verification rake task in our CI pipeline)
29
+
30
+ The rake tasks are:
31
+
32
+ `rake rabl:extend:compiler:all` Runs all steps
33
+ `rake rabl:extend:compiler:reset` Will reset all signatures from the extended files
34
+ `rake rabl:extend:compiler:compile` Will compile and sign each use of `extend` in the code base
35
+ `rake rabl:extend:compiler:verify` Will `exit(1)` if the extensions are not compiled or the signatures do not match on the compiled extensions
36
+
37
+
38
+ The "signatures" encompass the attributes or files from an extension and are merely a SHA256 digest of the file contents during the compilation step and creates an easy and fast mechanism to determine if the extended files have been altered without updating the extensions.
39
+
40
+ ## Development
41
+
42
+ 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.
43
+
44
+ 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).
45
+
46
+ ## Contributing
47
+
48
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/rabl-extend-compiler.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require "rabl/extend/compiler"
4
+
5
+ Rake::TestTask.new(:spec) do |t|
6
+ t.libs << "spec"
7
+ t.libs << "lib"
8
+ t.test_files = FileList["spec/**/*_spec.rb"]
9
+ end
10
+
11
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rabl/extend/compiler"
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(__FILE__)
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,7 @@
1
+ module Rabl
2
+ module Extend
3
+ module Compiler
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,14 @@
1
+ require "rabl"
2
+ require "rabl/extend/compiler/version"
3
+
4
+ module Rabl
5
+ module Extend
6
+ module Compiler
7
+ if defined?(Rake)
8
+ ::Dir[::File.join(::File.dirname(__FILE__), "..", "..", "tasks", "**", "*.rake")].each do |rake_file|
9
+ load rake_file
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ require "rabl"
2
+ require "digest"
3
+ require "stringio"
4
+ require "rabl/extend/compiler"
5
+
6
+ namespace :rabl do
7
+ namespace :extend do
8
+ namespace :compiler do
9
+ desc "compile all extensions into rabl files"
10
+ task :all do
11
+ ::Rake::Task["rabl:extend:compiler:reset"].invoke
12
+ ::Rake::Task["rabl:extend:compiler:compile"].invoke
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,60 @@
1
+ require "rabl"
2
+ require "digest"
3
+ require "stringio"
4
+
5
+ namespace :rabl do
6
+ namespace :extend do
7
+ namespace :compiler do
8
+ desc "compile all uncompbiled extensions into rabl files"
9
+ task :compile do
10
+ view_paths = ::Rabl.configuration.view_paths
11
+
12
+ loop do
13
+ did_compile_a_file = false
14
+ view_paths.each do |view_path|
15
+ ::Dir.glob("#{view_path}/**/*.rabl").each do |rabl_file|
16
+ # Rewrite all of the file for extensions
17
+ file_contents = ::File.read(rabl_file)
18
+ new_file_contents = ::StringIO.new
19
+ file_contents.each_line do |file_line|
20
+ extension_file = file_line.scan(/\A[[:space:]]*extends[([:space:]]*['"]+([^"]*)['"]+/).flatten
21
+
22
+ if extension_file.empty?
23
+ new_file_contents.puts file_line
24
+ next
25
+ end
26
+
27
+ extension_filename = "#{view_path}/#{extension_file.first}.rabl"
28
+ extension_file_digest = ::Digest::SHA256.file(extension_filename).hexdigest
29
+ extension_contents = ::File.read(extension_filename)
30
+
31
+ new_file_contents.puts <<~EXTENDS_MESSAGE
32
+ # rabl-extend-compiler #{file_line.chomp} => #{extension_file_digest}
33
+ #
34
+ # This file segment is generated by rabl-extend-compiler rake task
35
+ # and should not be edited. To edit the generated extension
36
+ # edit the file at: #{extension_file}
37
+ EXTENDS_MESSAGE
38
+
39
+ new_file_contents.puts extension_contents
40
+ new_file_contents.puts "# #{extension_file_digest}"
41
+ end
42
+
43
+ # Replace the file if the contents changed and the following will rewrite it again
44
+ if file_contents != new_file_contents.string
45
+ did_compile_a_file = true
46
+ ::File.write(rabl_file, new_file_contents.string)
47
+ end
48
+ end
49
+ end
50
+
51
+ if did_compile_a_file
52
+ did_compile_a_file = false
53
+ else
54
+ break
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,55 @@
1
+ require "rabl"
2
+ require "digest"
3
+ require "stringio"
4
+
5
+ namespace :rabl do
6
+ namespace :extend do
7
+ namespace :compiler do
8
+ desc "reset extensions to be compiled"
9
+ task :reset do
10
+ view_paths = ::Rabl.configuration.view_paths
11
+
12
+ view_paths.each do |view_path|
13
+ ::Dir.glob("#{view_path}/**/*.rabl").each do |rabl_file|
14
+ file_contents = ::File.read(rabl_file)
15
+ new_file_contents = ::StringIO.new
16
+
17
+ ##
18
+ # Run through each line and verify the Sha256 digest of the extension file contents
19
+ # against the digest that is already stored in the file that extends
20
+ #
21
+ waiting = false
22
+ waiting_hash = ""
23
+ file_contents.each_line do |file_line|
24
+ if waiting
25
+ waiting = !file_line.include?(waiting_hash) # if we are in a waiting state then we throw the line away
26
+ next
27
+ end
28
+
29
+ if file_line.start_with?("# rabl-extend-compiler extends")
30
+ extension_file = file_line.scan(/\A[[:space:]]*#[[:space:]]+rabl-extend-compiler[[:space:]]*extends[([:space:]]*['"]+([^"]*)['"]+/).flatten.first
31
+ extension_filename = "#{view_path}/#{extension_file}.rabl"
32
+ extension_file_digest = file_line.split("=>").last.gsub(/[[:space:]]/, "")
33
+
34
+ if extension_file_digest == ::Digest::SHA256.file(extension_filename).hexdigest
35
+ new_file_contents.puts file_line
36
+ else
37
+ new_file_contents.puts file_line.split("=>").first.gsub("# rabl-extend-compiler ", "")
38
+ waiting = true
39
+ waiting_hash = extension_file_digest
40
+ end
41
+ else
42
+ new_file_contents.puts file_line
43
+ end
44
+ end
45
+
46
+ # Replace the file if the contents changed and the following will rewrite it again
47
+ if file_contents != new_file_contents.string
48
+ ::File.write(rabl_file, new_file_contents.string)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,54 @@
1
+ require "rabl"
2
+ require "digest"
3
+ require "stringio"
4
+
5
+ namespace :rabl do
6
+ namespace :extend do
7
+ namespace :compiler do
8
+ desc "verify that all extensions are created and the signatures match; return exit(1) if not verifiable"
9
+ task :verify do
10
+ view_paths = ::Rabl.configuration.view_paths
11
+
12
+ view_paths.each do |view_path|
13
+ ::Dir.glob("#{view_path}/**/*.rabl").each do |rabl_file|
14
+ file_contents = ::File.read(rabl_file)
15
+ new_file_contents = ::StringIO.new
16
+
17
+ ##
18
+ # Run through each line and verify the Sha256 digest of the extension file contents
19
+ # against the digest that is already stored in the file that extends
20
+ #
21
+ waiting = false
22
+ waiting_hash = ""
23
+ file_contents.each_line do |file_line|
24
+ if waiting
25
+ waiting = !file_line.include?(waiting_hash) # if we are in a waiting state then we throw the line away
26
+ next
27
+ end
28
+
29
+ if file_line.start_with?("# rabl-extend-compiler extends")
30
+ extension_file = file_line.scan(/\A[[:space:]]*#[[:space:]]+rabl-extend-compiler[[:space:]]*extends[([:space:]]*['"]+([^"]*)['"]+/).flatten.first
31
+ extension_filename = "#{view_path}/#{extension_file}.rabl"
32
+ extension_file_digest = file_line.split("=>").last.gsub(/[[:space:]]/, "")
33
+
34
+ next if extension_file_digest == ::Digest::SHA256.file(extension_filename).hexdigest
35
+ $stderr << "rabl-extend-compiler: Compiled extension digest mismatch #{extension_filename}"
36
+ $stderr << "rabl-extend-compiler: Run rake rabl:extend:compiler:all to reset"
37
+
38
+ exit(1)
39
+ end
40
+ end
41
+
42
+ file_contents.each_line do |file_line|
43
+ extension_file = file_line.scan(/\A[[:space:]]*extends[([:space:]]*['"]+([^"]*)['"]+/).flatten
44
+ next if extension_file.empty?
45
+ $stderr << "rabl-extend-compiler: Uncompiled extenion at #{extension_file.first}"
46
+
47
+ exit(1)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,40 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "rabl/extend/compiler/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rabl-extend-compiler"
8
+ spec.version = Rabl::Extend::Compiler::VERSION
9
+ spec.authors = ["Brandon Dewitt"]
10
+ spec.email = ["brandonsdewitt+rubygems@gmail.com"]
11
+
12
+ spec.summary = %q{ a set of rake tasks to compile rabl templates for performance }
13
+ spec.description = %q{ a set of rake tasks to compile and verify rabl templates that use `extend` for moooooaaar performance }
14
+ spec.homepage = "https://github.com/abrandoned/rabl-extend-compiler"
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
+ if spec.respond_to?(:metadata)
19
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against " \
22
+ "public gem pushes."
23
+ end
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
28
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
29
+ end
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_dependency "rabl"
35
+ spec.add_dependency "rake", "~> 10.0"
36
+
37
+ spec.add_development_dependency "pry"
38
+ spec.add_development_dependency "bundler", "~> 1.16"
39
+ spec.add_development_dependency "minitest", "~> 5.0"
40
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rabl-extend-compiler
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brandon Dewitt
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-06-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rabl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
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: :runtime
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: pry
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: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.16'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.16'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '5.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '5.0'
83
+ description: " a set of rake tasks to compile and verify rabl templates that use `extend`
84
+ for moooooaaar performance "
85
+ email:
86
+ - brandonsdewitt+rubygems@gmail.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - README.md
95
+ - Rakefile
96
+ - bin/console
97
+ - bin/setup
98
+ - lib/rabl/extend/compiler.rb
99
+ - lib/rabl/extend/compiler/version.rb
100
+ - lib/tasks/all.rake
101
+ - lib/tasks/compile_extensions.rake
102
+ - lib/tasks/reset_extensions.rake
103
+ - lib/tasks/verify_extensions.rake
104
+ - rabl-extend-compiler.gemspec
105
+ homepage: https://github.com/abrandoned/rabl-extend-compiler
106
+ licenses: []
107
+ metadata:
108
+ allowed_push_host: https://rubygems.org
109
+ post_install_message:
110
+ rdoc_options: []
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 2.6.13
126
+ signing_key:
127
+ specification_version: 4
128
+ summary: a set of rake tasks to compile rabl templates for performance
129
+ test_files: []