rails2lb4 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +19 -0
- data/README.md +68 -0
- data/bin/rails2lb4 +30 -0
- data/lib/rails2lb4.rb +137 -0
- data/templates/datasource.erb +14 -0
- data/templates/model.erb +42 -0
- data/templates/repository.erb +15 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 17a1f0ccbd6c81c97d997cba4184988c8a6932b50091bd6ce5d4123621159258
|
4
|
+
data.tar.gz: 23f60cfdffac43b3fa4e23e63db2096e4b3761556521c861c5a82ef863a37776
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 803ccfbdb19c79a9f07dc07975fb215bbaaa3044b7c682f9efdc126e4ef3d1a95653a9a9b8cf58165f5f4f4185a619f8ec7ce9941c51fa533359f3778b8b11f6
|
7
|
+
data.tar.gz: 26175cd91f0588e6728a0af73284e46f4157250b5d26ec24a080d8e7814e91b7e0f8056d13d1fbc2df922beb7174a7db62067c3ca5003a509c446b05f101fe50
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
MIT license
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
**Warning**: this application is only demo quality at the moment. Do not use on
|
2
|
+
an existing loopback4 appication is not under version control where all of the
|
3
|
+
changes have already been committed as this application may overwrite files.
|
4
|
+
|
5
|
+
This tool will create a loopback4 model, respository, and datasource based on
|
6
|
+
an existing Rails application.
|
7
|
+
|
8
|
+
Step 0
|
9
|
+
------
|
10
|
+
|
11
|
+
Install `rails` and/or `loopback4` if they are not already installed:
|
12
|
+
|
13
|
+
gem install rails
|
14
|
+
npm install -g loopback-cli
|
15
|
+
|
16
|
+
Note: in order to install these tools, you need to have previously installed `ruby`, `node`, `npm` and other tools. Check the installation instructions for
|
17
|
+
[rails](https://guides.rubyonrails.org/getting_started.html#installing-rails) and
|
18
|
+
[loopback4](https://loopback.io/doc/en/lb4/Getting-started.html) for details.
|
19
|
+
|
20
|
+
Step 1
|
21
|
+
------
|
22
|
+
|
23
|
+
Install this tool:
|
24
|
+
|
25
|
+
gem install rails2lb4
|
26
|
+
|
27
|
+
Step 2
|
28
|
+
------
|
29
|
+
|
30
|
+
Locate a Rails application. If you don't already have one, you can follow the [Creating the Blog Application](https://guides.rubyonrails.org/getting_started.html#creating-the-blog-application) in the Rails guide, or
|
31
|
+
clone it from [https://github.com/rubys/railsguide_blog](https://github.com/rubys/railsguide_blog.git).
|
32
|
+
|
33
|
+
Step 3
|
34
|
+
------
|
35
|
+
|
36
|
+
Locate or create a new loopback application. To create a new application:
|
37
|
+
|
38
|
+
lb4 app blog
|
39
|
+
|
40
|
+
Step 4
|
41
|
+
------
|
42
|
+
|
43
|
+
Run the tool, specifying the path to the source rails and destination loopback applications:
|
44
|
+
|
45
|
+
rails2lb4 /path/to/rails/blog /path/to/loopback4/blog
|
46
|
+
|
47
|
+
Note: by default, this tool will set up the loopback application to access the Rails `development` database. If you would like to access another database, set the `RAILS_ENV` environment variable before running this step.
|
48
|
+
|
49
|
+
|
50
|
+
Step 5 (optional)
|
51
|
+
-----------------
|
52
|
+
|
53
|
+
Create REST controllers for the new models:
|
54
|
+
|
55
|
+
lb4 controller article
|
56
|
+
lb4 controller comment
|
57
|
+
|
58
|
+
Note: specify `number` as the type of `id` for these controllers.
|
59
|
+
|
60
|
+
Step 6 (optional)
|
61
|
+
-----------------
|
62
|
+
|
63
|
+
Start the loopback4 server:
|
64
|
+
|
65
|
+
npm start
|
66
|
+
|
67
|
+
Note: by default, both Rails and Loopback4 default to listen to port 3000. Be sure to stop your Rails server before starting your loopback4 server.
|
68
|
+
|
data/bin/rails2lb4
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
source = target = Dir.pwd
|
4
|
+
|
5
|
+
if ARGV.length == 2
|
6
|
+
source, target = ARGV
|
7
|
+
elsif ARGV.length == 1
|
8
|
+
if File.exist? File.expand_path('Rakefile', ARGV.first)
|
9
|
+
source = File.expand_path(ARGV.first)
|
10
|
+
elsif File.exist? File.expand_path('index.ts', ARGV.first)
|
11
|
+
target = File.expand_path(ARGV.first)
|
12
|
+
end
|
13
|
+
else
|
14
|
+
STDERR.puts "Usage: #{$0} [source] [target]"
|
15
|
+
exit 1
|
16
|
+
end
|
17
|
+
|
18
|
+
unless File.exist? File.expand_path('Rakefile', source)
|
19
|
+
STDERR.puts 'source directory is not a Rails app'
|
20
|
+
exit 1
|
21
|
+
end
|
22
|
+
|
23
|
+
unless File.exist? File.expand_path('index.ts', target)
|
24
|
+
STDERR.puts 'target directory is not a lb4 app'
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
require 'rails2lb4'
|
29
|
+
|
30
|
+
rails2lb4 source, target
|
data/lib/rails2lb4.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'erubis'
|
2
|
+
require 'ansi'
|
3
|
+
require 'yaml'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require 'active_support/core_ext/string'
|
7
|
+
require 'active_support/inflector'
|
8
|
+
|
9
|
+
def rails2lb4(source, target)
|
10
|
+
# import custom pluralization
|
11
|
+
if File.exist? "#{source}/config/initializers/inflections.rb"
|
12
|
+
require "#{source}/config/initializers/inflections.rb"
|
13
|
+
end
|
14
|
+
|
15
|
+
# define a write operation that colorizes output and determines if the
|
16
|
+
# output represent new content or a change.
|
17
|
+
def target.write path, contents
|
18
|
+
dest = File.join(self, path)
|
19
|
+
if File.size?(dest) and IO.read(dest) == contents
|
20
|
+
puts ANSI.blue { 'skipping ' } + path
|
21
|
+
else
|
22
|
+
if File.size?(dest)
|
23
|
+
puts ANSI.bold { ANSI.magenta { 'updating ' } } + path
|
24
|
+
else
|
25
|
+
puts ANSI.bold { ANSI.green { 'creating ' } } + path
|
26
|
+
end
|
27
|
+
IO.write dest, contents
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# determine the database type from the configuration
|
32
|
+
environment = ENV['RAILS_ENV'] || 'development'
|
33
|
+
database = YAML.load_file("#{source}/config/database.yml")
|
34
|
+
@adapter = database[environment]['adapter']
|
35
|
+
|
36
|
+
# common configuration
|
37
|
+
config = {
|
38
|
+
name: @adapter,
|
39
|
+
connector: "loopback-connector-#{@adapter}"
|
40
|
+
}
|
41
|
+
|
42
|
+
# database specific configuration
|
43
|
+
if @adapter == 'sqlite3'
|
44
|
+
config[:file] = File.expand_path(database[environment]['database'], source)
|
45
|
+
|
46
|
+
Dir.chdir target do
|
47
|
+
unless IO.read('package.json').include? 'loopback-connector-sqlite3'
|
48
|
+
system 'npm install loopback-connector-sqlite3 --save'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
elsif @adapter == 'mysql' or @adapter == 'postgresql'
|
53
|
+
environment = database[environment]
|
54
|
+
%w(database host password.port username).each do |property|
|
55
|
+
config[property] = environment[property] if environment[property]
|
56
|
+
end
|
57
|
+
|
58
|
+
if @adapter == 'mysql'
|
59
|
+
config[:socketPath] = environtment[:socket] if environment[:socket]
|
60
|
+
config[:connectionLimit] = environtment[:pool] if environment[:pool]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# produce datasource.ts
|
65
|
+
template = File.read(File.join(__dir__, '../templates/datasource.erb'))
|
66
|
+
datasource = Erubis::Eruby.new(template).result(binding)
|
67
|
+
path = File.join('src', 'datasources', "#{@adapter}.datasource.ts")
|
68
|
+
target.write path, datasource
|
69
|
+
|
70
|
+
# produce datasource.json
|
71
|
+
path = File.join('src', 'datasources', "#{@adapter}.datasource.json")
|
72
|
+
target.write path, JSON.pretty_generate(config)
|
73
|
+
|
74
|
+
# produce datasource/index.ts
|
75
|
+
index = Dir["#{target}/src/datasources/*.datasource.ts"].sort.
|
76
|
+
map {|file| "export * from './#{File.basename(file, '.ts')}';"}.
|
77
|
+
join("\n") + "\n"
|
78
|
+
target.write 'src/datasources/index.ts', index
|
79
|
+
|
80
|
+
# parse schema.rb from the source
|
81
|
+
schema = IO.read("#{source}/db/schema.rb")
|
82
|
+
table = /^\s+create_table "([^"]+)",.*?\n(.*?)\n\s+end/m
|
83
|
+
|
84
|
+
data_types = {
|
85
|
+
"integer" => "number",
|
86
|
+
"float" => "number",
|
87
|
+
"text" => "string",
|
88
|
+
"boolean" => "boolean",
|
89
|
+
"date" => "Date",
|
90
|
+
"datetime" => "Date",
|
91
|
+
}
|
92
|
+
|
93
|
+
tables = {}
|
94
|
+
schema.scan(table).each do |name, ddl|
|
95
|
+
cols = ddl.scan(/^\s+t\.(\w+)\s+"(\w+)/).
|
96
|
+
map {|names| [names.last, data_types[names.first] || names.first]}.to_h
|
97
|
+
tables[name] = cols
|
98
|
+
end
|
99
|
+
|
100
|
+
# produce model.ts and repository.ts for each model
|
101
|
+
Dir["#{source}/app/models/*.rb"].sort.each do |file|
|
102
|
+
model = File.read(file)
|
103
|
+
basename = File.basename(file, '.rb')
|
104
|
+
@table = tables[basename.pluralize] || {}
|
105
|
+
@class_name = model[/class (\w+)/, 1]
|
106
|
+
@table_name = @class_name.downcase.pluralize
|
107
|
+
|
108
|
+
@belongs_to = model.scan(/^\s+belongs_to\s*:(\w+)/).
|
109
|
+
map {|(name)| [name, name.camelcase]}.to_h
|
110
|
+
@has_many = model.scan(/^\s+has_many\s*:(\w+)/).
|
111
|
+
map {|(name)| [name.singularize, name.singularize.camelcase]}.to_h
|
112
|
+
|
113
|
+
template = File.read(File.join(__dir__, '../templates/model.erb'))
|
114
|
+
model = Erubis::Eruby.new(template).result(binding)
|
115
|
+
|
116
|
+
path = File.join('src', 'models', basename+'.model.ts')
|
117
|
+
target.write path, model
|
118
|
+
|
119
|
+
template = File.read(File.join(__dir__, '../templates/repository.erb'))
|
120
|
+
repository = Erubis::Eruby.new(template).result(binding)
|
121
|
+
|
122
|
+
path = File.join('src', 'repositories', basename+'.repository.ts')
|
123
|
+
target.write path, repository
|
124
|
+
end
|
125
|
+
|
126
|
+
# produce model.index.ts
|
127
|
+
index = Dir["#{target}/src/models/*.model.ts"].sort.
|
128
|
+
map {|file| "export * from './#{File.basename(file, '.ts')}';"}.
|
129
|
+
join("\n") + "\n"
|
130
|
+
target.write 'src/models/index.ts', index
|
131
|
+
|
132
|
+
# produce repositories.index.ts
|
133
|
+
index = Dir["#{target}/src/repositories/*.repository.ts"].sort.
|
134
|
+
map {|file| "export * from './#{File.basename(file, '.ts')}';"}.
|
135
|
+
join("\n") + "\n"
|
136
|
+
target.write 'src/repositories/index.ts', index
|
137
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import {inject} from '@loopback/core';
|
2
|
+
import {juggler} from '@loopback/repository';
|
3
|
+
import * as config from './<%= @adapter %>.datasource.json';
|
4
|
+
|
5
|
+
export class Sqlite3DataSource extends juggler.DataSource {
|
6
|
+
static dataSourceName = '<%= @adapter %>';
|
7
|
+
|
8
|
+
constructor(
|
9
|
+
@inject('datasources.config.<%= @adapter %>', {optional: true})
|
10
|
+
dsConfig: object = config,
|
11
|
+
) {
|
12
|
+
super(dsConfig);
|
13
|
+
}
|
14
|
+
}
|
data/templates/model.erb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
<%
|
2
|
+
imports = %w{Entity property model}
|
3
|
+
imports << 'belongsTo' unless @belongs_to.empty?
|
4
|
+
imports << 'hasMany' unless @has_many.empty?
|
5
|
+
%>
|
6
|
+
import {<%= imports.join(', ') %>} from '@loopback/repository';
|
7
|
+
<% @belongs_to.merge(@has_many).each do |name, value| %>
|
8
|
+
import {<%= value %>} from './<%= name %>.model';
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
@model({settings: {<%= @adapter %>: {table: '<%= @table_name %>'}}})
|
12
|
+
export class <%= @class_name %> extends Entity {
|
13
|
+
@property({
|
14
|
+
type: 'number',
|
15
|
+
id: true
|
16
|
+
})
|
17
|
+
id: number;
|
18
|
+
<% @table.each do |attr, value| %>
|
19
|
+
|
20
|
+
<% if @belongs_to.keys.any? {|key| "#{key}_id" == attr} %>
|
21
|
+
@belongsTo(() => <%= @belongs_to[attr.sub(/_id/, '')] %>, {keyTo: 'id'})
|
22
|
+
<% else %>
|
23
|
+
@property({
|
24
|
+
type: '<%= value %>'
|
25
|
+
})
|
26
|
+
<% end %>
|
27
|
+
<%= attr %>: <%= value %>;
|
28
|
+
<% end %>
|
29
|
+
<% @has_many.each do |name, value| %>
|
30
|
+
|
31
|
+
@hasMany(() => <%= value %>, {keyTo: '<%= @class_name.downcase %>_id'})
|
32
|
+
<%= name.pluralize %>: <%= value %>[];
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
getId() {
|
36
|
+
return this.id;
|
37
|
+
}
|
38
|
+
|
39
|
+
constructor(data?: Partial<<%= @class_name %>>) {
|
40
|
+
super(data);
|
41
|
+
}
|
42
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import {DefaultCrudRepository, juggler} from '@loopback/repository';
|
2
|
+
import {<%= @class_name %>} from '../models';
|
3
|
+
import {Sqlite3DataSource} from '../datasources';
|
4
|
+
import {inject} from '@loopback/core';
|
5
|
+
|
6
|
+
export class <%= @class_name %>Repository extends DefaultCrudRepository<
|
7
|
+
<%= @class_name %>,
|
8
|
+
typeof <%= @class_name %>.prototype.id
|
9
|
+
> {
|
10
|
+
constructor(
|
11
|
+
@inject('datasources.sqlite3') dataSource: Sqlite3DataSource,
|
12
|
+
) {
|
13
|
+
super(<%= @class_name %>, dataSource);
|
14
|
+
}
|
15
|
+
}
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails2lb4
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sam Ruby
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ansi
|
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: erubis
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Builds a loopback4 datasource, model, and repository from Rails schema.rb,
|
42
|
+
database.yml, and model sources
|
43
|
+
email:
|
44
|
+
- rubys@intertwingly.net
|
45
|
+
executables:
|
46
|
+
- rails2lb4
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- LICENSE
|
51
|
+
- README.md
|
52
|
+
- bin/rails2lb4
|
53
|
+
- lib/rails2lb4.rb
|
54
|
+
- templates/datasource.erb
|
55
|
+
- templates/model.erb
|
56
|
+
- templates/repository.erb
|
57
|
+
homepage: http://github.com/rubys/rails2lb4
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.7.4
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: Convert Rails model to loopback4
|
81
|
+
test_files: []
|