どなブロ

Ruby, Rails, Python, 機械学習, その他気になったこととか思ったこととか

【Rails】rakeタスクに引数を与える & ソース上での実行

おひさです。

rakeタスクに引数を与えたくて調べました。
あとModelでちょっとタスクを実行したくてそっちも調べました。

引数の与え方

タスク引数(?)

名前が合ってるかわからんですが[]で渡すようにするやり方

namespace :hogehoge do
  task :run, ['hoge', 'fuga'] => :environment do |task, args|
    puts args.hoge
    puts args.fuga
  end
end
# 実行
$ rails hogehoge:run["ほげ", "ふが"]
ほげ
ふが

ちなみに引数指定しないとnilが入るみたいです。

環境変数

コマンドライン引数で環境変数を指定してあげる感じ

namespace :hogehoge do
  task run: :environment do
    puts ENV['hoge']
  end
end
# 実行
$ rails hogehoge:run hoge="ほげえ"
ほげ

こっちも指定しないとnilになるみたい。

ソース上での実行

あんまりよくないやり方かもしれない。

require 'rake'
Rails.application.load_tasks
Rake::Task['タスク名'].execute # もしくは.invoke
Rake::Task['タスク名'].clear

最後にclearしないと同じ箇所を通った際に再度load_tasksされてexecuteで二回実行されてしまう。
.execute.invokeでは引数の扱いに違いがあるらしい。詳しくは以下参照
rakeタスク内で別のタスクを呼び出す - Qiita

参考

Ruby on Rails | Rakeタスクに引数を渡す - Tbpgr Blog
rakeタスクに引数を与える | 毒男日記
RailsでRakeタスクをcontrollerから呼び出す時の覚書 - Qiita

【Rails】migrationでのDB更新を余計な変更を加えずにschema.rbに反映させる

migrationで何かしらの変更をDBに加える時、db:migrateするとschema.rbへ更新が反映されます。
その時にDBが何かしらの理由で実際の形と異なっているとschema.rbに余計な変更が反映されてしまいます。

自分の場合で言うと、
流れとしてはローカルに立ててあるDBに向けてmigrateをして、schema.rbに変更が加わった後にmigrationファイルと一緒にコミットする感じです。
(これが普通のやり方なのかな?わからん)
それで、ローカルのDBに他の作業とかで関係ない変更が入ってたりすると、目的のmigrationと別の変更がschema.rbに入っちゃうっちゅうわけです。

今回はそういう時に安全に目的の変更だけをschemaに反映させる方法のメモです。
DBに消しちゃいけないデータがある場合はできないと思います。
あくまで自分みたいにmigration用みたいなDBがある場合。

変更前として正しいschema.rbをpullなどしてくる

db:migrateする前であればそのままでいいんですが、migrationで変更を入れる前の段階として正しいschema.rbをmasterブランチとかから持ってきます。
このschemaファイルは目的のmigrationの直前の状態のはずです。

db:resetしてDBをschema.rbと同じ状態にする

db:resetをするとDBがschema.rbと同じ状態になります。
類似のものにdb:migrate:resetがありますが、2つの違いについては簡単に言えば

db:reset => schema.rbを参照してDBを作り直す
db:migrate:reset => DBをDROPしてイチからmigrationし直す

って感じです。
詳しくはこちらで→rails db:migrate:resetできなかったのでrails db:resetした - Qiita

目的のmigrationファイルでdb:migrateする

あとはmigrationするだけです。
やってみたらgit diffとかで差分を見れば目的の変更だけdiffがある…はず。

おわり

勢いで書いたのでクソ読みづらいですね。すみませぬ。

【Python】Jupyter Notebookの差分を見やすくする -- nbdime

自分はまだペーペーなんですが、
たまにjupyter notebookで作った機械学習とか統計用のipynbファイルをレビューする機会があります。

その時にgithubで差分見てたりしたんですが、
ipynbファイルは中身としてはjsonなのでgithubでレビューしようとするとひたすらに見づらいです。

ほんで、絶対もっと楽に見れるやつあるだろ〜と思って調べたら見つけました、nbdime

jsonをパースした上で差分を見やすく出してくれるそう

ターミナルでgit diff的に見るには

nbdiff [file1] [file2]

で以下のように見れます。

f:id:andna0410:20190314162038p:plain

さらにブラウザで差分を見るには

nbdiff-web [file1] [file2]

で以下のように

f:id:andna0410:20190314162156p:plain

ん〜いいですね

file2つ用意しないといけないのちょっとアレですが、
多分git連携したらいけるのかな?そこまでは今回やってません。

installは、anacondaいれてるので
Nbdime :: Anaconda Cloud
ここを参考に

conda install -c conda-forge nbdime

で落としてきました。

レビューしやすくなって最高です。

コードの中身はまだ半分もわからないけどね!!

参考

Jupyter Notebookの差分を明瞭に確認する事ができるpackage : nbdime – Moonshot 🚀 – Medium

【Rails】複数テーブルに跨ってincludes / joinsする(ひ孫まで)

includes

Hoge.includes(fuga: :piyo)
  • ひ孫
Hoge.includes(fuga: [piyo: :bar])

joins

Hoge.joins({:fuga => :piyo})
  • ひ孫
Hoge.joins({:fuga => {:piyo => :bar}})

参考リンク

railsで親子孫ひ孫までをincludesする - niki12260714の日記

Railsでjoinsを多段ネストする方法(親から曾孫まで) - Qiita

その他

下書きに長く置きすぎて重要な事以外何書くのか忘れた…

【Ruby / Rails】全体が文字列になっちゃってる配列を正しい形に直す

やりたいこと

  • viewからparamsで配列をもらうんだけど、全体が文字列になっちゃってる
"[123,456,789]"

↑こんな感じの、ホントは配列だけど文字列になっちゃってるやつ
↓本当はこうしたい

[123, 456, 789]

解決方法

  • 無理やり直す
    splitしてdeleteで余分な物を消す
pry(main)> hoge = "[123,456,789]"
=> "[123,456,789]"
pry(main)> hoge.split(',').map { |m| m.delete('[]').to_i }
=> [123, 456, 789]

https://qiita.com/_miyachik/items/addf3766f0e0dd20f154

  • JSON使う
    parseするだけ
    文字列だとParseErrorになっちゃう
pry(main)> hoge = "[123,456,789]"
=> "[123,456,789]"
pry(main)> JSON.parse hoge
=> [123, 456, 789]

https://stackoverflow.com/questions/4477127/ruby-parsing-a-string-representation-of-nested-arrays-into-an-array

感想

  • JSON.parseするとなんでそうなるの

【Ruby】メソッド名を動的に呼び出す

やりたいこと

  • メソッド名を動的に変更して呼び出したい
    ex)
Class Hoge
  def hoge_once
    puts "hoge."
  end

  def hoge_twice
    puts "hoge hoge."
  end
end

# 別のところで
def fuga
  times = # "once"か"twice"が入る

  # hoge.hoge_ + times
  # みたいな感じで動的に呼び出したい
end

解決方法

  • Object#sendを使う
    ex)
times = "once"
hoge.send("hoge_#{times}")  # => "hoge."
  • sendはprivateメソッドも呼び出せちゃう
  • なので一応public_send(privateメソッドは見れない)を使う
times = "once"
hoge.public_send("hoge_#{times}")  # => "hoge."

補足

感想

メソッドチェーンで改行する場合のドットの位置

メソッドチェーンして開業する時のドットの位置って次の行に置くのが自然かと思ってましたが、行末に置くのもメリットあると知りました。

行頭

  obj.hoge(param1, param2).fuga(param3)
     .piyo(param4)
  • 綺麗に揃って見える
  • 縦にザーッと眺めた時にメソッドチェーンがあるとわかりやすい
  • (デメリット)irbやpryにコピーすると1行目だけ実行されてエラーになる

行末

  obj.hoge(param1, param2).fuga(param3).
      piyo(param4)
  • 横に読んでるとメソッドが続くのがわかりやすい
  • irbやpryにコピーした時に1行目でエラーにならない
  • (デメリット)ザッと読んでると行末のドットは気づきづらい

まとめ

一長一短ですね。
好みで言えば行頭です!

参考記事

Rubyコーディングアンチパターン - Qiita