のどをRubyでいっぱいにして RSSフィード Twitter

2011-11-08

GitHub Pages を使い始めたこと

| 00:03 |  GitHub Pages を使い始めたことを含むブックマーク  GitHub Pages を使い始めたことのブックマークコメント

ブログが増え(て)ました。

Hi - Hibariya

http://hibariya.github.com/index.html

理由:いつも使っているエディタ(自分の場合はVim)で日記が書きたかった。

あまりにもテキストエリアでの文章編集(とはてな記法)が身につかないので、いかに日記を楽に書くかを追求する予定。まずは、ターミナルから簡単に記事を書くためのツールをつくった。$EDITORを使ってターミナル上で記事を編集・プレビュー・公開までできるCUI向けツール。

no title

さて、ご存知の方も多いと思いますが、世の中には Octopress という素晴らしいツールがあります。僕はRetterの開発途中でOctopressの存在に気づいてしまった。*1

作ってしまったものは仕方がないし、どこまでのものを作ることができるかも試したいので、しばらくは黙々と開発を続けようと思います。パッチなどは小さなものから大きなものまで受け付けております。

*1:もちろんRetterにも優れている点があります。このツールはretterというコマンドで操作するのですが、コマンド自体は片手だけで打ててしまうため、とても指にやさしいです。

2011-06-19

Rails勉強会@東京第63回でセッションオーナーというのをやったこと

| 01:50 |  Rails勉強会@東京第63回でセッションオーナーというのをやったことを含むブックマーク  Rails勉強会@東京第63回でセッションオーナーというのをやったことのブックマークコメント

ここ数ヶ月間、行こう行こうと思いつつ中々いけなかった Rails’ Wiki - Rails勉強会@東京第63回 に行ってきた。今回は RubyKaigi Advent Calendar 2011 | 日本Ruby会議2011(7月16日〜18日) のイベントのひとつでもあるのでした。

久々の参加で遅刻したんですが、着いて早々に [twitter:@takkanm] さんに「Rails3.1のセッションもって」と指名された。こういうイベントで長時間話した経験は無いし、何をやるべきなのかぼんやりとしか分かっていなかったので、結構困惑した。その時点で最新のRailsすらマシンに入れて無かったし、話せることは全くない気がしていたのでした。

だけど心配はいらなかった! 今回は状況がよかった(みんな割と詳しかった、他)のもあると思うけど、事前に入念な準備が必要なわけではないし(あるに越したことはないけど)、知らないことがあるとむしろそれをトピックにできたりして、セッションオーナーというのはとても好都合な立ち位置なのでした。周りの人とだいたい同じような立ち位置のままで、ききたいことがすぐきけるし話に入りやすい。そうやって周りの人に身を任せてお喋りするのは割と楽しい。

セッションオーナーという名目があるとお喋りするのが当然になって、イベントに参加している感がとても出てくるようなので、寂しがり屋でシャイでものぐさな人にはとても合っているのではないかと思いました。

決してうまくやれた訳ではないけど好い経験になった。

あと、そのとき教えてもらった RailsCasts by Ryan Bates on Apple Podcasts はとても便利そうだと思いました。

2011-05-31

Mongoid::Paranoiaで論理削除したドキュメントも一緒くたに問い合わせる

| 00:47 |  Mongoid::Paranoiaで論理削除したドキュメントも一緒くたに問い合わせるを含むブックマーク  Mongoid::Paranoiaで論理削除したドキュメントも一緒くたに問い合わせるのブックマークコメント

hatena.vimの動作確認も兼ねて。

unscoped で論理削除されたものも引っ張ってこれるかと思ったら違った。

    # mongoid-2.0.2/lib/mongoid/paranoia.rb
    <中略...>
    module ClassMethods #:nodoc:
                                                                                                                                                                                                                
      # Override the default +Criteria+ accessor to only get existing
      # documents. Passes all arguments up to +NamedScope.criteria+
      #
      # Returns:
      #
      # A +Criteria+ for deleted_at not existing.
      def criteria(*args)
        super.where(:deleted_at.exists => false)
      end
      # Find deleted documents
      #
      # Examples:
      #
      #   <tt>Person.deleted</tt>  # all deleted employees
      #   <tt>Company.first.employees.deleted</tt>  # works with a join
      #   <tt>Person.deleted.find("4c188dea7b17235a2a000001").first</tt>
      def deleted
        where(:deleted_at.exists => true)
      end
    end
    <中略...>

Mongoid::Paranoiaを使うとcriteriaが上書きされるんですね。だから unscoped とかしてもだめだったのか。

削除されたものは deleted で取れるけど、論理削除関係なく問い合せたいときはどうするんだろう。

module Mongoid::Paranoia::ClassMethods
  def with_deleted
    c = criteria
    c.selector.clear
    c
  end
end

足してその場をしのいだ。

2010-10-12

はっとしたこと

| 20:13 | はっとしたことを含むブックマーク はっとしたことのブックマークコメント

ruby-1.9.2-p0 > 10.times.map{ 'foo' }.map{|v| puts v.object_id }
2152510320
2152510280
2152510200
2152510160
2152510120
2152510060
2152510020
2152509980
2152509920
2152509780
 => [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil] 
ruby-1.9.2-p0 > (['foo']*10).map{|v| puts v.object_id }
2151828140
2151828140
2151828140
2151828140
2151828140
2151828140
2151828140
2151828140
2151828140
2151828140
 => [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil] 

あまり意識してなかった。

no title

数値とかSymbolはどちらも同じでobject_idは変わらない。少し前にRHGをさらっとだけ読んだのでこれは想像できた。

ruby-1.9.2-p0 > 10.times.map{ :urryyyy }.map{|v| puts v.object_id }
498728
498728
498728
498728
498728
498728
498728
498728
498728
498728
 => [nil, nil, nil, nil, nil, nil, nil, nil, nil, nil] 

予想があたってよかった。

2010-10-10

Fabricationを使ってみた

| 21:25 | Fabricationを使ってみたを含むブックマーク Fabricationを使ってみたのブックマークコメント

※2011/11/08 コメント欄で指摘を頂いた箇所を加筆修正しました。また、割と古い記事ですので最新の情報は no title を参照することをお奨めします。

これを作ってるとき、machinistとmachinist_mongoを使っていたんですが、試しに前々から気になっていたFabricationで書き換えてみました。README書いてあることをいくつか実際にやってみたのでメモしておきます。割と使いやすかったです。

何に使えるの

下記をサポートしてるそうですので、Mongoid使えます。やった!

使ったもの

  • Fabrication…本日のメイン
  • Faker…嘘データをどんどこ作ってくれるやつ

QuickStart & 使い方

Gemfile

Rails/Mongoid/RSpec/Fabricationで↓のような組み合わせで使ってます。

group :development, :test do
  gem 'rspec-rails', '>= 2.0.0.beta.22'
  gem 'mongoid-rspec'
  gem 'faker'
  gem 'fabrication'  # <= これ
  gem 'wirble'
  gem 'spork'
end
記述する場所

spec/fabricators.rbに書くか、spec/fabricators/*.rbに複数ファイルにして書いてもいいみたいです。ここに置いておけば、必要になったら勝手に呼ばれます。最初から自分で読み込んでおきたいときはspec/spec_helper.rbなどに書きます。

Fabricatorを書いて使ってみる

spec/fabricators.rbなどにfabricatorを書いていきます。blueprintみたいな感じで。

# Userモデルはこんな感じだとします
class User
  include Mongoid::Document
  field :screen_name, :type=>String
  field :description, :type=>String
  field :site, :type=>String
  field :gender, :type=>String
end

# Userモデルのfabricatorを作ります
Fabricator(:user) do
  screen_name { Faker::Internet.user_name }
  description { Faker::Lorem.paragraph[0..190] }
  site { ['http://', Faker::Internet.domain_name].join }
  gender { ['male', 'female'].sort_by{ rand }.first }
end

作ったFabricatorをspecの中で好きなときに呼び出します。factorygirlやmachinistと同じように、3通りの呼び出し方があります。

# インスタンスを保存して返す
Fabricate(:user)
# => #<User _id: 4cb18e0c011c0e5a2c000001, screen_name: "aidan", description: "Vel iste illo beatae maxime earum accusantium. Facilis doloremque nemo dolores perspiciatis. Eum et nisi sunt qui soluta facilis consequatur quasi. Qui sunt omnis beatae sit. Quisquam earum d", site: "http://wintheiserwunsch.com", gender: "female">

# インスタンスを保存せずに返す
Fabricate.build(:user)
# => #<User _id: 4cb18e32011c0e5a2c000002, screen_name: "darlene", description: "Exercitationem voluptatem voluptatibus officia saepe labore earum. Voluptas ut ipsam soluta. Libero possimus eius illo soluta quo blanditiis quod. Similique ea qui reprehenderit nihil ut cons", site: "http://schiller.uk", gender: "female">

# 属性だけを生成してHashで返す
Fabricate.attributes_for(:user)
# => {"screen_name"=>"jaylon", "description"=>"Et vitae nobis enim non. Quia sunt ipsum laboriosam. Maxime ut neque voluptatum velit est aliquam sequi qui. Eius dolorem id ut assumenda.", "site"=>"http://wuckert.uk", "gender"=>"male"}
Fabricatorの継承とか

すでに作ったのとはちょっと違うのがほしいときは、すでにあるfabricatorを継承することができます。:fromパラメータ継承元の名前を入れて、変更したいフィールドの定義を記述します。

# 必ずfemaleなひとがほしい
Fabricator(:female, :from=>:user) do
  gender 'female'
end

もちろん、継承は使わず呼び出すときに直接指定することもできます。

# いまだけfemaleなひとがほしい
Fabricate(:user, :gender=>'female')
# => {"screen_name"=>"daron", "description"=>"Aut dolor reprehenderit consequuntur nihil magni odit eveniet. A est magni nam vero praesentium. Praesentium quae perferendis mollitia. Voluptatem harum ex aperiam tempora ab nihil voluptas. ", "site"=>"http://huel.com", "gender"=>"female"}
クラスの明示的な指定

:class_nameパラメータで明示的にクラス名を指定することもできます。色々なパターンでFabricatorをつくりたいときなどはこれで。クラス名はシンボルやklass、文字列で指定できます。

# :class_name は :user, User, 'User' などで指定可
Fabricator(:invalid_user, :class_name=>:user) do
  screen_name 'hibariya'
  description 'i have no gender'
end
Sequenceで一意にする

MachinistのShamのようなものも用意されています。*1Fabricate.sequenceを使うと、呼び出すたびにインクリメントする数値が得られます。ブロックも渡せるので数値以外の一意な何かもつくることができます。Fakerには大量の単語とかがコード中にドカっと入ってるんですが、普通に重複しますので、データが一意でないといけないときなどはこれを使います。

大きく分けると3つの書き方になるようです。

Fabricate.sequence(:foo_id) # 呼び出すたびに0から始まる連番を返す
Fabricate.sequence(:bar_id, 1000) # 呼び出すたびに1000から始まる連番を返す
Fabricate.sequence(:future){|n| n.days.since } # 呼び出すたびに1日ずつ未来の日付を返す

さっきのUserモデルの例だとこんな感じになります。

# uriもscreen_nameも重複させたくない!
Fabricator(:user) do
  screen_name { Fabricate.sequence(:screen_name){|i| [Faker::Internet.user_name, i.to_s].join } } # <= ここ
  description { Faker::Lorem.paragraph[0..190] }
  site { Fabricate.sequence(:uri){|i| ['http://', i.to_s, Faker::Internet.domain_name].join } } # <= ここ
  gender { %w(male female).sort_by{ rand }.first }
end
on_init, init_with でnewに引数を渡す

newするのに引数が必要なクラスのfabricatorを作るときなどに使えます

class Site
  def initialize(uri) @uri = uri end
end

# on_initとinit_withで、initializeに渡す引数を指定できる
Fabricator(:site) do
  on_init{ init_with(['http://', Faker::Internet.domain_name].join) }
end
after_build, after_create コールバック

保存する前、保存したあとのコールバック。さっきまで勘違いしていたんですが、Fabricate.buildでもafter_createは呼ばれるようです(でもsaveはされない)これはバグだったそうです(https://github.com/paulelliott/fabrication/pull/36

)。

# User#fetch_recent_entries!がsave前のステップで呼び出される
Fabricator(:foo_user, :from=>:user) do
  after_build {|user| user.fetch_recent_entries! }
end

# User#fetch_recent_entries!がsave後のステップで呼び出される
Fabricator(:bar_user, :from=>:user) do
  after_create {|user| user.fetch_recent_entries! }
end
belongs_to, references_oneな関連を!で表現

belongs_to, references_oneな関係にあるものは!を付けると自動的に作ってくれるらしい。べんり!というのは間違いで、!を付けるか否かで関連が作られるタイミングが変えられるようです(!を付けなければ参照されるまで作られない)。

Fabricator(:umbrella) do
  color { %w(red green blue pink violet purple).sort_by{ rand }.last }
end

Fabricator(:girl) do
  name 'unknown'
  umbrella! # !を付けると即座に関連が生成される
end

Machinist <=> Fabrication 比較表

Machinistとの違いを、よく使う項目だけ表にしてみるとこんな感じでしょうか。*2

MachinistFabrication
Model.blueprint do ~ endFabricator(:model) do ~ end
Model.blueprint(:named_blueprint) do ~ endFabricator(:named_fabricator, :from=>:model) do ~ end
Model.makeFabricate(:model)
Model.make_unsavedFabricate.build(:model)
Model.planFabricate.attribues_for(:model)

*1:Shamを使うと呼び出すデータの順番や一意性が保証されるのでした

*2:注) Model, :modelは何かのモデルクラスに読み替えます

ke_tachibanake_tachibana 2011/11/07 01:25 もう1年も前のエントリに対して何ですが、fabricationについてここまで詳細に突っ込んだ日本語記事は他に見当たらなかったので。

after_createが呼ばれてるのはどうもバグだったように思います。
https://github.com/paulelliott/fabrication/pull/36

あと、
> belongs_to, references_oneな関係にあるものは!を付けると自動的に作ってくれるらしい。
これは http://fabricationgem.org/#!defining-fabricators を見るかぎり違うような気がします。デフォルトではassociationに最初にアクセスするまでそのassociationのFabricatorの実行は遅延されるけど、!をつけることでその遅延を無くせる、という機能のように読めます。

hibariyahibariya 2011/11/08 23:16 本当だ、修正されているようですね。 > after_create

associationの箇所も確かに仰る通りに見えます。完全に勘違いしていました。
ご指摘ありがとうございます!

Connection: close