Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Rails 4+ #264

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions jack-core/src/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Use an official Ruby runtime as a parent image
FROM ruby:2.3.0

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

RUN bundle install

# The consumer is expected to provide two additional arguments:
# 1. the path to the Jack config file
# 2. the output directory
#
# example usage: docker run -w /app -v $(pwd):/app/temp --rm jack temp/jack_config.yml temp/jack
ENTRYPOINT ["ruby", "./rb/jack.rb"]
4 changes: 2 additions & 2 deletions jack-core/src/Gemfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
source "http://rubygems.org"
gem "activesupport", "~> 4.1"
gem "i18n", "~> 0.9"
gem "activesupport", ">= 4.1"
gem "i18n", ">= 0.9"
gem 'fattr'
22 changes: 10 additions & 12 deletions jack-core/src/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
GEM
remote: http://rubygems.org/
specs:
activesupport (4.2.5)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
activesupport (5.2.4.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
concurrent-ruby (1.0.5)
concurrent-ruby (1.1.6)
fattr (2.4.0)
i18n (0.9.1)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
json (1.8.6)
minitest (5.10.3)
minitest (5.14.0)
thread_safe (0.3.6)
tzinfo (1.2.4)
tzinfo (1.2.6)
thread_safe (~> 0.1)

PLATFORMS
ruby

DEPENDENCIES
activesupport (~> 4.1)
activesupport (>= 4.1)
fattr
i18n (~> 0.9)
i18n (>= 0.9)

BUNDLED WITH
1.16.1
1.17.2
83 changes: 83 additions & 0 deletions jack-core/src/rb/rails_3_to_5_translator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# frozen_string_literal: true

# Jack is designed for a version of Rails 3, which was end-of-lifed
# back in June of 2016. When Jack reads from the ActiveRecord
# schema, it does not account for various changes in the schema
# format that have been introduced subsequently:
# 1. add_index(table, columns, opts={}) was replaced by
# t.index(columns, opts={}) within a create_table block
# 2. t.integer(column, limit: 8) was replaced by t.bigint(column, opts={})
#
# Because there aren't very many schema changes and they are relatively
# simple, it seemed to Jacob that the laziest way to offer compatibility
# between Jack and newer versions of Rails is to programmatically
# translate Rails 4+ schemas into Rails 3 schemas and then run Jack
# as usual. He at least tried to update Jack to Rails 5, but it soon
# became clear that doing so would be more of a struggle than the
# aforementioned solution, and time happens to be of the essence right now.
# Future maintainers of this project should not hesitate to update Jack
# properly as time allows.
class Rails3To5Translator
def initialize(schema_rb_path)
@schema_rb_path = schema_rb_path
end

def translate
new_contents = ''
index_calls_by_table_name = hash_with_empty_arrays_as_new_values
this_table_name = nil
nesting_degree = 0

File.readlines(@schema_rb_path).each do |line|
# comments and empty lines
next if line.strip.start_with?('#') || line.strip == ''

if line.strip.start_with?('create_table')
# remember which table we're operating on
match = /create_table \"(.*?)\"/.match(line)
this_table_name = match[1]
nesting_degree += 1

elsif line.end_with?("do\n") || /do \|.*\|/.match(line)
# remember how far nested we are in terms of do/end blocks
nesting_degree += 1

elsif line.strip.start_with?('end')
# check if we have reached the final "end" in the file
# and, if so, replace it with the add_index calls we need
nesting_degree -= 1

if nesting_degree.zero?
index_calls_by_table_name.each do |table_name, index_calls|
index_calls.each do |index_call|
new_contents += " add_index [\"#{table_name}\"], #{index_call}\n"
end
end
end

elsif /\.bigint/.match(line)
# case 1 described in the top level comment
line.sub!('.bigint', '.integer')
line.sub!("\n", ", limit: 8\n")

elsif /\.index/.match(line)
# case 2 described in the top level comment
method_parameters = /\.index (.*?)\n/.match(line)[1]
index_calls_by_table_name[this_table_name].push(method_parameters)
next
end

new_contents += line
end

new_contents
end

private

def hash_with_empty_arrays_as_new_values
Hash.new do |hash, unrecognized_key|
hash[unrecognized_key] = []
end
end
end
1 change: 1 addition & 0 deletions jack-core/src/rb/requires.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
require File.expand_path(File.dirname(__FILE__) + "/database_defn")
require File.expand_path(File.dirname(__FILE__) + "/project_defn")
require File.expand_path(File.dirname(__FILE__) + "/schema_rb_parser")
require File.expand_path(File.dirname(__FILE__) + "/rails_3_to_5_translator")
require File.expand_path(File.dirname(__FILE__) + "/models_dir_processor")
require File.expand_path(File.dirname(__FILE__) + "/template_processor")
14 changes: 13 additions & 1 deletion jack-core/src/rb/schema_rb_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

module FromHash
def from_hash(ops)
ops.delete(:options)
ops.each do |k,v|
send("#{k}=",v)
end
Expand Down Expand Up @@ -124,9 +125,20 @@ def to_h

class SchemaRbParser
def self.parse(schema_rb, ignored_tables = [])
load schema_rb
translated_contents = Rails3To5Translator.new(schema_rb).translate
old_filename = schema_rb.split('/').last
new_schema_rb = schema_rb.sub(old_filename, 'TEMP_rails_3_compatible_schema.rb')
FileUtils.touch(new_schema_rb)
File.write(new_schema_rb, translated_contents)
load_new_schema(new_schema_rb, ignored_tables)
end

def self.load_new_schema(translated_schema_rb, ignored_tables)
load translated_schema_rb
defns = $schema.tables.map(&:to_model_defn).compact.reject { |x| ignored_tables.include?(x.table_name) }
[defns, $schema.version.to_s]
ensure
FileUtils.rm(translated_schema_rb)
end
end

Expand Down