sails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|