railsで意外なところでsql injectionした話

発生箇所

Product.all.order(params[:sort]).limit(5)

active record relationの
order methodで発生。
ユーザーからの入力を直接orderに渡していたため。
params[:sort] = ‘updated_at; delete from *.*;’
みたいにユーザーが入力渡すと、データ飛ぶ。
もちろん任意のsqlを実行可能。

Q. どうやってそんなん気づいたの?

A. Web セキュリティ勉強会で
active record relation使ってるとこで
params使われてるとこは
全部疑った方がいいみたいなこと
ぼそっと言ってたの思い出して。
自分は外注により作られたシスタムの
メンテしてるため、気になって見てみたら死んでた笑

cssの設計でbemから一歩進んだ話

前置き

bemでクラス設計してたけど、色々負を感じ

自分で勝手にアレンジしてた。

その話を他のエンジニアにしたら、それこれだよって言われてそうゆうのがあるって知った話

http://apbcss.com

 

bemから進んだ話ってタイトルですけど、個人的にbemより優れてるって判断です

 

atomic part base css

最小単位のcssatom(原子)とする。

atomを組み合わせでmoleclues(分子)とする

原子と分子の組み合わせでその他化合物(ページ)を作っていく考え。

atomのclassにはatomの様子を表すスタイルを当てる。

molecluesを作るにはatom間の関係(ファンデルワールス力)を表すスタイルを当てて作る感じ。

 

各単語は独自のニュアンスを多分に含んでいます笑

どこまでが原子、分子だの議論は一旦置いといて、イメージの話です。

 

背景

これまではbemのblock elementでクラス設計し、スタイルを当ててました。

だけどelementで共通のスタイル(色、フォントなど)

がめっさ発生してた。(ここがatom化できるポイント)

それをどうにかしたかった。

あとはサブ的な理由が、elementのクラスにブロック内でのレイアウトのスタイルが当たって責務がこんがらがって、チーム内統一ができなかった。

ここは単純にbemの設計の甘さ、チーム内メンバーの認識のズレがあったかもしれない。

 

結果

cssの重複がなくかけるようになった。

ただし重複をなくすことは、一個変えたら全部変わるということ。

いっぺんに変更したい単位、ここが変わったら一緒に変わってほしい範囲で原子かすることを気をつけなければ多分3ヶ月後に死んでる

rails newのフローを自動化

成果物

https://gist.github.com/nishisuke/a0dc642c36c3110cc0265b0f0212e6e5

背景

YAGNI(You ain't gonna need it)という言葉がある。
一般的に動いてるシステムにおいて、
後からコードを消す事はとても難しい。
システム全てが影響範囲である可能性があり、
それを全て確認できて初めて消せるから。

それなのにrails newコマンドはもりもり
いらないものを生成してて毎回最初は消してた。
けど何回もrails newしてるうちにアホほどめんどくなってきて、
自動化にいたる。

方法

rails new -h

上記コマンドで option いっぱい表示されるので、
いらないの探して適用させてく感じ。
generateとかも同じようにoption表示させて
option適用させればok.
generateの場合はenvironments/develop.rbに設定すると
でふぉになる。

config.generators do |g|
  g.assets false
end

rubyでstrategyパターン実例

strategy パターンとは

デザインパターンの一つ。

class(もの)に対して戦略を外部から渡してやる(dependency injection的な)考え方

 

 

class Engine
  def boost
    p "普通に走行"
  end
end

class SuperEngine
  def boost
    p 'めっちゃ速く走行'
  end
end

class Car
  def initialize(engine)
    @engine = engine
  end
  
  def run
    @engine.boost
  end
end

car_1 = Car.new(Engine.new)
car_2 = Car.new(SuperEngine.new)

car_1.run # => '普通に走行'
car_2.run # => 'めっちゃ速く走行'

 

 このように車から走行の仕方を分離できます

RubyGemsに自作gemを公開する

流れ

  • install bundler
  • bundlerで雛形作成
  • gem実装
  • RubyGems にアップ

 

install bundler

gem install bundler

 

雛形作成

bundler gem gem_name

 実装

lib/hoge.rb

 

module Hoge
  class << self
    def say_hoge
      p "hoge__"
    end
  end
end

 

 

あとはhoge.gemspaecのtodoを書き換えるだけ

 

 アップ

1. サインアップ

2. キー登録

3. リリース

 

% rake release

 

Rspecを高速化した話

Rspecの実行時間を90min -> 20 minにした方法

1~2ヶ月前の事で当時は記事化するつもりなかったので、
ところどころ抽象度が高い記事になります。

きっかけ

待てない
てかrspec 90minって冷静に異常だよね?

から思い立った。

流れ

1. 遅いの特定
2. 原因追求
3. 改善

遅いの特定

rspec -p /path/to/file

で遅いspecが表示されます。

自分のケースだと20min以上かかるgroupが3つあり、
それがダントツで足を引っ張ってました。

原因の追求

特定した、足をひっぱてるグループのテストコードを見る前に、
rspec 高速化」でぐぐって遅い原因の可能性がすでに頭にありました。
(実際にぐぐったのはきっかけの直後)

今回可能性として想像できてたのは、

  • dbにcreateしすぎ
  • 画像めっちゃ使ってる

の二つでした。


そしていざ遅いテストコードを見ると、
割と複雑なmodel(リレーション5~7つながったもの)
をbefore eachで2〜4こ作っていました。

今回のケースは検索系のテストグループ3つにおいて
それぞれ5~10このspecが走っていました。
そのそれぞれにeachで上記modelを作っているのが
完全に無駄だったので、ここを改善ポイントに完全にfixしました。

改善

検索ようのデータでテスト中にデータが汚れなかったので
before :allで最初にデータたくさん作って、
aftere :allで消すというシンプルな作戦を決行しました。

以下やりかたです。
20minになったといっても
速くなったら速くなったで
また全然待てないのが自分のさがでした。。


'database_cleaner'というgemを使いtest中のdbの清掃をする。
https://github.com/DatabaseCleaner/database_cleaner:title=公式 を読んで設定をしたのち、

spec_helper.rbに

describe "対象Groups" do
  before :all do
    @product = create....
  end
 
  describe "対象GroupA" do
  end
  describe "対象GroupC" do
  end

  after :all do
    DatabaseCleaner.clean_with(:truncation)
  end
end

MacにRubyをインストール

Homebrew, rbenvでRubyをインストールする最低限の手順です。

流れは以下です。

  • Homebrew で rbenv をインストール
  • rbenv で ruby をインストール

rbenvは主にrubyのversion管理をしてくれるものです.
Homebrewはインストール済みとします.
Homebrew Install

Environment

OS X:  10.11
shell: zsh

1. Homebrewで rbenv をインストールする

% brew update
% brew install rbenv
% rbenv init
% echo 'eval "$(rbenv init -)"' >> ~/.zshrc # or your shell config
% source ~/.zshrc # same file above

2. rbenv で ruby をインストール

% rbenv install -l # show versions
% rbenv install 2.4.3 # whatever version
% rbenv rehash
% rbenv global 2.4.3 # set global version
% ruby -v # => 2.4.3
% cd someproject
% rbenv local 1.8.0 # set version only in project dir
% ruby -v # => 1.8.0