Railsのmigrationでchange_columnを利用する
change_column
Railsのmigrationでカラムの情報を変更したい場合によく使うchange_columnですが、
change_column(table_name, column_name, type, options = {})
と変更したいtypeを設定してoptionsを設定すればいいので、add_columnなどとインターフェイスが変わらず設定できます。
change_column_null
NULLのtrue/falseを切り替えたいだけの場合は change_column_nullが便利ですね。
change_column_null(:users, :nickname, false)
このように設定できます。
change_column_comment
カラムに設定するコメントのみを変更する場合はchange_column_commentですね。 nilを入れることで設定しているコメントを削除することもできます。
change_column_comment(:users, :id, 'comment') change_column_comment(:users, :nickname, nil)
change_column_default
最後にカラムのデフォルト値を変更するchange_column_defaultなのですが、 このメソッドは引数にHashで:from と :to で設定することで可逆的な設定がすることができます。
change_column_default(:posts, :state, from: nil, to: "draft")
これは便利ですね。 テストで作ったけど戻したい等の場合はとても役に立ちます。
mysqldumpでテーブルを対象、対象外にする
mysqldumpを定期的にするのですが、 対象外にしたいテーブルが複数でてきたときの対応方法をメモしておきます。
ダンプファイルと取るときには直接テーブル名を選択すればいいケースもあります。 以下のコマンドですと一番上を選択してデータベースを指定して登録したいテーブル名を後ろに列挙するといいですね。
shell> mysqldump [options] db_name [tbl_name ...] shell> mysqldump [options] --databases db_name ... shell> mysqldump [options] --all-databases
MySQL :: MySQL 5.6 リファレンスマニュアル :: 4.5.4 mysqldump — データベースバックアッププログラム
オプションはいろいろあるので見てもらうとして、対象外にしたい場合は--ignore-table
をつければ良さそうです。
ただ複数テーブル対象外にしたい場合は少し厄介で、--ignore-table=db_name.table_name
をたくさん作らないといけなくなります。
shellで書くとすると以下みたいにつくります。
db_host=hogehoge_host db_name=hogehoge_db db_user=hogehoge_user ignore_tables=("tests" "users" "accounts") ignore_option_str="" for tab in $ignore_tables[@]; do ignore_option_str=$ignore_option_str" --ignore-table=$db_name.$tab" done mysqldump --single-transaction $ignore_option_str -h $db_host -u $db_user -p $db_name
対象のテーブル名の方が少ない場合はテーブル名を列挙して取るのが早そうなので、ケースによって判断して取得するのがいいですかね。
Ruby2.6が早くもpreveiw2をリリース
今年のRubyKaigiは少し大きめのリリースがあったので残念ながら会社でお仕事してました。
preview2がリリースされたということで早速インストールしてみました。
brewからruby-buildを入れているので以下のように設定して置きました。
➜ ~ brew upgrade ruby-build
➜ ~ rbenv install --list | grep 2.6.0 2.6.0-dev 2.6.0-preview1 2.6.0-preview2
➜ ~ rbenv install 2.6.0-preview2
➜ ~ rbenv global 2.6.0-preview2
➜ ~ ruby -v ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-darwin17]
これでしばらくruby2.6.0-preview2で生活してみます。
ActiveRecordでOR文を作るときのエラー対処
少し複雑なSQLのOR文をActiveRecordで作るときにはすこし億劫になりますね。
ArgumentError: Relation passed to #or must be structurally compatible. Incompatible values: [:joins, :references]
とエラーが出てしまったのでいろいろ調べてみました。
今回のエラーはRails5.2の以下のコードで ArgumentError が発生しています。
rails/query_methods.rb at c81a7fcf76663e6d189792d6eed57b1162199635 · rails/rails · GitHub
structurally_incompatible_values_for_or が何なのかと見てみると
rails/query_methods.rb at c81a7fcf76663e6d189792d6eed57b1162199635 · rails/rails · GitHub
STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references] def structurally_incompatible_values_for_or(other) STRUCTURAL_OR_METHODS.reject do |method| get_value(method) == other.get_value(method) end end
Relation::VALUE_METHODS が 以下で登録されているのですが、
rails/relation.rb at ac1efe7a947ba04b276a7109f1a86e559a6ab683 · rails/rails · GitHub
[:includes, :eager_load, :preload, :select, :group, :order, :joins, :left_joins, :left_outer_joins, :references, :extending, :unscope, :limit, :offset, :lock, :readonly, :reordering, :reverse_order, :distinct, :create_with, :where, :having, :from]
ここから [:extending, :where, :having, :unscope, :references] を省いた項目が一致してることをチェックしてるので
[:includes, :eager_load, :preload, :select, :group, :order, :joins, :left_joins, :left_outer_joins, :limit, :offset, :lock, :readonly, :reordering, :reverse_order, :distinct, :create_with, :from]
の項目が一致してないと ArgumentError になるということですね。
これを個別に対応していくのは大変なのですね。。
これらの項目を設定するメソッドはいろいろ用意されてはいますが、
ActiveRecord::QueryMethods#methods: extending_values group_values includes_values= left_joins_values left_outer_joins_values= lock_value offset_value= preload_values readonly_value= reordering_value reverse_order_value= set_value eager_load_values extending_values= group_values= joins_values left_joins_values= limit_value lock_value= order_values preload_values= references_values reordering_value= select_values unscope_values eager_load_values= get_value includes_values joins_values= left_outer_joins_values limit_value= offset_value order_values= readonly_value references_values= reverse_order_value select_values= unscope_values=
a の オブジェクトから b のオブジェクトに移すみたいなことは項目数から考えても面倒ですね。
b.joins(a.joins_values)
項目を並べてget_value と set_value で移すこともできますが、、、
[:includes, :eager_load, :preload, :select, :group, :order, :joins, :left_joins, :left_outer_joins, :limit, :offset, :lock, :readonly, :reordering, :reverse_order, :distinct, :create_with, :from].each do |method| b.set_value(a.get_value(method)) end
流石に面倒そうです。
User. joins(:accounts). group(:id). having('count(accounts.id) > 2'). whrere(created_at: Time.zone.today.all_day)
このSQLにORを付けたいのですが、
当日と5日前に追加されたユーザを調べたいとします。
today = Time.zone.today relation = User. joins(:accounts). group(:id). having('count(accounts.id) > 2') relation.where(created_at: today.all_day).or(scope.whrere(created_at: today.days_ago(5).all_day))
このようにローカル変数にor前のRelationを渡してしまってwhereをつくればいいということですね。 少し面倒ですが、これで大丈夫そうです。
スコープを使ったケースを見てみます。
scope :hogehoge, -> { where(created_at: Time.zone.today.all_day) }
このようなscopeがあるとします。まだ条件は当日のみです。
User. joins(:accounts). references(:accounts). having('count(accounts.id) > 2'). group(:id). extending(Pagination). unscoped. hogehoge
先程の処理にhogehogeを追加してみました。 hogehogeのなかでOR文を作ってみます。
scope :hogehoge, -> { today = Time.zone.today where(created_at: today.all_day).or(where(created_at: today.days_ago(5).all_day)) }
ここではローカル変数なしに設定できました。
スコープではない場合は一旦変数に入れないといけないというのは不便ではあります。
これ自体が面倒な場合は String で直接SQLを記載するのがいいかもしれないです。
今回のケースはDateTime型で日付に対する条件になるので BETWEENが使われます。
day1 = today.all_day day2 = today.days_ago(5).all_day where('(users.created_at BETWEEN ? AND ?) OR (users.created_at BETWEEN ? AND ?)', day1.first, day1.last, day2.first, day2.last)
このような感じなります。
? に 設定する値がnilだった場合はこれだと面倒になったりするので
ケースによって使い方を選択してもいい気がします。
以下、参考にしたサイトです。
Unicode エンコードの競合 というファイル名になってしまう
20180419_プロダクションレディマイクロサービス.txt
というテキストファイルをDropboxのディレクトリに作っていたのですが、
20180419_プロダクションレディマイクロサービス (Unicode エンコードの競合).txt
という名前に変換されてしまっていました。 何なのかと思い、調べてみると
リンクされている別のパソコンで同期されないファイルがある場合 – Dropbox のヘルプ
ここの中に ユニコード エンコード問題 という項目があり、 Unicode Encoding Conflict とファイル名につくとありますがこれの日本語バージョンのようです。 とりあえず日本語を使うのをやめると解消されていました。 困ったものですね。。
Nodeのバージョンが10.0.0に
Nodeが早くも10.0.0です。 パフォーマンス改善も著しく注目も高いですね。 以下、CHANGELOGの内容です。
ちょうどNode学園の30時限目がありお邪魔してきました。
Nodeの改善に取り組んできた内容や今回の改善点、今後の展望?のようなことが聞けて為になりました。 HTTP GET のサンプルコードは async await書くことでコード量もスッキリしてとても良さそうです。 ローカルのNodeのバージョンも10.0.0を入れてみて楽しんでみます。