# 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 外部プロセスを並列実行
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 |