差分表示
- 最後の更新で追加された行はこのように表示します。
- 最後の更新で削除された行は
このように表示します。
---(
# Basic
%!STRING! : ダブルクォート文字列
%Q!STRING! : 同上
%q!STRING! : シングルクォート文字列
%w!STRING! : 要素が文字列の配列(空白区切り)
%W!STRING! : 要素が文字列の配列(空白区切り)。式展開、バックスラッシュ記法が有効
%w!credit debit_ap fee tx_fee!.map(&:to_sym) シンボルの配列
strftime("%F") 2015-01-07
strftime("%Y/%m/%d %H:%M:%S") 2015/01/07 21:12:32
puts [a, b, c, d].join(' ')
# 文字コード
Encoding.default_external = Encoding::UTF_8
# Nokogiri
doc = Nokogiri::HTML(open(url).read)
doc.css('p.parent > text()') node text without children
node['attr']
# Mechanize
agent = Mechanize.new
# agent.log = Logger.new(STDOUT)
agent.get("https://example.com/login")
form = agent.page.forms.first
form["username"] = config["username"]
form["password"] = config["password"]
form.submit
agent.get("https://example.com/target")
doc = Nokogiri::HTML(agent.page.body)
data = parse_page(doc)
# Active support
gem 'activesupport'
require 'active_support/core_ext'
Time.now + 2.months
# mongoid
class Earning
include Mongoid::Document
include Mongoid::Timestamps::Created
field :title, type: String
field :open_at, type: Time
field :total, type: Float
index({ created_at: 1 }, { name: "created_at_index" })
end
Earning.create_indexes
team = Team.find_or_initialize_by(name: @team_name)
team.content = params[:content]
team.save!
# haml
%table.table{ style: 'width: 40%' }
%tr
%td 最終更新時刻
%td= @last_update.strftime('%Y/%m/%d %H:%M:%S')
%tr
%td ツイート数
%td= @tweet_count
%tr
%td 削除イベント数
%td= @delete_count
---)
* JSON
symbolize_namesを入れるとパターンマッチングと相性がいい
キーがシンボルでも、to_jsonすると文字列に変換される
---(
JSON.parse(File.read("hoge.json"), symbolize_names: true)
---)
* 正規表現
---(
str[regexp] 最初にマッチした部分文字列
%r|RegExp| 正規表現リテラル
%r|OPEN\s+(?<open_at>\d+:\d+)\s+/\s+START\s+(?<close_at>\d+:\d+)| 名前付きキャプチャ
# 複数のマッチを変数に分解
# 参考: https://docs.ruby-lang.org/ja/latest/method/Regexp/i/match.html
_, foo, bar, baz = */(foo)(bar)(baz)/.match("foobarbaz")
---)
* パターンマッチング
2.7と3.0で仕様変更あり。以下は3.0(inがboolを返す)
---(
irb(main):007:1* if {a: 42, b: 24, c: 12} in {a:, b:, c:}
irb(main):008:1* puts a, b, c
irb(main):009:0> end
42
24
12
---)
マッチしない場合に例外を出したければ => を使う
---(
irb(main):021:0> {a: 42, b: 24} => {a:, b:, c:}
irb(main):022:0> puts a, b, c
(irb):21:in `<main>': {:a=>42, :b=>24} (NoMatchingPatternError)
---)
* clockwork
skip_first_runおすすめ。起動直後のジョブ実行を行わない。デバッグ中に何度も起動した場合に、APIのレートリミットを使い果たすのを避けられる
every(10.minutes, "crawl_home", :skip_first_run => true)
* お手軽にテストを書く
http://d.hatena.ne.jp/shingo-zukunashi/20121010/1349868645
if __FILE__ == $0
#テストコード
end
* struct
Hashよりメンバが明示的でいい
[[【Ruby】Struct(構造体クラス)を理解する - Qiita>https://qiita.com/k-penguin-sato/items/54189d5ed4e5f7463266]]
* 外部プロセスを並列実行
---(
require "open3"
require "thwait"
class Runner
def initialize
@failed_cmds = []
end
def run_parallel(cmds)
contexts = []
threads = []
cmds.each do |cmd|
stdin, stdout, stderr, wait_thread = *Open3.popen3(cmd)
stdin.close
contexts << {
"cmd" => cmd,
"stdout" => stdout,
"stderr" => stderr,
"wait_thread" => wait_thread,
}
threads << wait_thread
end
ThreadsWait.all_waits(*threads)
ret = true
contexts.each do |context|
puts context["cmd"]
puts context["stdout"].read.encode(Encoding::UTF_8, Encoding::Shift_JIS)
puts context["stderr"].read.encode(Encoding::UTF_8, Encoding::Shift_JIS)
unless context["wait_thread"].value.success?
@failed_cmds << context["cmd"]
ret = false
end
end
ret
end
attr_reader :failed_cmds
end
runner = Runner.new
runner.run_parallel(cmds)
if runner.failed_cmds.empty?
puts "全コマンドの実行に成功しました"
else
puts "下記のコマンドの実行に失敗しました"
puts runner.failed_cmds.join("\n")
end
---)