さくらの専用サーバ(CentOS)にRailsの実行環境を作る
表題の件、手順をメモ。
(1)各種インストール
su yum install emacs yum install ruby yum install rubygems gem install rails -v=2.3.2 gem install passenger gem install ruby-devel gem install httpd-devel passenger-install-apache2-module
(2)下記の内容で /etc/httpd/conf.d/rails.conf を作る
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.5/ext/apache2/mod_passenger.so PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.5 PassengerRuby /usr/bin/ruby RailsAllowModRewrite on RailsMaxPoolSize 4 RailsPoolIdleTime 30 NameVirtualHost XXX.YYY.ZZZ.WW:80ServerName hoge.jp ServerAlias www.hoge.jp DocumentRoot /RAILSROOT/rails/public AddDefaultCharset UTF-8 RailsBaseURI / RailsEnv production RailsAllowModRewrite off PassengerEnabled on
ActiveRecordのupdated_at、created_atを自動更新しない方法
railsのモデル(ActiveRecord)にはtimestamps(updated_atとcreated_at)というフィールドがあって、更新日時、生成日時が勝手に記録されて便利ですね。
でも特定のタイミングでこの自動更新(特にupdated_at)を止めたい場合があります。
そんな時にはActiveRecord::Baseのrecord_timestampsをfalseにするといいみたいです。
例えば、僕の場合:
・CMSみたいな仕組みを作っている
・ページの中身を入れておくPageというモデルがあった。
・このモデルにアクセスカウンター(pages.counter)用のフィールドあり。
・アクセスカウンターは/pages/showが呼ばれる度にpages.counterを+1する仕組み
・ということは/pages/showが呼ばれる度にupdated_atが更新される
・/pages/indexではページの内容が更新された順に並べたい
・updated_at DESCでソートしても「最近閲覧されたページ順」になってしまう
・アクセスカウンターの処理ではupdated_atは更新してくれるな!
というわけで
Page.record_timestamps = false page.count_up Page.record_timestamps = true
という感じのコードになりました。
migrationの新機能(redo, rollback)
実はそんなに新しい機能じゃないっぽいけど、最近知ったのでメモ
最近適用したmigrationを元に戻す(downを実行してくれる)
rake db:rollback
最新のmigrationを適用し直し(downとupをしてくれる)
rake db:migrate:redo
これまではmigrationのdownの部分って適当に書いてて、いざ実行してみると失敗して、DBの構造がよく分からんことになったりした。migrationファイルをコミットする前に一度redoを試しておくとdownの部分を含めて動作の確認が取れるので良いと思う。
2つ同時にコミットするなら
rake db:rollback STEP=2 rake db:migrate
とか。
自動生成したrspecのコードが失敗するときのメモ
rspecの低い(<= 1.2.2)バージョンを前提にgenerateされるコードが多いみたいなので、下記の修正が必要だったりします。
(1)route_forのパラメータは数字(integer)じゃなくて文字列(string)にする
○ route_for(:controller => "comments", :action => "index", :entry_id => "1").should == "/entries/1/comments"
× route_for(:controller => "comments", :action => "index", :entry_id => 1).should == "/entries/1/comments"
(2)route_forの右辺には:methodも含める
○ route_for(:controller => "acts", :action => "update", :id => "1", :manual_id => "1").should
== {:path => "/manuals/1/acts/1", :method => "PUT"}
× route_for(:controller => "acts", :action => "update", :id => "1", :manual_id => "1").should == "/manuals/1/acts/1"
※ GETの場合は文字列のみで良い
(3)formatted_XXX_pathは単にXXX_pathで良い
○ user_path(:id => '1', :format => 'xml').should == "/users/1.xml"
× formatted_user_path(:id => '1', :format => 'xml').should == "/users/1.xml"
参考:
rspec-rails 1.2.2やCucumber 0.2.0にあげるときの作業メモ
Rspec Rails、なんか仕様が変わった?
rspec_nested_scaffoldでネストした構造のscaffoldが一発生成
例えばブログ記事(Entry)の下にコメント(Comment)が複数ぶらさがっているとしますよね。
そいつを操作するプログラムを作る場合、routes.rbの指定は
map.resources :entrys do |entry| entry.resources :comments end
とか指定するわけですよね。
でURLは「/entrys/1/comments」とかなるわけですよね。
こういう「URLをネストさせて」という構造、実は今まで嫌いでした。なんかメンドくさかったんですよね。ごちゃごちゃしてて。
でも「rspec_nested_scaffold」というのを知って、目から鱗が落ちましたね。「私がわるうございましたー!」みたいな。
script/plugin install git://github.com/phorsfall/rspec_on_rails_nested_scaffold.git script/generate scaffold entry subject subject:string body:text script/generate rspec_nested_scaffold comment body:text entry_id:integer --owner=entry
と実行して
config/routes.rb
map.resources :entries do |entries| entries.resources :comments end
app/models/entry.rb
has_many :comments, :uniq => true
app/models/comment.rb
belongs_to :entry
app/views/entries/show.html.erb
%= link_to 'Show Comments', entry_comments_path(@entry) %> |
と追記すればOK! これで記事の下にコメントがついて、という構造を正しく処理してくれるプログラムが出来上がりです。
超カンタン!
ActiveRecordのhas_manyに:uniqを指定して重複を削除
ActiveRecordのhas_manyに:uniqを指定したときの動作を確認してみた。
グループの下に複数のユーザーがぶら下がっているテーブル構成を考える。
class Group < ActiveRecord::Base has_many :users, :uniq => true end class User < ActiveRecord::Base belongs_to :group end
とか
class Group < ActiveRecord::Base has_many :users, :though => :groups_users, :uniq => true has_many :groups_users, :dependent => :destroy end class User < ActiveRecord::Base has_many :groups, :though => :groups_users, :uniq => true has_many :groups_users, :dependent => :destroy end
という感じ。
consoleで
- グループを作る g
- ユーザーを作る u
- 同じユーザーを何度も関連づける g.users << u
- 重複して登録されているか確認する g.users.size
としてみる。
g = Group.create! u = User.create! 10.times do g.users << u p g.users.size end
結果は
1 1 1 1 1 1 1 1 1 1
ということで重複なし。
:uniq => trueを付けない場合の挙動は以下。
1 2 3 4 5 6 7 8 9 10
という感じで重複して追加されていきます。
※ 中間テーブルを作らない1対多の構成( has_many :users と belongs_to :group の方)だと、そもそもテーブル構成的に:uniq=>trueなので、DB上は重複がない。