Hatena::ブログ(Diary)

130単位

2011-11-29

GitHub ウォッチ中リポジトリのフィードをOPML出力

英語が使えるようになりたいです。

モチベーションの維持がなかなか難しいです。


GitHubリポジトリフィードを読んでみるのはどうかと思いつきました。

f:id:deeeki:20111129185914p:image

前つくったものへ機能追加してみました。

できること

やったこと

Octokit.watched('deeeki').reject{|r| r.owner == 'deeeki'} 

放置しないよう日々眺めていければと思います。


4797359986
Rubyレシピブック 第3版 303の技


関連記事

2011-11-10

Rails3 Shift_JISのCSVダウンロード処理

元々あったRails3でのCSV出力のコードを改善してみました。

要件

  • Windowsユーザーが閲覧するCSV
  • 条件によって絞り込み

ということで、Excelで閲覧するためにShift_JISにする必要があります。また、絞り込みはMetaSearchというgemを活用します。

Ruby/Railsっぽく、というところも意識しつつのリファクタリングの過程を晒してみます。

環境

旧コード (Controller & View)

app/controllers/products_controller.rb

class ProductsController < ApplicationController
  def export
    require 'kconv'
    @products = Product.search(params[:search])
    respond_to do |format|
      format.csv {render :content_type => 'text/csv', :force_encoding => 'SJIS'} 
    end
  end
end

app/views/products/export.csv

<%= 'ID,名前,日付'.tosjis %>
<% @products.each do |p| %>
"<%= p.id %>","<%= p.name.gsub(/"/, '""').tosjis %>","<%= p.created_at.strftime('%Y年%m月%d日').tosjis %>"
<% end %>
改善したい点
  • erbで1レコードを1行におさめないといけないのがしんどい
    • Vimが激重になったりする
  • Rubyスクリプトマークアップ量がしんどい
  • ダブルクォートのエスケープが必要なカラムが多くなるとしんどい
    • Array#joinとか活用するならそもそもModelかHelperに書きたい
  • exportアクションにわけなくてもformatの分岐で事足りる
  • 別のCSV出力もあるとするとDRYでない
  • ファイル名つけたい場合ややこしい response.headers を設定する必要がある

新コード (Model & Controller)

app/models/product.rb

class Product < ActiveRecord::Base
  def self.csv params = {}
    rows = ['ID,名前,日付']
    Product.search(params).each do |p|
      cols = [
        p.id,
        p.name,
        p.created_at.strftime('%Y年%m月%d日'),
      ]
      rows << ('"' << cols.map{|c| c.to_s.gsub(/"/, '""')}.join('","') << '"')
    end
    rows.join("\n")
  end
end

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  private
  def send_csv csv_data, options = {}
    require 'kconv'
    options[:type] ||= 'text/csv'
    send_data csv_data.tosjis, options
  end
end

app/controllers/products_controller.rb

class ProductsController < ApplicationController
  def index
    respond_to do |format|
      format.html do
        @products = Product.search(params[:search]) 
      end
      format.csv do
        send_csv Product.csv(params[:search]), :filename => "#{Time.now.strftime('%Y%m%d%H%M%S')}_products.csv"
      end
    end
  end
end
改善できた点
  • ModelとControllerだけで完結
  • 1カラム1行でカラム追加にも対応しやすいはず
  • 共通処理はsend_csvメソッドにまとめた

どんなもんでしょうか。もっといい方法などありましたら教えてくださいー。


4797363827
Rails3レシピブック 190の技

4797359730
Ruby on RailsによるWebアプリケーション・スーパーサンプル改訂版