原发于: http://bbs.yundianjia.net/d/111-2-ruby-gem
写的不好,希望大家吐槽拉。这里贴出的代码,是最初一个版本的,后续的修改,可以参考 https://github.com/xiajian/bbs_uploader,代码没写测试。确实是个硬伤。更多关于 gem 编写的介绍: http://guides.rubygems.org/make-your-own-gem/
如何创建一个 gem,并将其发布到 rubygems 上,让世界感受你的代码中蕴含的洪荒的力量,从此展开征服世界旅程。。。。。
从一个小的功能开始,比如将 论坛中图片上传 七牛 上,这个小的功能,名字就取得通俗一点: bbs_uploader
1 创建一个新的 gem 目录:
bundle gem bbs_uploader
生成如下的目录:
bbs_uploader
├── CODE_OF_CONDUCT.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bbs_uploader.gemspec
├── bin
│ ├── console
│ └── setup
└── lib
├── bbs_uploader
│ └── version.rb
└── bbs_uploader.rb
bbs_uploader.gemspec:
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'bbs_uploader/version'
Gem::Specification.new do |spec|
spec.name = "bbs_uploader"
spec.version = BbsUploader::VERSION
spec.authors = ["xiajian"]
spec.email = ["[email protected]"]
spec.summary = %q{简单分装七牛上传的图片类}
spec.description = %q{简单封装七牛的图片上传,并演示如何创建 gem 的功能}
spec.homepage = "https://github.com/xiajian/bbs_uploader"
spec.license = "MIT"
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
# delete this section to allow pushing this gem to any host.
if spec.respond_to?(:metadata)
spec.metadata['allowed_push_host'] = "https://rubygems.org"
else
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
end
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.bindir = "bin"
spec.executables = ['bbs_uploader']
spec.require_paths = ["lib"]
spec.add_dependency "qiniu", "~> 6.8.1"
spec.add_development_dependency "bundler", "~> 1.10"
spec.add_development_dependency "rake", "~> 10.0"
end
lib/bbs_uploader.rb
# 参考: http://bbs.yundianjia.net/d/110--
require "qiniu"
require "bbs_uploader/version"
module BbsUploader
# Your code goes here...
IMAGE_URL_REGEXP = /http:\/\/.*[jpg|png|jpeg]$/
class << self
@@qiniu = {}
# 初始化全局变量 @@qiniu
def qiniu=(options)
@@qiniu = default_options(options)
end
def qiniu
@@qiniu != {} ? @@qiniu : default_options
end
def default_options(options = {})
{
access_key: "79WvzAxvV-nOEX7m0PERzwR0Lhm-FDHriz2-QdAN",
secret_key: "4wwnWNU16n9uVK8DHRW6qO61b2gls3aSduHswkvc",
bucket: "bss-image",
bucket_domain: "ognvcf5x6.bkt.clouddn.com"
}.merge(options)
end
def upload_image(file_path)
# 构建鉴权对象
Qiniu.establish_connection! access_key: self.qiniu[:access_key],
secret_key: self.qiniu[:secret_key]
key = "bbs_image/#{File.basename(file_path)}"
put_policy = Qiniu::Auth::PutPolicy.new(
self.qiniu[:bucket], # 存储空间
key, # 指定上传的资源名,如果传入 nil,就表示不指定资源名,将使用默认的资源名
3600 # token 过期时间,默认为 3600 秒,即 1 小时
)
uptoken = Qiniu::Auth.generate_uptoken(put_policy)
# 调用 upload_with_token_2 方法上传
code, result = Qiniu::Storage.upload_with_token_2(
uptoken,
file_path,
key,
nil, # 可以接受一个 Hash 作为自定义变量,请参照 http://developer.qiniu.com/article/kodo/kodo-developer/up/vars.html#xvar
bucket: self.qiniu[:bucket]
)
if code == 200
image_url = "http://#{self.qiniu[:bucket_domain]}/#{result['key']}"
puts "图片上传成功! \n链接为: #{image_url} \nmarkdown 链接: #{markdown_image_link(image_url)}"
image_url
else
puts '上传图片失败'
nil
end
rescue => e
puts "上传图片发生异常: #{e}"
nil
end
def markdown_image_link(image_url)
if image_url && image_url.is_a?(String) && IMAGE_URL_REGEXP.match(image_url)
"![](#{image_url})"
else
''
end
end
# 根据目录下指定目录下的文件,将文件上传到七牛上
#
# @note 注意文件需要按照文件目录的自然顺序
def generate_markdown_format(dir)
content = ''
files = []
`ls #{dir}`.split('\n').map { |filename| files << "#{dir}/#{filename}" }
files.each do |file|
content << markdown_image_link(upload_image(file)) + "\n"
end
puts content
content
end
end
end
bin/bbs_uploader
#!/usr/bin/env ruby
require 'json'
require 'psych'
require 'optparse'
require 'bundler/setup'
require 'bbs_uploader'
options = {}
OptionParser.new do |opts|
opts.banner = "Usage: bbs_uploader [options]"
opts.on_tail('-h', '--help', 'Show this message') do
puts opts
exit
end
opts.on_tail('-v', '--version', 'Print version') do
puts "bbs_uploader #{BbsUploader::VERSION}"
exit
end
opts.on('-i', '--input-file [file]', 'Default: xxx.jpg') do |file|
unless File.exist? file
puts "输入的文件 #{file} 不存在,请检查后重试"
exit
end
options[:input_file] = File.absolute_path file
end
end.parse!
if options[:input_file].nil?
file = ARGV[0]
if !file.nil? && File.exists?(file)
options[:input_file] = File.absolute_path file
elsif !file.nil?
puts "输入的文件 #{ARGV[0]} 不存在,请检查后重试"
exit
elsif file.nil?
puts "没有选择上传的图片"
exit
end
end
BbsUploader.upload_image options[:input_file]
至此,代码算是也好了,可以在本地测试一下,是否正常:
bin/bbs_uploader /Users/xiajian/Downloads/test.jpg
D, [2016-11-15T13:09:03.811865 #23391] DEBUG -- : Query bss-image hosts Success: {"ttl"=>86400, "http"=>{"io"=>["http://iovip.qbox.me"], "up"=>["http://up.qiniu.com", "http://upload.qiniu.com", "-H up.qiniu.com http://183.136.139.16"]}, "https"=>{"io"=>["https://iovip.qbox.me"], "up"=>["https://up.qbox.me"]}}
图片上传成功!
链接为: http://ognvcf5x6.bkt.clouddn.com/bbs_image/test.jpg
markdown 链接: ![](http://ognvcf5x6.bkt.clouddn.com/bbs_image/test.jpg)
在项目中执行,将代码推送到远程:
git init
git add -A
git commit -m"first comment"
git remote add origin [email protected]:xiajian/bbs_uploader.git
git push -u origin master
执行 rake release 发布 gem 包。
$ rake release
bbs_uploader 0.1.0 built to pkg/bbs_uploader-0.1.0.gem.
Tagged v0.1.0.
Pushed git commits and tags.
Pushed bbs_uploader 0.1.0 to rubygems.org.
rubygems 上项目的地址: https://rubygems.org/gems/bbs_uploader
此刻,过个 30 分钟(taobao 同步 Rubygems 的时间间隔的 2 倍),就可以 gem install bbs_uploader
命令行使用:
使用指南:
Usage: bbs_uploader [options]
-i, --input-file [file] Default: xxx.jpg
-h, --help Show this message
-v, --version Print version
调用实例:
bbs_uploader ~/Downloads/test.jpg
D, [2016-11-15T16:31:52.906672 #30130] DEBUG -- : Query bss-image hosts Success: {"ttl"=>86400, "http"=>{"io"=>["http://iovip.qbox.me"], "up"=>["http://up.qiniu.com", "http://upload.qiniu.com", "-H up.qiniu.com http://183.136.139.16"]}, "https"=>{"io"=>["https://iovip.qbox.me"], "up"=>["https://up.qbox.me"]}}
图片上传成功!
链接为: http://ognvcf5x6.bkt.clouddn.com/bbs_image/test.jpg
markdown 链接: ![](http://ognvcf5x6.bkt.clouddn.com/bbs_image/test.jpg)
编程使用:
BbsUploader.qiniu = {
access_key: 'your access key',
secret_key: 'your secret key',
bucket: "your bucket",
bucket_domain: "your application domain"
}
BbsUploader.upload_image '~/Downloads/test.jpg'
至此,全文完!!!!