sails 0.1.0
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/.gitignore +34 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +45 -0
- data/LICENSE +22 -0
- data/README.md +33 -0
- data/bin/sails +19 -0
- data/lib/sails/base.rb +155 -0
- data/lib/sails/cli.rb +133 -0
- data/lib/sails/rails.rb +15 -0
- data/lib/sails/service.rb +77 -0
- data/lib/sails/templates/%app_name%.thrift.tt +17 -0
- data/lib/sails/templates/Gemfile +13 -0
- data/lib/sails/templates/Gemfile.lock +45 -0
- data/lib/sails/templates/Rakefile.tt +54 -0
- data/lib/sails/templates/app/services/application_service.rb.tt +6 -0
- data/lib/sails/templates/app/services/gen-rb/%app_name%.rb.tt +11 -0
- data/lib/sails/templates/app/services/handler.rb.tt +3 -0
- data/lib/sails/templates/config/application.rb.tt +23 -0
- data/lib/sails/templates/config/boot.rb +7 -0
- data/lib/sails/templates/config/database.yml +15 -0
- data/lib/sails/templates/config/environments/development.rb +0 -0
- data/lib/sails/templates/config/environments/production.rb +0 -0
- data/lib/sails/templates/config/environments/test.rb +0 -0
- data/lib/sails/templates/config/locales/en.yml +2 -0
- data/lib/sails/templates/config/locales/rails.zh-CN.yml +203 -0
- data/lib/sails/templates/config/locales/zh-CN.yml +4 -0
- data/lib/sails/templates/db/seeds.rb +7 -0
- data/lib/sails/version.rb +5 -0
- data/lib/sails.rb +7 -0
- data/sails.gemspec +23 -0
- data/spec/dummy/log/development.log +1 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/tails_spec.rb +33 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f659284fee2c294ceb15bf368ea80f61c8331fc3
|
4
|
+
data.tar.gz: 0f52d780eb04bafa7b4a63ef9d5460fce2ea8c2a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 717ac7ec1138af2afe82d8460af64c0e5cafe6573fbe8e1b198124823074eaceba4514a93e9ca1da316c22b4eb9ec621468c53914f6721df3b583d664973619d
|
7
|
+
data.tar.gz: 3aa695a566367311681b0439a7e16c48171c2595b228b3775411139cd6583f88f08518a1319e39f4dc77121e4234ba42c024d29a7188616d76cf39e5b05d42ba
|
data/.gitignore
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
10
|
+
/tmp/
|
11
|
+
|
12
|
+
## Specific to RubyMotion:
|
13
|
+
.dat*
|
14
|
+
.repl_history
|
15
|
+
build/
|
16
|
+
|
17
|
+
## Documentation cache and generated files:
|
18
|
+
/.yardoc/
|
19
|
+
/_yardoc/
|
20
|
+
/doc/
|
21
|
+
/rdoc/
|
22
|
+
|
23
|
+
## Environment normalisation:
|
24
|
+
/.bundle/
|
25
|
+
/lib/bundler/man/
|
26
|
+
|
27
|
+
# for a library or gem, you might want to ignore these files since the code is
|
28
|
+
# intended to run in multiple environments; otherwise, check them in:
|
29
|
+
# Gemfile.lock
|
30
|
+
# .ruby-version
|
31
|
+
# .ruby-gemset
|
32
|
+
|
33
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
34
|
+
.rvmrc
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sails (0.1.0)
|
5
|
+
activesupport (>= 3.2.0)
|
6
|
+
thor
|
7
|
+
thrift (>= 0.9.0)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (4.1.8)
|
13
|
+
i18n (~> 0.6, >= 0.6.9)
|
14
|
+
json (~> 1.7, >= 1.7.7)
|
15
|
+
minitest (~> 5.1)
|
16
|
+
thread_safe (~> 0.1)
|
17
|
+
tzinfo (~> 1.1)
|
18
|
+
diff-lcs (1.2.5)
|
19
|
+
i18n (0.6.11)
|
20
|
+
json (1.8.1)
|
21
|
+
minitest (5.4.3)
|
22
|
+
rspec (3.1.0)
|
23
|
+
rspec-core (~> 3.1.0)
|
24
|
+
rspec-expectations (~> 3.1.0)
|
25
|
+
rspec-mocks (~> 3.1.0)
|
26
|
+
rspec-core (3.1.7)
|
27
|
+
rspec-support (~> 3.1.0)
|
28
|
+
rspec-expectations (3.1.2)
|
29
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
30
|
+
rspec-support (~> 3.1.0)
|
31
|
+
rspec-mocks (3.1.3)
|
32
|
+
rspec-support (~> 3.1.0)
|
33
|
+
rspec-support (3.1.2)
|
34
|
+
thor (0.19.1)
|
35
|
+
thread_safe (0.3.4)
|
36
|
+
thrift (0.9.2.0)
|
37
|
+
tzinfo (1.2.2)
|
38
|
+
thread_safe (~> 0.1)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
ruby
|
42
|
+
|
43
|
+
DEPENDENCIES
|
44
|
+
rspec
|
45
|
+
sails!
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Jason Lee
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Sails
|
2
|
+
=====
|
3
|
+
|
4
|
+
Sails, create [Thrift](thrift.apache.org) app server like Rails.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
```
|
9
|
+
$ gem install sails
|
10
|
+
```
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
### Create new project
|
15
|
+
|
16
|
+
```
|
17
|
+
$ sails new foo
|
18
|
+
$ cd foo
|
19
|
+
$ sails start
|
20
|
+
```
|
21
|
+
|
22
|
+
### Generate Thrift IDL
|
23
|
+
|
24
|
+
You can edit Thrift IDL in `app_name.thrift`, and then generate it to ruby source code.
|
25
|
+
|
26
|
+
```
|
27
|
+
$ rake gen
|
28
|
+
```
|
29
|
+
|
30
|
+
|
31
|
+
## API Documents
|
32
|
+
|
33
|
+
http://rdoc.info/github/huacnlee/sails
|
data/bin/sails
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
git_path = File.expand_path('../../.git', __FILE__)
|
3
|
+
|
4
|
+
if File.exist?(git_path)
|
5
|
+
sails_path = File.expand_path('../../lib', __FILE__)
|
6
|
+
$:.unshift(sails_path)
|
7
|
+
require_relative "../lib/sails/cli"
|
8
|
+
end
|
9
|
+
|
10
|
+
source_dir = Dir.pwd
|
11
|
+
if File.exist?(File.join(source_dir,"config/application.rb"))
|
12
|
+
$:.unshift(source_dir)
|
13
|
+
require "config/application"
|
14
|
+
require "sails"
|
15
|
+
else
|
16
|
+
require "sails/cli"
|
17
|
+
end
|
18
|
+
|
19
|
+
Sails::CLI.start(ARGV)
|
data/lib/sails/base.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'active_support/all'
|
4
|
+
require 'i18n'
|
5
|
+
require 'thrift'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
Bundler.require()
|
9
|
+
|
10
|
+
module Sails
|
11
|
+
extend ActiveSupport::Autoload
|
12
|
+
|
13
|
+
class Config
|
14
|
+
include ActiveSupport::Configurable
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.config
|
18
|
+
return @config if defined?(@config)
|
19
|
+
@config = Config.new.config
|
20
|
+
@config.app_name = "Sails"
|
21
|
+
@config.cache_store = [:memory_store]
|
22
|
+
@config.autoload_paths = %W(app/models app/models/concerns app/workers app/services app/services/concerns lib)
|
23
|
+
@config.i18n = I18n
|
24
|
+
@config.i18n.load_path += Dir[Sails.root.join('config', 'locales', '*.{rb,yml}').to_s]
|
25
|
+
@config.i18n.default_locale = :en
|
26
|
+
@config.thrift_processor = nil
|
27
|
+
@config
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.cache
|
31
|
+
return @cache if defined?(@cache)
|
32
|
+
@cache = ActiveSupport::Cache.lookup_store(self.config.cache_store)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sails.root
|
36
|
+
def self.root
|
37
|
+
@root ||= Pathname.new(Dir.pwd)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.root=(root)
|
41
|
+
@root = Pathname.new(root)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Sails.env.development?
|
45
|
+
def self.env
|
46
|
+
@env ||= ActiveSupport::StringInquirer.new(ENV['RAILS_ENV'].presence || 'development')
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.logger
|
50
|
+
return @logger if defined?(@logger)
|
51
|
+
@logger = Logger.new(File.join(Sails.root, "log/#{self.env}.log"))
|
52
|
+
@logger.formatter = proc { |severity, datetime, progname, msg|
|
53
|
+
self.stdout_logger.info msg if !Sails.env.test?
|
54
|
+
"#{msg}\n"
|
55
|
+
}
|
56
|
+
@logger
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.stdout_logger
|
60
|
+
return @stdout_logger if defined?(@stdout_logger)
|
61
|
+
@stdout_logger = Logger.new(STDOUT)
|
62
|
+
@stdout_logger.formatter = proc { |severity, datetime, progname, msg|
|
63
|
+
"#{msg}\n"
|
64
|
+
}
|
65
|
+
@stdout_logger
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.load_initialize
|
69
|
+
Dir["#{Sails.root}/config/initializers/*.rb"].each do |f|
|
70
|
+
require f
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.init
|
75
|
+
$:.unshift self.root.join("lib")
|
76
|
+
# init root
|
77
|
+
return false if @inited == true
|
78
|
+
|
79
|
+
self.root
|
80
|
+
|
81
|
+
ActiveSupport::Dependencies.autoload_paths += Sails.config.autoload_paths
|
82
|
+
|
83
|
+
env_file = self.root.join('config/environments/',Sails.env)
|
84
|
+
if File.exist?(env_file)
|
85
|
+
require env_file
|
86
|
+
end
|
87
|
+
|
88
|
+
require "sails/service"
|
89
|
+
|
90
|
+
puts "ENV: #{Sails.env}"
|
91
|
+
|
92
|
+
load_initialize
|
93
|
+
@inited = true
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.start!(type)
|
97
|
+
if type == "thread"
|
98
|
+
start_thread_pool_server!
|
99
|
+
else
|
100
|
+
start_non_blocking_server!
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.service
|
105
|
+
@service ||= Sails::Service.new
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.start_thread_pool_server!
|
109
|
+
transport = ::Thrift::ServerSocket.new(nil, config.thrift_thread_port)
|
110
|
+
transport_factory = ::Thrift::BufferedTransportFactory.new
|
111
|
+
protocol_factory = ::Thrift::BinaryProtocolFactory.new
|
112
|
+
processor = config.thrift_processor.new(self.service)
|
113
|
+
server = ::Thrift::ThreadPoolServer.new(processor, transport, transport_factory, protocol_factory, Setting.pool_size)
|
114
|
+
|
115
|
+
puts "Boot on: #{Sails.root}"
|
116
|
+
puts "[#{Time.now}] Starting the Sails with ThreadPool size: #{Setting.pool_size}..."
|
117
|
+
puts "serve: #{config.thrift_host}:#{config.thrift_thread_port}"
|
118
|
+
|
119
|
+
begin
|
120
|
+
server.serve
|
121
|
+
rescue => e
|
122
|
+
puts "Start thrift server exception! \n #{e.inspect}"
|
123
|
+
puts e.backtrace
|
124
|
+
|
125
|
+
if self.env != "development"
|
126
|
+
sleep 2
|
127
|
+
retry
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.start_non_blocking_server!
|
133
|
+
transport = ::Thrift::ServerSocket.new(nil, config.thrift_port)
|
134
|
+
transport_factory = ::Thrift::FramedTransportFactory.new
|
135
|
+
protocol_factory = ::Thrift::BinaryProtocolFactory.new
|
136
|
+
processor = config.thrift_processor.new(self.service)
|
137
|
+
server = ::Thrift::NonblockingServer.new(processor, transport, transport_factory)
|
138
|
+
|
139
|
+
puts "Boot on: #{Sails.root}"
|
140
|
+
puts "[#{Time.now}] Starting the Sails with NonBlocking..."
|
141
|
+
puts "serve: #{config.thrift_host}:#{config.thrift_port}"
|
142
|
+
|
143
|
+
begin
|
144
|
+
server.serve
|
145
|
+
rescue => e
|
146
|
+
puts "Start thrift server exception! \n #{e.inspect}"
|
147
|
+
puts e.backtrace
|
148
|
+
|
149
|
+
if self.env != "development"
|
150
|
+
sleep 2
|
151
|
+
retry
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
data/lib/sails/cli.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'sails/version'
|
3
|
+
|
4
|
+
module Sails
|
5
|
+
class ThreadDaemon
|
6
|
+
class << self
|
7
|
+
attr_accessor :options, :mode, :app_name, :pid_file
|
8
|
+
|
9
|
+
def init(opts = {})
|
10
|
+
self.app_name = Sails.config.app_name
|
11
|
+
self.mode = opts[:mode]
|
12
|
+
self.app_name = "#{ThreadDaemon.app_name}-thread" if self.mode == "thread"
|
13
|
+
self.pid_file = Sails.root.join("tmp/#{ThreadDaemon.app_name}.pid")
|
14
|
+
self.options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_pid
|
18
|
+
if !File.exist?(pid_file)
|
19
|
+
return nil
|
20
|
+
end
|
21
|
+
|
22
|
+
pid = File.open(pid_file).read.to_i
|
23
|
+
begin
|
24
|
+
Process.getpgid(pid)
|
25
|
+
rescue
|
26
|
+
pid = nil
|
27
|
+
end
|
28
|
+
return pid
|
29
|
+
end
|
30
|
+
|
31
|
+
def start_process(options = {})
|
32
|
+
$PROGRAM_NAME = self.app_name
|
33
|
+
old_pid = read_pid
|
34
|
+
if old_pid != nil
|
35
|
+
puts "Current have #{app_name} process in running on pid #{old_pid}"
|
36
|
+
return
|
37
|
+
end
|
38
|
+
|
39
|
+
pid = fork do
|
40
|
+
Sails.start!(self.mode)
|
41
|
+
end
|
42
|
+
File.open(pid_file, "w+") do |f|
|
43
|
+
f.puts pid
|
44
|
+
end
|
45
|
+
|
46
|
+
puts "Started #{app_name} on pid: #{pid}"
|
47
|
+
|
48
|
+
if options[:daemon] == false
|
49
|
+
Process.waitpid(pid)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def stop_process
|
54
|
+
pid = read_pid
|
55
|
+
if pid == nil
|
56
|
+
puts "#{app_name} process not found, pid #{pid}"
|
57
|
+
return
|
58
|
+
end
|
59
|
+
|
60
|
+
print "Stopping #{app_name} with pid: #{pid}..."
|
61
|
+
begin
|
62
|
+
Process.kill("QUIT", pid)
|
63
|
+
ensure
|
64
|
+
File.delete(pid_file)
|
65
|
+
end
|
66
|
+
puts " [Done]"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class CLI < Thor
|
72
|
+
include Thor::Actions
|
73
|
+
|
74
|
+
map '-v' => :version
|
75
|
+
|
76
|
+
def self.source_root
|
77
|
+
__dir__
|
78
|
+
end
|
79
|
+
|
80
|
+
no_commands {
|
81
|
+
def app_name
|
82
|
+
@app_name
|
83
|
+
end
|
84
|
+
}
|
85
|
+
|
86
|
+
option :daemon, type: :boolean, default: false
|
87
|
+
option :mode, default: 'nonblocking'
|
88
|
+
desc "start", "Start Thrift server"
|
89
|
+
def start()
|
90
|
+
ThreadDaemon.init(mode: options[:mode])
|
91
|
+
ThreadDaemon.start_process(daemon: options[:daemon])
|
92
|
+
end
|
93
|
+
|
94
|
+
option :mode, default: 'nonblocking'
|
95
|
+
desc "stop", "Stop Thrift server"
|
96
|
+
def stop()
|
97
|
+
ThreadDaemon.init(mode: options[:mode])
|
98
|
+
ThreadDaemon.stop_process
|
99
|
+
end
|
100
|
+
|
101
|
+
option :mode, default: 'nonblocking'
|
102
|
+
desc "restart", "Restart Thrift server"
|
103
|
+
def restart()
|
104
|
+
ThreadDaemon.init(mode: options[:mode])
|
105
|
+
ThreadDaemon.stop_process
|
106
|
+
ThreadDaemon.start_process(daemon: true)
|
107
|
+
end
|
108
|
+
|
109
|
+
desc "new APP_NAME", "Create a project"
|
110
|
+
def new name
|
111
|
+
require 'fileutils'
|
112
|
+
|
113
|
+
app_dir = File.expand_path File.join(Dir.pwd, name)
|
114
|
+
@rel_dir = name
|
115
|
+
@app_name = File.basename app_dir
|
116
|
+
templte_dir = File.join(File.dirname(__FILE__), "templates")
|
117
|
+
|
118
|
+
directory 'templates', name
|
119
|
+
%W(log tmp/pids tmp/cache lib/tasks app/models/concerns config/initializers log).each do |dir_name|
|
120
|
+
empty_directory File.join(app_dir,dir_name)
|
121
|
+
end
|
122
|
+
puts ''
|
123
|
+
ensure
|
124
|
+
@app_name = nil
|
125
|
+
@rel_dir = nil
|
126
|
+
end
|
127
|
+
|
128
|
+
desc "version", "Show Sails version"
|
129
|
+
def version
|
130
|
+
puts "Sails #{Sails.version}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/lib/sails/rails.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
module Sails
|
2
|
+
class Service
|
3
|
+
include ActiveSupport::Callbacks
|
4
|
+
define_callbacks :action
|
5
|
+
|
6
|
+
set_callback :action, :before do |object|
|
7
|
+
end
|
8
|
+
|
9
|
+
set_callback :action, :after do |object|
|
10
|
+
ActiveRecord::Base.clear_active_connections! if defined?(ActiveRecord::Base)
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(method_name, *args, &block)
|
14
|
+
run_callbacks :action do
|
15
|
+
time = Time.now.to_f
|
16
|
+
|
17
|
+
Sails.logger.info "\nProcessing by \"#{method_name}\" at #{Time.now.to_s}" unless Sails.env.test?
|
18
|
+
Sails.logger.info " Parameters: { #{args.map(&:inspect).join(', ')} }" unless Sails.env.test?
|
19
|
+
|
20
|
+
begin
|
21
|
+
res = interface.send(method_name, *args, &block)
|
22
|
+
status = "Completed"
|
23
|
+
return res
|
24
|
+
rescue ActiveRecord::RecordNotFound => e
|
25
|
+
status = "Not Found"
|
26
|
+
interface.raise_error(-1004)
|
27
|
+
rescue ThriftServer::OperationFailed => e
|
28
|
+
status = "Failed #{e.code}"
|
29
|
+
raise e
|
30
|
+
rescue => e
|
31
|
+
status = "Error 500"
|
32
|
+
Sails.logger.info "\"#{method_name}\" error : #{e.inspect}\n\n"
|
33
|
+
Sails.logger.info %Q(backtrace: #{e.backtrace.join("\n")}\n)
|
34
|
+
interface.raise_error(-1000)
|
35
|
+
ensure
|
36
|
+
elapsed = format('%.3f', (Time.now.to_f - time) * 1000)
|
37
|
+
Sails.logger.info "#{status} in (#{elapsed}ms).\n\n" unless Sails.env.test?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def args
|
43
|
+
@args ||= []
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(*array)
|
47
|
+
args.concat array
|
48
|
+
end
|
49
|
+
|
50
|
+
class Interface
|
51
|
+
Dir["#{Sails.root.join("app/services")}/*_service.rb"].each do |f|
|
52
|
+
next if 'base_service.rb' == File.basename(f)
|
53
|
+
if File.basename(f) =~ /^(.*)_service.rb$/
|
54
|
+
require f
|
55
|
+
mtd = $1.dup
|
56
|
+
klass_name = "#{mtd.camelize}Service"
|
57
|
+
include klass_name.constantize
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def raise_error code, msg = nil
|
62
|
+
raise ThriftServer::OperationFailed.new(
|
63
|
+
code: code,
|
64
|
+
message: msg
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
def logger
|
69
|
+
Sails.logger
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def interface
|
74
|
+
@interface ||= Interface.new
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
namespace rb Thrift
|
2
|
+
|
3
|
+
struct Session {
|
4
|
+
1:i64 user_id,
|
5
|
+
2:string access_token
|
6
|
+
}
|
7
|
+
|
8
|
+
exception OperationFailed {
|
9
|
+
1: i32 code,
|
10
|
+
2: string message
|
11
|
+
}
|
12
|
+
|
13
|
+
service <%= @app_name.capitalize %> {
|
14
|
+
|
15
|
+
// ping <-> pong
|
16
|
+
string ping() throws (1:OperationFailed failure)
|
17
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
activemodel (4.2.0.rc2)
|
5
|
+
activesupport (= 4.2.0.rc2)
|
6
|
+
builder (~> 3.1)
|
7
|
+
activerecord (4.2.0.rc2)
|
8
|
+
activemodel (= 4.2.0.rc2)
|
9
|
+
activesupport (= 4.2.0.rc2)
|
10
|
+
arel (~> 6.0)
|
11
|
+
activesupport (4.2.0.rc2)
|
12
|
+
i18n (>= 0.7.0.beta1, < 0.8)
|
13
|
+
json (~> 1.7, >= 1.7.7)
|
14
|
+
minitest (~> 5.1)
|
15
|
+
thread_safe (~> 0.1)
|
16
|
+
tzinfo (~> 1.1)
|
17
|
+
arel (6.0.0)
|
18
|
+
builder (3.2.2)
|
19
|
+
daemons (1.1.9)
|
20
|
+
eventmachine (1.0.3)
|
21
|
+
i18n (0.7.0.beta1)
|
22
|
+
json (1.8.1)
|
23
|
+
minitest (5.4.3)
|
24
|
+
rack (1.5.2)
|
25
|
+
sails (0.1.0)
|
26
|
+
activesupport (>= 3.2.0)
|
27
|
+
thor
|
28
|
+
thrift (>= 0.9.0)
|
29
|
+
thin (1.6.3)
|
30
|
+
daemons (~> 1.0, >= 1.0.9)
|
31
|
+
eventmachine (~> 1.0)
|
32
|
+
rack (~> 1.0)
|
33
|
+
thor (0.19.1)
|
34
|
+
thread_safe (0.3.4)
|
35
|
+
thrift (0.9.2.0)
|
36
|
+
tzinfo (1.2.2)
|
37
|
+
thread_safe (~> 0.1)
|
38
|
+
|
39
|
+
PLATFORMS
|
40
|
+
ruby
|
41
|
+
|
42
|
+
DEPENDENCIES
|
43
|
+
activerecord (~> 4.2.0.rc2)
|
44
|
+
sails
|
45
|
+
thin
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rubygems"
|
3
|
+
|
4
|
+
require File.expand_path('../config/application.rb', __FILE__)
|
5
|
+
|
6
|
+
Dir.glob('lib/tasks/*.rake').each { |r| import r }
|
7
|
+
|
8
|
+
task :default => :test
|
9
|
+
|
10
|
+
task :console do
|
11
|
+
puts "Starting thrift-server console..."
|
12
|
+
system "pry -I config/application.rb -r ./config/application.rb"
|
13
|
+
end
|
14
|
+
|
15
|
+
task :gen do
|
16
|
+
puts "Generating thrift code..."
|
17
|
+
system 'thrift \
|
18
|
+
--gen rb \
|
19
|
+
-out app/services/gen-rb \
|
20
|
+
-strict \
|
21
|
+
-debug \
|
22
|
+
-verbose \
|
23
|
+
<%= app_name %>.thrift'
|
24
|
+
|
25
|
+
puts "[Done]"
|
26
|
+
end
|
27
|
+
|
28
|
+
task :test do
|
29
|
+
system 'rspec spec'
|
30
|
+
end
|
31
|
+
|
32
|
+
load 'active_record/railties/databases.rake'
|
33
|
+
|
34
|
+
class << ActiveRecord::Tasks::DatabaseTasks
|
35
|
+
def env
|
36
|
+
@env ||= Sails.env
|
37
|
+
end
|
38
|
+
|
39
|
+
def migrations_paths
|
40
|
+
[File.expand_path('../db/migrate', __FILE__)]
|
41
|
+
end
|
42
|
+
|
43
|
+
def database_configuration
|
44
|
+
YAML.load open(File.expand_path('../config/database.yml', __FILE__)).read
|
45
|
+
end
|
46
|
+
|
47
|
+
def db_dir
|
48
|
+
File.expand_path('../db', __FILE__)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
task :environment do
|
53
|
+
require File.expand_path('../config/application.rb', __FILE__)
|
54
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sails'
|
2
|
+
$LOAD_PATH.unshift Sails.root
|
3
|
+
|
4
|
+
Bundler.require()
|
5
|
+
|
6
|
+
require "app/services/handler"
|
7
|
+
|
8
|
+
module Sails
|
9
|
+
config.app_name = '<%= app_name %>'
|
10
|
+
# Thrift Configs
|
11
|
+
config.thrift_host = '127.0.0.1'
|
12
|
+
config.thrift_port = 4000
|
13
|
+
config.thrift_processor = Thrift::<%= app_name.capitalize %>::Processor
|
14
|
+
|
15
|
+
# config.autoload_paths += %W(app/workers)
|
16
|
+
|
17
|
+
config.i18n.default_locale = 'zh-CN'
|
18
|
+
|
19
|
+
# cache store
|
20
|
+
# config.cache_store = [:dalli_store, '127.0.0.1']
|
21
|
+
end
|
22
|
+
|
23
|
+
Sails.init()
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,203 @@
|
|
1
|
+
zh-CN:
|
2
|
+
date:
|
3
|
+
abbr_day_names:
|
4
|
+
- 日
|
5
|
+
- 一
|
6
|
+
- 二
|
7
|
+
- 三
|
8
|
+
- 四
|
9
|
+
- 五
|
10
|
+
- 六
|
11
|
+
abbr_month_names:
|
12
|
+
-
|
13
|
+
- 1月
|
14
|
+
- 2月
|
15
|
+
- 3月
|
16
|
+
- 4月
|
17
|
+
- 5月
|
18
|
+
- 6月
|
19
|
+
- 7月
|
20
|
+
- 8月
|
21
|
+
- 9月
|
22
|
+
- 10月
|
23
|
+
- 11月
|
24
|
+
- 12月
|
25
|
+
day_names:
|
26
|
+
- 星期日
|
27
|
+
- 星期一
|
28
|
+
- 星期二
|
29
|
+
- 星期三
|
30
|
+
- 星期四
|
31
|
+
- 星期五
|
32
|
+
- 星期六
|
33
|
+
formats:
|
34
|
+
default: ! '%Y-%m-%d'
|
35
|
+
long: ! '%Y年%b%d日'
|
36
|
+
short: ! '%b%d日'
|
37
|
+
month_names:
|
38
|
+
-
|
39
|
+
- 一月
|
40
|
+
- 二月
|
41
|
+
- 三月
|
42
|
+
- 四月
|
43
|
+
- 五月
|
44
|
+
- 六月
|
45
|
+
- 七月
|
46
|
+
- 八月
|
47
|
+
- 九月
|
48
|
+
- 十月
|
49
|
+
- 十一月
|
50
|
+
- 十二月
|
51
|
+
order:
|
52
|
+
- :year
|
53
|
+
- :month
|
54
|
+
- :day
|
55
|
+
datetime:
|
56
|
+
distance_in_words:
|
57
|
+
about_x_hours:
|
58
|
+
one: 大约一小时
|
59
|
+
other: 大约 %{count} 小时
|
60
|
+
about_x_months:
|
61
|
+
one: 大约一个月
|
62
|
+
other: 大约 %{count} 个月
|
63
|
+
about_x_years:
|
64
|
+
one: 大约一年
|
65
|
+
other: 大约 %{count} 年
|
66
|
+
almost_x_years:
|
67
|
+
one: 接近一年
|
68
|
+
other: 接近 %{count} 年
|
69
|
+
half_a_minute: 半分钟
|
70
|
+
less_than_x_minutes:
|
71
|
+
one: 不到一分钟
|
72
|
+
other: 不到 %{count} 分钟
|
73
|
+
less_than_x_seconds:
|
74
|
+
one: 不到一秒
|
75
|
+
other: 不到 %{count} 秒
|
76
|
+
over_x_years:
|
77
|
+
one: 一年多
|
78
|
+
other: ! '%{count} 年多'
|
79
|
+
x_days:
|
80
|
+
one: 一天
|
81
|
+
other: ! '%{count} 天'
|
82
|
+
x_minutes:
|
83
|
+
one: 一分钟
|
84
|
+
other: ! '%{count} 分钟'
|
85
|
+
x_months:
|
86
|
+
one: 一个月
|
87
|
+
other: ! '%{count} 个月'
|
88
|
+
x_seconds:
|
89
|
+
one: 一秒
|
90
|
+
other: ! '%{count} 秒'
|
91
|
+
prompts:
|
92
|
+
day: 日
|
93
|
+
hour: 时
|
94
|
+
minute: 分
|
95
|
+
month: 月
|
96
|
+
second: 秒
|
97
|
+
year: 年
|
98
|
+
errors:
|
99
|
+
format: ! '%{attribute}%{message}'
|
100
|
+
messages:
|
101
|
+
accepted: 必须是可被接受的
|
102
|
+
blank: 不能为空字符
|
103
|
+
present: 必须是空白
|
104
|
+
confirmation: 与确认值不匹配
|
105
|
+
empty: 不能留空
|
106
|
+
equal_to: 必须等于 %{count}
|
107
|
+
even: 必须为双数
|
108
|
+
exclusion: 是保留关键字
|
109
|
+
greater_than: 必须大于 %{count}
|
110
|
+
greater_than_or_equal_to: 必须大于或等于 %{count}
|
111
|
+
inclusion: 不包含于列表中
|
112
|
+
invalid: 是无效的
|
113
|
+
less_than: 必须小于 %{count}
|
114
|
+
less_than_or_equal_to: 必须小于或等于 %{count}
|
115
|
+
not_a_number: 不是数字
|
116
|
+
not_an_integer: 必须是整数
|
117
|
+
odd: 必须为单数
|
118
|
+
record_invalid: ! '验证失败: %{errors}'
|
119
|
+
restrict_dependent_destroy:
|
120
|
+
one: 由于 %{record} 需要此记录,所以无法移除记录
|
121
|
+
many: 由于 %{record} 需要此记录,所以无法移除记录
|
122
|
+
taken: 已经被使用
|
123
|
+
too_long:
|
124
|
+
one: 过长(最长为一个字符)
|
125
|
+
other: 过长(最长为 %{count} 个字符)
|
126
|
+
too_short:
|
127
|
+
one: 过短(最短为一个字符)
|
128
|
+
other: 过短(最短为 %{count} 个字符)
|
129
|
+
wrong_length:
|
130
|
+
one: 长度非法(必须为一个字符)
|
131
|
+
other: 长度非法(必须为 %{count} 个字符)
|
132
|
+
other_than: 长度非法(不可为 %{count} 个字符
|
133
|
+
template:
|
134
|
+
body: 如下字段出现错误:
|
135
|
+
header:
|
136
|
+
one: 有 1 个错误发生导致「%{model}」无法被保存。
|
137
|
+
other: 有 %{count} 个错误发生导致「%{model}」无法被保存。
|
138
|
+
helpers:
|
139
|
+
select:
|
140
|
+
prompt: 请选择
|
141
|
+
submit:
|
142
|
+
create: 新增%{model}
|
143
|
+
submit: 储存%{model}
|
144
|
+
update: 更新%{model}
|
145
|
+
number:
|
146
|
+
currency:
|
147
|
+
format:
|
148
|
+
delimiter: ! ','
|
149
|
+
format: ! '%u %n'
|
150
|
+
precision: 2
|
151
|
+
separator: .
|
152
|
+
significant: false
|
153
|
+
strip_insignificant_zeros: false
|
154
|
+
unit: CN¥
|
155
|
+
format:
|
156
|
+
delimiter: ! ','
|
157
|
+
precision: 3
|
158
|
+
separator: .
|
159
|
+
significant: false
|
160
|
+
strip_insignificant_zeros: false
|
161
|
+
human:
|
162
|
+
decimal_units:
|
163
|
+
format: ! '%n %u'
|
164
|
+
units:
|
165
|
+
billion: 十亿
|
166
|
+
million: 百万
|
167
|
+
quadrillion: 千兆
|
168
|
+
thousand: 千
|
169
|
+
trillion: 兆
|
170
|
+
unit: ''
|
171
|
+
format:
|
172
|
+
delimiter: ''
|
173
|
+
precision: 1
|
174
|
+
significant: false
|
175
|
+
strip_insignificant_zeros: false
|
176
|
+
storage_units:
|
177
|
+
format: ! '%n %u'
|
178
|
+
units:
|
179
|
+
byte:
|
180
|
+
one: Byte
|
181
|
+
other: Bytes
|
182
|
+
gb: GB
|
183
|
+
kb: KB
|
184
|
+
mb: MB
|
185
|
+
tb: TB
|
186
|
+
percentage:
|
187
|
+
format:
|
188
|
+
delimiter: ''
|
189
|
+
precision:
|
190
|
+
format:
|
191
|
+
delimiter: ''
|
192
|
+
support:
|
193
|
+
array:
|
194
|
+
last_word_connector: ! ', 和 '
|
195
|
+
two_words_connector: ! ' 和 '
|
196
|
+
words_connector: ! ', '
|
197
|
+
time:
|
198
|
+
am: 上午
|
199
|
+
formats:
|
200
|
+
default: ! '%Y年%b%d日 %A %H:%M:%S %Z'
|
201
|
+
long: ! '%Y年%b%d日 %H:%M'
|
202
|
+
short: ! '%b%d日 %H:%M'
|
203
|
+
pm: 下午
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# This file should contain all the record creation needed to seed the database with its default values.
|
2
|
+
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
|
3
|
+
#
|
4
|
+
# Examples:
|
5
|
+
#
|
6
|
+
# cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
|
7
|
+
# Mayor.create(name: 'Emanuel', city: cities.first)
|
data/lib/sails.rb
ADDED
data/sails.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require File.expand_path('lib/sails/version')
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "sails"
|
7
|
+
s.version = Sails.version
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Jason Lee"]
|
10
|
+
s.email = ["huacnlee@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/huacnlee/sails"
|
12
|
+
s.summary = %q{Sails, create Thrift Server use like Rails}
|
13
|
+
s.description = %q{Sails, create Thrift Server use like Rails}
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = ["sails"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.license = 'MIT'
|
19
|
+
|
20
|
+
s.add_dependency "activesupport", [">= 3.2.0"]
|
21
|
+
s.add_dependency "thrift", [">= 0.9.0"]
|
22
|
+
s.add_dependency "thor"
|
23
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# Logfile created on 2014-12-08 13:02:26 +0800 by logger.rb/44203
|
data/spec/spec_helper.rb
ADDED
data/spec/tails_spec.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe 'Sails' do
|
4
|
+
it { expect(Sails.version).not_to be_nil }
|
5
|
+
|
6
|
+
describe '#root' do
|
7
|
+
it 'should be a Pathname class' do
|
8
|
+
expect(Sails.root).to be_a(Pathname)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should support Sails.root.join' do
|
12
|
+
expect(Sails.root.join("aaa").to_s).to eq File.join(Dir.pwd, "spec/dummy/aaa")
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should work' do
|
16
|
+
expect(Sails.root.to_s).to eq File.join(Dir.pwd, "spec/dummy")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#logger' do
|
21
|
+
it 'should be a Logger class' do
|
22
|
+
expect(Sails.logger).to be_a(Logger)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#config' do
|
27
|
+
it 'should work' do
|
28
|
+
expect(Sails.config).to be_a(Hash)
|
29
|
+
expect(Sails.config.autoload_paths).to be_a(Array)
|
30
|
+
expect(Sails.config.app_name).to eq "Sails"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jason Lee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.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: 3.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thrift
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.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.9.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: thor
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Sails, create Thrift Server use like Rails
|
56
|
+
email:
|
57
|
+
- huacnlee@gmail.com
|
58
|
+
executables:
|
59
|
+
- sails
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- Gemfile
|
65
|
+
- Gemfile.lock
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
- bin/sails
|
69
|
+
- lib/sails.rb
|
70
|
+
- lib/sails/base.rb
|
71
|
+
- lib/sails/cli.rb
|
72
|
+
- lib/sails/rails.rb
|
73
|
+
- lib/sails/service.rb
|
74
|
+
- lib/sails/templates/%app_name%.thrift.tt
|
75
|
+
- lib/sails/templates/Gemfile
|
76
|
+
- lib/sails/templates/Gemfile.lock
|
77
|
+
- lib/sails/templates/Rakefile.tt
|
78
|
+
- lib/sails/templates/app/services/application_service.rb.tt
|
79
|
+
- lib/sails/templates/app/services/gen-rb/%app_name%.rb.tt
|
80
|
+
- lib/sails/templates/app/services/handler.rb.tt
|
81
|
+
- lib/sails/templates/config/application.rb.tt
|
82
|
+
- lib/sails/templates/config/boot.rb
|
83
|
+
- lib/sails/templates/config/database.yml
|
84
|
+
- lib/sails/templates/config/environments/development.rb
|
85
|
+
- lib/sails/templates/config/environments/production.rb
|
86
|
+
- lib/sails/templates/config/environments/test.rb
|
87
|
+
- lib/sails/templates/config/locales/en.yml
|
88
|
+
- lib/sails/templates/config/locales/rails.zh-CN.yml
|
89
|
+
- lib/sails/templates/config/locales/zh-CN.yml
|
90
|
+
- lib/sails/templates/db/seeds.rb
|
91
|
+
- lib/sails/version.rb
|
92
|
+
- sails.gemspec
|
93
|
+
- spec/dummy/log/development.log
|
94
|
+
- spec/spec_helper.rb
|
95
|
+
- spec/tails_spec.rb
|
96
|
+
homepage: https://github.com/huacnlee/sails
|
97
|
+
licenses:
|
98
|
+
- MIT
|
99
|
+
metadata: {}
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - ">="
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
requirements: []
|
115
|
+
rubyforge_project:
|
116
|
+
rubygems_version: 2.4.2
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Sails, create Thrift Server use like Rails
|
120
|
+
test_files:
|
121
|
+
- spec/dummy/log/development.log
|
122
|
+
- spec/spec_helper.rb
|
123
|
+
- spec/tails_spec.rb
|
124
|
+
has_rdoc:
|