newラブプラス+

NEWラブプラス+発売に伴い,ゲームとは何の関係のない年末一発ネタ.

class Love {
};

int main()
{
    Love *love;

    (love = new Love)++;

    delete --love;
    return 0;
}

色々弄くり回してこんな漢字に落ち着いた. 演算子の優先順位とか結合順序とか,自己代入とか,やってみると色々注意することが多かった.

loveがdeleteされるオチ付き.

Javascriptのシフト演算の挙動

Javascriptで符号なし32ビット整数っぽいシフト演算をさせたかったときにハマったのでメモ.

必要な前提知識
  • コンピュータ上での数値の表し方(浮動小数点,符号付き整数,2進数[16進数]の計算とか)
  • シフト演算(算術シフト,論理シフト)
続きを読む

e-AMUSEMENT COLUDで麻雀格闘倶楽部を遊んでみた

そういえばe-AMUSEMENT CLOUDのテストサービスが始まってから,一回も触ってなかったのでプレイしてみたので感想とかいろいろ.

続きを読む

Rails3のメソッド紹介(1) ActiveRecord::Relation#first_or_create

少しずつRailsの便利なメソッドを紹介してみようと思い立ったので書く.
今回はタイトルどおりActiveRecord::Relation#first_or_createというメソッドを紹介.
(後々気づいたけど,Rails4から非推奨になるらしい.代わりにfind_or_create_byなるメソッドを使うらしい)

このメソッドはメソッド名通りで,ActiveRecordで一番最初に見つかったものを返す.
もし見つからなければ指定した引数にしたがって新しいレコードを作成する.

ソースコードを見てみてもそのまんま

def first_or_create(attributes = nil, options = {}, &block)
  first || create(attributes, options, &block)
end

最初にfirstを実行し,見つからなければcreateを実行している.

簡単な実行例

例えばid, name, email, ageを持つUserモデルが以下のようになっているとし,現在以下のようにデータベースにユーザ情報が保存されているとする.

id name email age
1 藤井隆 fujii@example.com 25
2 山田太郎 yamada@example.com 20
3 山本健太 yamamoto@example.com 20

この時,次のコードを実行すると…

User.where(:age => 20).first_or_create(
  :name => "加藤拓哉",
  :email => "kato@example.com",
  :age => 30
)
#=> <User id: 2, name: '山田太郎', email: 'yamada@example.com', age: 20>

id==2のレコードが取得されている.
この場合はまず,whereでUserテーブルからageが20のものを取得し,その中で一番最初のものを見つけるので,結果はid==2のレコードが取得できる.

次のコードを実行すると…

User.where(:age => 30).first_or_create(
  :name => "加藤拓哉",
  :email => "kato@example.com"
)
#=> <User id: 4, name: '加藤拓哉', email: 'kato@example.com', age: 30>

新しくid==4のレコードが取得されている. この場合はまず,whereでUserテーブルからageが30のものを取得するが,テーブル上にひとつもない.
その上でfirst_or_createが実行されるが,先ほどのwhereでレコードがひとつも見つからなかったので,first_or_createの引数で指定した内容のUserが新しく作成され,作成したUserのレコード情報が返ってくる. 注目すべきは,ageに30が入っている点.
実はfirst_or_create以前にwhereで絞り込んだ値を自動的に使ってくれます.

また,createされたので当然データベースも更新されていて,

id name email age
1 藤井隆 fujii@example.com 25
2 山田太郎 yamada@example.com 20
3 山本健太 yamamoto@example.com 20
4 加藤拓哉 kato@example.com 30

となるはずである.

実行例(応用編)

データベースは先ほどと同様に以下のとおりとする.

id name email age
1 藤井隆 fujii@example.com 25
2 山田太郎 yamada@example.com 20
3 山本健太 yamamoto@example.com 20

first_or_createはブロックを渡すことができ,例えば次のコードのようにかけます.

例1

User.where(:age => 20).first_or_create do |user|
  user.name = "前田剛"
  user.email = "maeda@example.com"
end
#=> <User id: 2, name: '山田太郎', email: 'yamada@example.com', age: 20>

例2

User.where(:age => 30).first_or_create do |user|
  user.name = "前田剛"
  user.email = "maeda@example.com"
end
#=> <User id: 4, name: '前田剛', email: 'maeda@example.com', age: 30>

例1はageが20のレコードが存在するので,ageが20のレコードのうち一番先頭のid==2のものを取得している.
このとき,すでにレコードが見つかっているのでブロックの中身は無視される.

例2も上記の基本の実行例と同じくageが30のものを探すが,見つからないので新しくid==4の前田さんのレコードを作成している.
こちらもfirst_or_create以前にwhereで絞り込んだ条件を使ってくれて,ageに30がちゃんと入っています.

その他

  • first_or_create!メソッドもある.こちらはfirstで見つからないときにcreateではなくcreate!を使う.つまり作成に失敗すると例外が発生します.
  • より詳細はRailsのドキュメントを参照

まとめ

  • first_or_createを使うとDBにあればそれを使い,なければ新しく作るみたいなことが綺麗にかける
  • first_or_createはで新しくレコードを作成するときは,ActiveRecordのwhereで絞り込んだ属性をデフォルトで自動的に使ってくれる
  • Rails4からは非推奨で代わりに,find_or_create_byメソッドを使うらしい

書いてる途中で非推奨であることに気づいた.ついでなので次回はfind_or_create_byについて調べてみようかな?

詳細はRailsのドキュメントを参照

参考

Ruby on Rails Documentation

Rails3で有効なパスの場合だけリンクを表示する

Railsのビューでリンクを作成する場合多くの場合でlink_toを使う.
link_toはリンクを作成するが,リンク先がちゃんとあるかどうかは確認されないため,リンク先のルーティングが設定されていないと"No route matches"エラーとなる.

というわけで.urlがルーティング上有効な場合のみリンクを表示するlink_to_only_valid_pathヘルパーを作成した.

app/helpers/application_helper.rbにlink_to_only_valid_pathヘルパ−を追加

module ApplicationHelper
  def link_to_only_valid_path(*args)
      application_name = Rails.application.class.parent_name
      all_routes = eval(application_name)::Application.routes.routes
      return link_to_if(
        all_routes.map{ |r| r.path.match(args.second).present? }.include?(true), *args
      )
  end
end

引数はlink_toと全く同じで,使い方も同じです.
一応やってることはこんな感じ.

  1. ルーティング一覧を取得
  2. 取得したルーティング一覧の中でurlがマッチしたものがあるかを調べる
  3. 1つでもマッチしていればリンク先があり,1つもマッチしなければリンク先がないのでそれぞれをtrue, falseとしてlink_to_ifの条件とする.

これにhttp://またはhttps://で始まる文字列をリンクとするようにしたけど,ここでは本筋ではないので割愛.
ソースコードは以下にあります.
github:gist wishid