元祖若手のプログラミング奮闘記

元祖若手の奮闘記。主にメモ

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

まぁどんまい!