RailsのModelを複雑にした時
SQLのこんな動きをしたい
UPDATEする時JOINしてGROUPBYしてって時
update items inner join ( select orders.item_id, count(*) count from orders group by item_id ) myorders set items.orders_count = myorders.count where items.id = myorders.item_id
Arelなら綺麗にかけるけども
現場でArelを使ってかいてなかった。。
って時に考えた結果こうなった
ベタ書きってどうよ。。
order = Order.select("#{Order.tn}.item_id, COUNT(*) count").group(:item_id) Item.joins("INNER JOIN (#{order.to_sql}) myorders") .where("#{Item.tn}.id = myorders.item_id") .update_all("#{Item.tn}.orders_count = myorders.count")
PHPの正規表現でWARNINGがでまくったのでとめた。
こんなコードを書いていたら
WARNINGがでまくったので
<?php public function validateWords($word_list = array()){ $pattern = implode('', array( "\x{3041}-\x{3094}", //ひらがな "\x{30A1}-\x{30F3}", //カタカナ "\x{4E00}-\x{9FFF}", //漢字 "\x{F900}-\x{FAFF}", //漢字 "\x{FF01}-\x{FF5A}", //全角記号、全角英数字 "a-zA-z0-9Α-Ωα-ω¢£" )); $result = array(); foreach ($word_list as $word){ if (preg_match('/[^'. $pattern .']/', $word)){ $result[] = $word; } } } return $result; ?>
そしてこんな感じでWARNINGがでた
Warning: pregmatch() [function.preg-match]: Compilation failed: invalid range in character class at offset 13
まぁ範囲の指定がUnicodeとa-zとかごちゃってるからな
ってことで
全部統一してみる
だがしかしWARNINGは止まらない
そして気づく。
「そういえばこれEUC-JPやんけ。。」
ってことで修正
<?php public function validateWords($word_list = array()){ $pattern = implode('', array( "\x{0030}-\x{0039}", //半角数 "\x{0041}-\x{005A}", //半角英小 "\x{0061}-\x{007A}", //半角英大 "\x{3041}-\x{3094}", //ひらがな "\x{30A1}-\x{30F3}", //カタカナ "\x{4E00}-\x{9FFF}", //漢字 "\x{F900}-\x{FAFF}", //漢字 "\x{FF01}-\x{FF5A}", //全角記号、全角英数字 "\x{FFE0}\x{FFE1}" //セント、ポンド )); $result = array(); foreach ($word_list as $word){ $str = mb_convert_encoding($str, "UTF-8", "EUC-JP"); // UTF-8へ変換 if (preg_match('/[^'. $pattern .']/u', $str)){ //u修飾子をつけ忘れないように $result[] = $word; } } return $result; } ?>
WARNING止まった!!!!
だが待つんだ
喜ぶのはまだ遅かった
全角のマイナスとセント、ポンドがなぜか
NGワードでひっかかる
ってことで
UTF-8に変換したところでvar_dump
なんと半角に変換されていた。。。。
-¢£ => -¢£
ってことなので
範囲を追加。
下のやつでおしまい。
<?php public function validateWords($word_list = array()){ $pattern = implode('', array( "\x{0030}-\x{0039}", //半角数 "\x{0041}-\x{005A}", //半角英小 "\x{0061}-\x{007A}", //半角英大 "\x{3041}-\x{3094}", //ひらがな "\x{30A1}-\x{30F3}", //カタカナ "\x{4E00}-\x{9FFF}", //漢字 "\x{F900}-\x{FAFF}", //漢字 "\x{FF01}-\x{FF5A}", //全角記号、全角英数字 "\x{FFE0}\x{FFE1}" //セント、ポンド "\x{2D}\x{A2}\x{A3}" )); $result = array(); foreach ($word_list as $word){ $str = mb_convert_encoding($str, "UTF-8", "EUC-JP"); // UTF-8へ変換 if (preg_match('/[^'. $pattern .']/u', $str)){ //u修飾子をつけ忘れないように $result[] = $word; } } return $result; } ?>
PHPの配列(array_diff)を甘くみていたらはまった
これは特殊なケースかなと思ったけど一応メモ。
PHPの配列を深く知らなかったがために
結構はまった。。
追加した処理が二つの配列を比較して
新たにデータを追加したり、削除するような機能を作りたいとする。
<?php $array1 = array("green", "red", "blue", "red"); $array2 = array("green", "yellow", "red"); $result = array_diff($array1, $array2); print_r($result); ?>
こちらの$resut変数をそのまま引数として渡すとこうなる
Array ( [1] => blue )
ここの添え字が [1] になっているのが
わかると思うが
添え字もしっかり [0] にして渡さないと
エラーになってしまうことがつい最近わかった
ってことで初期化
<?php $array1 = array("green", "red", "blue", "red"); $array2 = array("green", "yellow", "red"); $result = array_diff($array1, $array2); print_r(array_merge($result)); ?>
Array ( [0] => blue )
これでオッケー
もう値はあってるのになんで。。。
みたいなことはなくなるかと
Raisでコードの書き方で指摘されたこと
Railsで指摘されたことをまとめる
・アロー演算子を使わない
# 古いコードを見ながら書くとついついやるやつ validates :name, :presence => true # こっちの書き方で validates :email, presence: true
・evalを使わない
セキュリティ上よくないらしいけど
深くまで知らない
あと例が悪くて申し訳ない。。
_params = set_params search_types = [] if _params[:name].present? name_ids = User.get_ids_by_name(_params[:name]) search_types << "name_ids" end if _params[:email].present? email_ids = User.get_ids_by_email(_params[:email]) search_types << "email_ids" end # &にすることで二つの配列で同じ値のみ代入される # merge_ids = name_ids & email_ids merge_ids = eval(search_types.join("&"))
・長い1行を改行するときのインデント
メモ残すまでって感じではないけど一応。。
# こうするとselfを変えた際に # いちいちインデントをそろえなくちゃいけない self.where(name: my_name) .where(email: my_email) .first # これで self.where(name: my_name) .where(email: my_email) .first
まだまだ言われてるけど
まずはこれくらいで
PHP var_dump 全出し(メモ)
よく見かける記事ですがメモ代わりで
var_dumpって長文省略されんちゃうんだねって
ことで省略されないようにする
<?php #前略 $string = "・・ めっちゃ長文 ・・"; ini_set('xdebug.var_display_max_children', -1); ini_set('xdebug.var_display_max_data', -1); ini_set('xdebug.var_display_max_depth', -1); var_dump($string); #後略 ?>
コントローラー、ヘルパー、ビューにモデル処理を描くんじゃない!
タイトルの通り今回これをやらかしてたので
今日はこれ
当たり前っちゃ当たり前なんだけど
コード書きまくってたら良くやるのもこれ
なんてったって実際そんな書き方してるコードが
あるんだから参考にしちゃうよねw
基本書くのはこちら
app/models/...
気を付けよう!
まず一例でこちら
ヘルパーにモデル処理書いてみたよ。
app/helpers/users_helper.rb
module UsersHelper def get_user_names_by_group(group) User.where(group: group).pluck(:name) end end
これは突っ込みありまくりコードだけど
気を付けよう実際あったし。
app/controllers/users_controller.rb
def create if request.post? @users = set_user_params User.transaction do @users.each do |user| new_user = User.new(name: user[:name]) raise unless user.save end end end @users = User.all end
まぁどんまい!