2012年3月13日火曜日

都道府県別に表示する

簡単に都道府県別で分けれたらいいかと思い、プロジェクト内で作成したのでここにメモ

今回重要なのは都道府県をマッチさせなければならない為、登録の際に間違って登録されていたらうまく表示されない。

routes.rb
resources :users

resources :prefectures do
  resources :users
end

usersが存在するという仮定で作成
都道府県表示する為に

users_helper.rb
def choose_region
    %w(北海道 青森県 岩手県 宮城県 秋田県
        山形県 福島県 茨城県 栃木県 群馬県
        埼玉県 千葉県 東京都 神奈川県 新潟県
        富山県 石川県 福井県 山梨県 長野県
        岐阜県 静岡県 愛知県 三重県 滋賀県
        京都府 大阪府 兵庫県 奈良県 和歌山県
        鳥取県 島根県 岡山県 広島県 山口県
        徳島県 香川県 愛媛県 高知県 福岡県
        佐賀県 長崎県 熊本県 大分県 宮崎県
        鹿児島県 沖縄県
      )
  end

users_controller.rb
def index
    if params[:prefecture_id]
      @users = User.where(:PREF => NKF.nkf("-eW", params[:prefecture_id])).order("created_at DESC").paginate(:page => params[:page], :per_page => 40)
    else
      @users = User.where("NAME <> ''").order("created_at DESC").paginate(:page => params[:page], :per_page => 70)
    end
  end


ここでもしパラメーターが[prefecture_id]が来たらwhereで(:PREF)のNKF.nkf("-eW",)で変換されたパラメーター[:prefecture_id]を返すという設定。
NKFは前回でのブログでmysqlの文字コードが違う為に今回仕方なく設定している。

index.html.erb
<h3>都道府県別</h3>
  <% choose_region.collect do |p| %>
    <%= link_to p, prefecture_users_path(:prefecture_id => p),
      :class => 'prefectures' %>
  <% end %>

<div class="organization">
      <% @users.each do |user| %>
        <%= link_to(user.name, user) %><br/>
      <% end %>
    </div>

という形。choose_regionで都道府県をcollectで出し、それぞれをリンクにして、無理矢理prefecture_users_pathで指定しいる
今回は都道府県用のdbを作成しないので無理矢理パスを決めている。

以上のようにすれば都道府県がしっかり登録されていれば都道府県をクリックしたら都道府県別に表示された。

文字コードを変換する方法

今回のプロジェクトは既に昔から動いているperlで出来たHPの管理システム。
mysqlの文字コードはlatin1を使用していてテンパったのでここにメモ

database.ymlを書く

development:
  adapter: mysql2
  encoding: latin1
  database: データベース名
  pool: 5
  username: ユーザー名
  password: パスワード

データベースを作る

  • 今回は既存のデータに追加する形で使う
  • データベースのテーブル名は大文字である
  • 必要なデータだけdevelopmentで再現する
$ rails g model user

class CreateUsers < ActiveRecord::Migration
  def change
    if Rails.env.production?
      add_column :USER, :advertisement, :text
      add_column :USER, :created_at, :datetime
      add_column :USER, :updated_at, :datetime
    else
      create_table :USER do |t|
        t.string :NAME
        t.string :PREF
        t.string :ADDRESS
        t.string :EMAIL
        t.string :TEL
        t.text   :advertisement #今回追加する部分
 
        t.timestamps
      end
    end
  end
end

今回は1つデータベースに追加する形なので小文字がRailsプロジェクトで作成したカラムである。他は開発環境で再現する為に作った開発環境のみのDB。
またRAILS_ENVの時は「add_column」で「USER」テーブルに追加する

次にモデルの編集

class User < ActiveRecord::Base
  self.table_name = "USER" #このままだとseedに挿入出来ないのでテーブル名を指定する。

  attr_accessor :ad, :pref, :address, :name # カラム名を変換

  after_find do # 変換する
    self.pref = self.PREF ? NKF.nkf("-Ew", self.PREF) : ""
    self.ad = self.advertisement ? NKF.nkf("-Ew", self.advertisement) : ""
    self.address = self.ADDRESS ? NKF.nkf("-Ew", self.ADDRESS) : ""
    self.name = self.NAME ? NKF.nkf("-Ew", self.NAME) : ""
  end

  before_save do
    self.PREF = NKF.nkf("-eW", self.pref) if self.pref
    self.ADDRESS = NKF.nkf("-eW", self.address) if self.address
    self.NAME = NKF.nkf("-eW", self.name) if self.name
    self.advertisement = NKF.nkf("-eW", self.ad) if self.ad
  end
end

seedを作成する
中身は以下の通りである。「attr_accessor」で指定したカラム名に変更
テキスト内容は以下の様にして外部ファイルを読み込む

pref = ["北海道","東京都","神奈川県","愛知県","大阪府","福岡県","沖縄県"]
0.upto(200) do |idx|
  User.create!(
    :name => "団体名第 #{idx}",
    :pref => "#{pref[idx % 7]}",
    :address => "#{pref[idx % 7]}",
    :EMAIL => "mail#{idx}@example.com",
    :TEL => "00-1234-5678",
    :ad => File.read(Rails.root.join("db/seeds/advertisement.txt"))
  )
end

あとはcontrollerを設定すれば表示されるはずです。「次は都道府県別に表示する」をメモします。

アプリケーションをサーバに上げる手順

Railsアプリケーションを完成させたのでそれを上げるまでの一連の流れをメモ!

ドメインを作成

レポジトリを作る
$ mkdir hoge
$ hg init
$ ls -a
.  .. .hg
「hg init」でレポジトリが出来るので確認してコミットする
$ hg push ssh://xxx@hg.xxxx.jp/directory/directory/main
.hg/hgrcを編集する
[paths]
default = ssh://xxx@hg.xxxx.jp/directory/directory/main
とすれば以降プッシュが楽になる。

デプロイ先を決める

deploy.rbを書く
require 'bundler/capistrano'
load 'deploy/assets'

set :application, "application名"
set :scm, :mercurial
set :use_sudo, false
set :keep_releases, 3

desc "説明文"
task :production do
  set :deploy_to, "/var/rails/#{application}"
  set :repository, "ssh://xxx@hg.xxxx.jp/directory/directory/main"
  set :user, 'app'
  set :runner, "app"
  set :staging_server, false
  set :use_passenger, true
  set :rails_env, 'production'
  set :resettable, false  role :app, "サーバー"
  role :web, "サーバー"
  role :db,  "サーバー", :primary => true
  set :default_environment, {
    'PATH' => "/usr/local/bin:$PATH",
  }
end

desc "説明文"
after "deploy:update_code", :roles => :app do
  run "cp #{shared_path}/config/database.yml #{release_path}/config/"
end

namespace :deploy do
  # deploy:restart の上書き
  desc "説明文"
  task :restart do
    run "mkdir -p #{shared_path}/tmp"
    run "touch #{shared_path}/tmp/restart.txt"
  end
end
↓ デプロイ先にフォルダを作る
$ cap production deploy:setup
database.ymlを作る
通常のサーバー上であれば
/var/rails/application名/shared/config/database.ymlに書く
production:
  adapter: mysql2
  encoding: 文字コード
  database: application名
  pool: 5
  username: ユーザー名
  password: パスワード
  timeout: 5000

デプロイする
$ cap production deploy

サーバー上で手動でマイグレーションする(deploy.rbに書かない場合)
サーバー上で
$ export RAILS_ENV=production
$ bundle exec rake db:migrate

サーバー上で手動でrake db:assets:precompileをする(deploy.rbに書かない場合)
$ export RAILS_ENV=production
$ bundle exec rake db:assets:precompile

apacheのconfを書く
標準であればこんな感じ?
<VirtualHost *:80>
  ServerName ドメイン
  ErrorLog "/var/log/httpd/ドメイン.error_log"
  CustomLog "/var/log/httpd/ドメイン.access_log"
  DocumentRoot /var/rails/linkage/current/public
  RailsEnv production
  RackEnv production
  PassengerRestartDir /var/rails/linkage/shared/tmp
</VirtualHost>

apacheのconfが間違っていないか確認
$ sudo ./apachectl configtest
apacheの再起動
$ sudo ./apachectl graceful