rake taskで可変長引数を使う
rake taskで可変長引数を使う
約1年間Railsエンジニアやってて初めてrake task書いた。
その時のめも。
to_a
メソッドを使う
namespace :test_task do desc '可変長引数を受け取るtask' task :hoge, ['huga'] => :environment do |_task, args| p args.to_a p args.huga end end
実行する。
$ bundle exec rake test_task:hoge[1,2,3,4] ["1", "2", "3", "4"] "1"
args
はHash
ではなくRake::TaskArguments
であり、Rake::TaskArguments
のインスタンスメソッドである
to_a
を使うことで引数の値をすべて取得する事ができる
- リファレンス
http://www.rubydoc.info/gems/rake/12.0.0/Rake/TaskArguments#to_a-instance_method
Ruby勉強し直してみた 3
メソッドの可変長引数
Ruby勉強し直してて普段あんま使ったことないのでめも。
自分で定義するメソッドで可変長引数を使いたければ引数名の手前に*をつける
def メソッド名(引数1, 引数2, *可変長引数) # メソッド処理 end
みたいに。
例
def test(*name) name end test('tanaka', 'fuzita', 'yamada') => ['tanaka', 'fuzita', 'yamada']
可変長引数で渡された引数は配列になる
さっそく使ってみたい…!
Ruby勉強し直してみた 2
inject/reduce
たたみ込み演算なるもの… 例を見たほうが早い
numbers = [1, 2, 3, 4] sum = numbers.inject(0) { |result, n| result + n }
ブロックの第一引数(result)には初回のみinjectメソッドの引数が入る。
2回目以降は前回のブロックの戻り値が入る。
繰り返し処理が最後まで終わると、ブロックの戻り値がinjectメソッドの戻り値になる。
チェリー本にて復習中だけども、以外と知らなかったことが多い…
Danger 導入した
機械的なレビューを自動で行ってくれるDangerというgemを最近導入したので、その時の
Dangerってそもそも何?
DangerのGithubには以下のことが書かれています
Stop saying "you forgot to …" in code review Formalize your Pull Request etiquette.
「あなたは〜をやることを忘れているよ。」ということをやめる。
プルリクエストの礼儀作法を形式化
つまり
「プルリクエストの礼儀作法を形式化し、指摘を自動化する」ための便利なgemです
導入背景
チーム開発をしていると、そのチームごとにプルリクエストの書き方の決まりやルールなどができてくると思います。例えば
- テストは必ず書きましょう
- レビューしてもらいたい時はWIPを外しましょう
- labelを必ずつけましょう
- 変更が多い場合はプルリクエストを分けましょう
…などなど
もちろん自分のチームでも上記のようなルールがあったのですが、
- テストを書いていなかったり
- WIPつけっぱなしのままレビュー依頼出しちゃったり
- labelつけ忘れてたり
- 1つのプルリクエストでの変更が多すぎたり
…などなどが発生しており、そのようなプルリクエストが上がるたびに同じ指摘を繰り返していました。
しかし、上記で上げたような指摘って誰にでもできるものですよね? いちいち同じ指摘する工数も工数なので自動化しよう!!というのがきっかけです
Danger導入
Circle CiでDangerを実行し、プルリクエストに自動でコメントします
Gemfileの設定
source "https://rubygems.org" gem 'danger'
Gemfile編集後に'bundle install'コマンドを実行します
Dangerfile設定
'bundle exec danger init'コマンドを実行します
'danger init'を実行すると初期セットアップ実行され、'Dangerfile'が作成されます。
'Dangerfile'としてはクックパッド開発者ブログを参考に以下のように編集しました。
# ===== PR title ===== warn('PR is classed as Work in Progress') if github.pr_title.include? '[WIP]' # ===== diff size ===== warn('PRの変更量が多すぎます。PRを分割しましょう!') if git.lines_of_code > 500 # ===== Test ===== raise('テストが書かれていません!') if `grep -r fdescribe specs/ `.length > 1 raise('テストが書かれていません!') if `grep -r fit specs/ `.length > 1 # ===== Label ==== labels = github.pr_labels warn('labelを選択してください!') if labels.empty?
- WIPがつけっぱなしのとき
- プルリクエストの変更差分が多すぎるとき
- テストが書かれていないとき
- labelをつけていないとき
に自動でレビューを行ってくれる設定です。
'Dangerfile'を作成すると長文の説明文が流れてくるので、読みつつ、設定しつつenterで進めていきます
- Step1
'Dangerfile'を作成しましたというメッセージ
- Step2
'Danger'からプルリクエストに対してコメントの書き込みが行われるので、そのためのアカウントを作成しておくと良いです。
- Step3
botアカウントでアクセストークンを作るように、と言われます。
リポジトリにアクセス可能なアカウントでAPI トークンを作成します。
個人のアカウントでも問題はないのですが、bot用のアカウントだと機械的に指摘されたコメントというように区別できてわかりやすいです
- Step4
Ciの設定を行います。
詳しい案内はないのでGetting Set Upを参照します
Ciのsettingsで対象のリポジトリのAPI permissionsにトークンを登録します。
'.circleci/config.yml'に以下のように追記します
- run: name: Run Danger file command: bundle exec danger --verbose
最後に!
Circle Ciでdangerを使う場合は 'Only Build pull requests'を有効にし、プルリクエスト作成時のスキップを回避してください
これで設定は終了です。
プルリクエストをWIPつけっぱなしで作成するとちゃんと指摘してくれてますね!
まとめ
このような感じで誰でもできるようなレビューはdangerにまかせて、本当にレビューする必要がある箇所に意識が集中できるようにどんどんしていきたいですね!
Rails ActiveRecord いろいろ
仕事柄プルリクをレビューすることが多々あるのですが、やっぱりまだまだわかっていないことが多い… 忘れないようにメモメモ…
inverse_of
inverse_of を指定したリレーションのある2つのモデルでは、双方から同一のインスタンスを参照することができる。 つまり、双方ともメモリ上では同じインスタンスとして扱われる。 inverse_of の設定がないと同一のインスタンスとしては扱われず、一方からの変更がもう一方から参照されても変更されていない ふむふむ…
例
class User < ActiveRecord::Base has_many :menus end class Menu < ActiveRecord::Base belongs_to :user end
user = User.first menu = user.menus.first user.name == menu.user.name # => true user.name = "change" user.name == menu.user.name # => false
Userのフィールド name の変更が、Menu からたどった時に変更が参照されていない。メモリ上では別インスタンスとして扱われているからである。
inverse_of を指定してあげる
class User < ActiveRecord::Base has_many :menus, inverse_of: :user end class Menu < ActiveRecord::Base belongs_to :user, inverse_of: :menus end
メモリ上では同一インスタンスとして扱われるようになるので、user もしくは user.menuから name を変更しても以下の結果になる
user.name == menu.user.name # => true
すげーな!
change_column_null
ActiveRecordでcolumnにNotNull成約をかけてしまったけども、後々になってやっぱり制約を外したい…なんてときに使います。
class ChangeColumnToUser < ActiveRecord::Migration[5.1] def change change_column_null :users, :name, true end end
change_column_null table名, column名, true/false
Ruby勉強し直してみた 1
Railsエンジニアになってはや1年が経とうとしています。そんな中で最近思うのですが「Railsはわかってきたけれども、Rubyが全くわからない…」 これはやべぇと思い、ここで改めてRubyを勉強し直していきます その備忘録
Rubyの演算子
高い ! && || not 低い and or
優先度があることにより、英語の論理演算子と記号の論理演算子を混在させてしまうと、求めたい結果が変わってしまうことがある
a = true b = false !a || b not a || b
↓このように評価される
(!a) || b not (a || b)
ふむふむ。 また記号の論理演算子と違い、英語の論理演算子同士の場合は優先順位の違いがない。 ()をつかわなければ左から右に順番に評価されていく
a = true b = true c = false # && の方が || より優先順位が高い a || (b && c) # and or は優先順位が同じなので左から評価されていく (a or b) and c
記号と英語の演算子で優先順位に違いがあるため and or を && || の代わりに使おうとすると期待と違う形になるやも
and や or は条件分岐で使うのではなく、制御フローを扱うのに向いている 例えば 「正常なuserであればメールを送信する」という制御フローを実行したければ
user.valid? and send_mail_to user
というように書くことができる
or も「Aが真か? 真でなければBせよ」という制御フローを実現することに向いている
# userが不正だったらエラーメッセージを返す user.valid? or return 'userが不正です'
三項演算子
n = 11 if n > 10 '10より大きい' else '10以下' end => "10より大きい"
こんな風にかける
n = 11 n > 10 ? '10より大きい' : '10以下' => "10より大きい"
シンプルなif/else文であればこの書き方のほうがスッキリと書くことができる
改めてRuby勉強するとおもしろい…!
Go langでFizzBuzz
田舎育ちのエンジニアです Go lang気になってたのでちょっと勉強始めてみました 備忘録です。
Go langとは
Go言語は2009年にGoogleによって作られたオープンソースの静的言語です。 特徴としては ・ シンプル
・ コンパイル・実行速度が早い。
・ 安全性が高い。
・ 同期処理が容易に行える。
などなど…
ちなみに調べる時は「Go」だけでなく「Go lang」、「Go言語」と検索したほうが良いです
FizzBuzz
プログラマーの人ならだいたい書いたことのあるFizzBuzzをGo langで書いていきます。
package main import "fmt" func main() { n := 0 for { n++ if n > 15 { break } switch n { case 15: fmt.Println("FizzBuzz") case 5, 10: fmt.Println("Buzz") case 3, 6, 9, 12: fmt.Println("Fizz") default: fmt.Println(n) } } }
こんな感じで書くことができるのですが、Go langのcase文では値だけでなく式を指定することもできます 少し変更を加えると
package main import "fmt" func main() { n := 0 for { n++ if n > 15 { break } switch { case n%15 == 0: fmt.Println("FizzBuzz") case n%5 == 0: fmt.Println("Fizz") case n%3 == 0: fmt.Println("Buzz") default: fmt.Println(n) } } }
うん。こっちの方がなんか良い!
まだGo langをはじめて数日ですが、おもしろいと感じています。
これからも雑でもアウトプットは出していきたい…