Rails3からhas_and_belongs_to_manyより柔軟なhas_many thorughというRelationshipができたので試す。ブログの記事を登録する際に、セレクトボックスで複数のカテゴリを選択する場合を想定している。コントローラーやviewについて記述が無い箇所は、scaffoldで生成したコードと同等のもので動くと思う。

まずはmigrationを使ってテーブルを作る。

# ブログ記事
class Posts < ActiveRecord::Migration
  def change
    create_Table :posts do |t|
      t.string :title
      t.text :body
      t.timestamps
    end
  end
end

# カテゴリ
class Categories < ActiveRecord::Migration
  def change
    create_Table :categories do |t|
      t.string :name
      t.timestamps
    end
  end
end

# ブログ記事とタグを繋ぐ中間テーブル
class Categorizations < ActiveRecord::Migration
  def change
    create_Table :categorizations do |t|
      t.references :post, null: false
      t.references :category, null: false
      t.timestamps
    end
  end
end

中間テーブルのカラム名を複数形にしてしまい少しハマッたので注意。次にモデルを定義する。

# ブログ記事のモデル
class Post < ActiveRecord::Base
  has_many :categorizations, dependent: :destroy
  has_many :categories, through: :categorizations
end

# カテゴリのモデル
class Category < ActiveRecord::Base
  has_many :categorizations, dependent: :destroy
  has_many :posts, through: :categorizations
end

# 中間テーブルのモデル
class Categorization < ActiveRecord::Base
  belongs_to :post
  belongs_to :category
end

最後に、ブログ記事の新規登録画面のviewを少し書き換える。

<%= form_for @post do |f| %>
  <%= render '/shared/validation_messages', :model => @product %>
    <div class="field">
      <%= f.label :name %><br/>
      <%= f.text_field :name %>
    </div>
    <div class="field">
      <%= f.label :body %><br/>
      <%= f.text_area :body %>
    </div>
    <div class="field">
      <%= f.label :category_ids %><br/>
      <%= f.select :category_ids, Category.all.map {|c| [c.name, c.id]}, {}, multiple: true %>
    </div>
  </div>
    <div class="actions">
      <%= f.submit 'Launch this product' %>
    </div>
  </div>
<% end %>

これを使うまで知らなかったんだけど、フォームの項目名を複数系にすることでmultipleな入力も受け付けてくれるようなのですごく簡単にこういったことができる。

 

http streamを使ったchunked uploadのとき、webrickとかだとスルーされる。なのでvalums file uploaderとかpluploadとか使ってるとparamsにHttp::UploadedFileが渡されず、ファイル名だけポツンとそこにいて大変寂しい思いをする。

そういうときはrack middlewareを自前で書いてたんだけど、githubでいいのを見つけた。
newbamboo/rack-raw-upload
使い方は簡単で、Gemfileに以下の一行を追加して

gem 'rack-raw-upload', git: 'git://github.com/newbamboo/rack-raw-upload.git'

RAILS_ROOT/config/initializers/rack_raw_upload.rbみたいなものを作って

Rails.application.config.middleware.use Rack::RawUpload

とするだけでよい。

そうするとparams[:file]にHttp::UploadedFileが渡されるようになるので、そのままpaperclipなりcarrierwaveなりが指定するようにparams[:file]をゴニョゴニョするとうまくいく。

ところで今日、Rails3.1RC6がリリースされ、同時にRails3.1のリリース予定日が8/30と発表されたので要チェックです。

 

Ubuntu10.04からSysVintの後継であるUpstartが搭載されているので、アプリケーションのデーモン化がすごく簡単になったらしいのでrvm+unicorn_railsなRailsアプリで試してみました。

下記は/etc/init/rails_example.confです。

#!/bin/sh
description "Example ROR3.1 application"

start on runlevel [2345]
stop on runlevel [016]

console owner

exec /var/www/.rvm/bin/rails31_unicorn_rails -c /var/www/example.com/config/unicorn.conf.rb -E production /var/www/example.com/config.ru

respawn

これをおいとくだけで以下の事が出来るようになるらしいです。

# サービスの起動
sudo service rails_example start
# サービスの停止
sudo service rails_example stop
# サービスの状況を確認
sudo service rails_example status
# サービスの再起動
sudo service rails_example resart

実はsudo service rails_example reloadするとUSR2が送られてリロードされてたりするんでしょうか。
確認してないけど十分楽なのでいいのではないでしょうか。

 

プログラミングによる遊びの1つとしてCodegolf(コードゴルフ)というゲームがあります。
お題の通りの動作をするプログラムを最小の文字数で書いた人がエライというルールです。

今回は新入社員に研修の息抜きとして、もっともお手軽なプログラミング問題であるFizzBuzzをお題にコードゴルフに挑戦してもらいつつ、自分も挑戦してみました。
結果は100文字ジャスト。以下がそのコード。

enum _{_;{for(int i=1;i<101;i++){System.out.println((i%3<1?"Fizz":"")+(i%5<1?"Buzz":i%3<1?"":i));}}}

静的初期化子を使うのが定石かと思っていたんですが最近のjavaではenumがベストらしいですね。
anarchy golf – FizzBuzzによると最短記録は97文字だそうですがあとどこを削ればいいのか。。。

© 2011 sanojimaru.com Suffusion theme by Sayontan Sinha