Skip to content

Instantly share code, notes, and snippets.

@hamakn
Last active March 1, 2018 06:25
Show Gist options
  • Save hamakn/a8c43d87d5fd70ac9c0c703806acfbf3 to your computer and use it in GitHub Desktop.
Save hamakn/a8c43d87d5fd70ac9c0c703806acfbf3 to your computer and use it in GitHub Desktop.
My Rubyレシピブック

Gemfileに書かずにプロジェクトにgemを加える

  • 背景・動機・目的
    • 非公開なgemを使うプロジェクトがある場合に、そのプロジェクトを非公開なgemがない場合でも(それなりに)動くようにしたい
      • 委託するとか
        • その際のVPNの申請がめんどいとか...
      • herokuに上げるとか
      • 譲渡するとか
    • そういう背景なので、そもそもそのgemがないと根本的に動作しないようなケースは考慮しない
    • bundlerの便利な仕組みは活用したい

方法

  • 非公開なgemに依存しないGemfileと、依存するGemfile.in(名前はなんでもいい)を用意し、状況に応じて使い分ける

  • Gemfile

source "https://rubygems.org"
gem "pry"
  • Gemfile.in
gem "secret_gem", git: "https://github.internal.test/hamakn/secret_gem.git"
source "https://rubygems.internal.test" do
  gem "secret_gem2"
end

instance_eval File.read(File.join(__dir__, "Gemfile"))
  • あとは、Gemfile.inを用いる場合は、 BUNDLE_GEMFILE="Gemfile.in" bundle とかすればいい
  • この場合、Gemfile.lockとは別にGemfile.in.lockが作られる
  • めんどくさければ、 export BUNDLE_GEMFILE="Gemfile.in" するか.gitconfigに alias ibe="BUNDLE_GEMFILE=Gemfile.in bundle exec" とかすればいいんじゃないかな
    • exportの場合は export -n BUNDLE_GEMFILE で元に戻る

spring

  • 上記のみだと、spring内のBUNDLE_GEMFILEがGemfile.inにならないので、下記のような.envと~/.spring.rb(設置場所に注意)を書いてBUNDLE_GEMFILEを反映させる

  • .env

BUNDLE_GEMFILE=Gemfile.in
  • ~/.spring.rb
env_path = File.join(ENV["PWD"], ".env")
if File.exist? env_path
  File.read(env_path).each_line do |line|
    k, v = line.chomp.split("=", 2)
    ENV["BUNDLE_GEMFILE"] = v if k == "BUNDLE_GEMFILE"
  end
end

参考

HTTP Requestに署名する

  • まとめ
    • RFCはないが、Draftとその実装はある

ライブラリ

Ruby版とJava版の互換性

  • 以下のコードで出てくるsignatureとJava版のREADMEのsignatureが一致するので互換性はあるだろう(雑)
require "net/http"
require "http_signatures"

context = HttpSignatures::Context.new(
  keys: {"examplekey" => "don't tell"},
  algorithm: "hmac-sha256",
  headers: ["digest", "date", "(request-target)"],
)
message = Net::HTTP::Get.new(
  "/foo/Bar",
  "date" => "Tue, 07 Jun 2014 20:51:35 GMT",
  "digest" => "SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE="
)

context.signer.sign message
puts message["Signature"]
# => keyId="examplekey",algorithm="hmac-sha256",headers="digest date (request-target)",signature="6aq7lLvqJlYRhEBkvl0+qMuSbMyxalPICsBh1qV6V/s="

サンプルコード(Ruby)

MySQLでROW_FORMATを指定する

ActiveSupport.on_load :active_record do
  module RowFormatAdapter
    def create_table(table_name, options = {})
      table_options = options.merge(options: "ROW_FORMAT=DYNAMIC")
      super(table_name, table_options) do |td|
        yield td if block_given?
      end
    end
  end
  ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.prepend(RowFormatAdapter)
end

bundle_execを省略する

  • 毎回bundle execするのだるい
  • binstabを使えば./bin/railsとかできる
  • direnvでbinにpathを通せば./bin/も省略できる

dierenvの設定

  • .envrc
export PATH=bin:$PATH

rspec

  • spring-commands-rspecを使えばrspecもbundle execを省略できるようになる

コーディングルールを守った開発をする

rubocop / onkcop

inherit_gem:
  onkcop: "config/rubocop.yml"
AllCops:
  TargetRubyVersion: 2.3

pre-commit

  • commit前に何かする系のgem
  • pre-commit install で .git/hooks/pre-commit を作成する
    • bundler管理下のpre-commitを使うにはcmdを以下の用に修正する
cmd="bundle exec ruby"
  • あとは.git/configを書けばcommit時に走るようになる
[pre-commit "checks"]
  remove = []  # execjsがないプロジェクトであれば [:jshint] するのがよい
  add = [:rubocop]

Railsのenvironmentsを他のenvironmentsと同じにしたい

  • cpすると後々同期が取れなくなって死ぬ
  • instance_evalすればいい
# config/environments/staging.rb
instance_eval File.read(File.join(__dir__, "production.rb"))

MySQLのCOLLATION

Collation パパ=ハハ問題 🍣=🍺問題 Case Sensitive
utf8mb4_bin TRUE
utf8mb4_general_ci FALSE
utf8mb4_unicode_ci FALSE
  • まとめ
    • utf8mb4_bin を使うのが良い
    • ci = Case Insensitive

my.cnf

  • 以下を追加する(MySQL 5.6.20の場合)
    • MySQLのversionが変わると必要なoptionも変わるので詳しくはリンク先参照
innodb_file_format = Barracuda
innodb_large_prefix = 1

database.yml

  • collation: utf8mb4_bin を指定する
common: &common
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_bin

書くべきテスト

  • ログインIDをCase Insensitiveにしたいケース想定
    • model: column: "hoge" なレコードが存在する場合に column: "Hoge" なレコードが作成できないこと
      • before_saveでdowncaseする、modelのvalidatesで uniqueness: { case_sensitive: false }するのが良いと思う
    • controller: ログイン時にcaseが異なっていてもログインできること

参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment