怖話をruby1.9.3-p194、rails3.2.8にアップグレードしました。
ビビリなのでとりあえずconfig.active_record.whitelist_attributesはまだで。
@machidaさんがsassをcompassベースにしたりと、そろそろ少し複雑化してきたコードベースの負債を返済中。
怖話をruby1.9.3-p194、rails3.2.8にアップグレードしました。
ビビリなのでとりあえずconfig.active_record.whitelist_attributesはまだで。
@machidaさんがsassをcompassベースにしたりと、そろそろ少し複雑化してきたコードベースの負債を返済中。
>> helper.link_to 'foo', 'bar'
=> "<a href="\"bar\"">foo</a>"
>> app.users_path
=> "/users"
# config/application.rb
module Foo
class Application < Rails::Application
(snip)
config.sass.preferred_syntax = :sass
end
end
怖話に自分の投稿した怖い話にコメントが付いたらメール通知する機能を付けました。
Userにメール通知する/しないフラグを追加して、CommentObserverを書く。
# app/models/comment_observer.rb:
class CommentObserver < ActiveRecord::Observer def after_create(comment)
if comment.story.user.notify_comment
mail = NoticeMailer.comment_notice(comment)
mail.transport_encoding = '8bit'
mail.deliver
end
end
end
拡張子をfoo.html.hamlとかにしとくだけでHTMLメールになるのも便利ですね。
怖話はスマホ向けWebサイトです。今のスマホのHTML5 Audioではサウンドノベル風に音を鳴らすのが難しいのでcordovaでアプリ版を作っています。
しかし、サーバー側で普通のブラウザからのアクセスなのか、cordovaからのアクセスなのか区別がつかない。数ページ程度だったらquery stringにでも何か付けてアクセスするようにすればいいけど、怖話はサイト全体に渡ってどちらからもアクセスされる可能性があるのでcookieが使えないガラケーのようなquery string引き回しなどはやりたくない。
StackOverflow駆け込み寺に問い合わせたところ、10minで答えが来た。
「cordovaのソース弄ってヘッダ追加すれば?」
なるほどですねー!
% git diff
diff --git a/framework/src/org/apache/cordova/DroidGap.java b/framework/src/org/apache/cordova/DroidGap.java
index 5e2586d..dfbdb44 100755
--- a/framework/src/org/apache/cordova/DroidGap.java
+++ b/framework/src/org/apache/cordova/DroidGap.java
@@ -562,7 +562,9 @@ public class DroidGap extends Activity implements CordovaInterface {
};
Thread thread = new Thread(runnable);
thread.start();
- me.appView.loadUrl(url);
+ HashMap headers = new HashMap();
+ headers.put("X-Access-From-Cordova", "true");
+ me.appView.loadUrl(url, headers);
}
});
}
X-Access-From-Cordovaという勝手なヘッダを付けて、以前のエントリー通りcordovaをbuildして自分のプロジェクトに放り込む。
サーバー側(Rails)に下記helperを追加。
# app/helpers/application_helper.rb
module ApplicationHelper
def cordova?
request.headers['X-Access-From-Cordova'] == 'true'
end
end
神様仏様StackOverflow大明神様 <3 <3 <3
Macを再インストールしたのでrvmが新しくなったからか、capれない。
% bundle exec cap staging deploy
/Users/komagata/.rvm/lib/rvm/capistrano.rb:5:in `': RVM - Capistrano integration was extracted to a separate gem, install: `gem install rvm-capistrano` and remove the `$LOAD_PATH.unshift` line, note also the 'set :rvm_type, :user' is now the default (instead of :system). (RuntimeError)
長いエラーをちゃんと読むと、rvmのcapistrano関連の部分はrvm-capistranoとして別gemになったようです。Gemfileに追加します。
group :development do
gem 'rvm-capistrano'
end
また「$LOAD_PATH.unshiftしてんのを取れ」と出てるので大抵の人はRAILS_ROOT/config/deploy.rb
に書いてる下記を取ればOK。
$:.unshift(File.expand_path('./lib', ENV['rvm_path'])) # REMOVE ME!
コンパイラが変わるという大転換期なので仕方無いとは思いますが、Xcode依存のゴタゴタはプログラマーにも厄介。デザイナーさんに環境作ってと気軽に言い辛いここ最近のMac環境です…。
deviseはデフォルトでuserの更新(Devise::RegistrationsController#update)に現在のパスワード(current_password)が要る。
ソースを見てみるとmodelにupdate_without_passwordというのがあるのでこれかと思いきや、これはpasswordとpassword_confirmation無しでupdateするものだった。
自分でupdate_without_current_passwordを作る。
# app/models/user.rb:
class User < ActiveRecord::Base
def update_without_current_password(params, *options)
params.delete(:current_password)
if params[:password].blank?
params.delete(:password)
params.delete(:password_confirmation) if params[:password_confirmation].blank?
end
clean_up_passwords
update_attributes(params, *options)
end
end
controllerからもこれを使うようにする。
# app/controllers/registrations_controller.rb:
class RegistrationsController < Devise::RegistrationsController
def update
@user = User.find(current_user.id)
if @user.update_without_current_password(params[:user])
sign_in @user, bypass: true
set_flash_message :notice, :updated
redirect_to after_update_path_for(@user)
else
render 'edit'
end
end
end
面倒ですね。
怖話ではさくらVPS512を使ってます。性能的にはまだ問題無いんだけど、HDD容量が20GBとちと不安。先日もproduction.logが1.7GBになってたのでちゃんとローテートする。
$ cat /etc/logrotate.d/kowabana
/var/www/kowabana/shared/log/*.log {
weekly
missingok
rotate 24
dateext
compress
delaycompress
lastaction
pid=/var/www/kowabana/shared/pids/unicorn.pid
test -s $pid && kill -USR1 "$(cat $pid)"
endscript
}
newrelicのログとかunicornのログとかも一辺にローテートされるから楽でいいですね。-dをつければdry run。-fで強制実行。
sudo logrotate -df /etc/logrotate.d/kowabana
後は一日14MBぐらいずつ増えるDBのバックアップファイルを何とかしなきゃ。
Railsで綺麗なURLにしたいと思うと一つのControllerに機能が集中して困ることがあります。
/comments
/posts/1/comments
/users/1/comments
# config/routes.rb:
Foo::Application.routes.draw do
resources :comments
resources :posts do
resources :comments
end
resources :users do
resources :comments
end
end
例えばこんな風にしたい時。
# app/controllers/comments_controller.rb:
class CommentsController < ApplicationController
def index
@comments =
if params[:post_id]
Post.find(params[:post_id]).comments
elsif params[:user_id]
User.find(params[:user_id]).comments
else
Comment.all
end
end
end
こんな風に書く?えーキモーイ。そもそもそれぞれの場合でviewが全然違うんですけどーみたいな場合。
そんなんねぇ俺の糞みたいな悩みはねぇStack Overflowさんに聞けば一発なんですよ。
Rails Namespace vs. Nested Resource - Stack Overflow
controllerのnamespaceでスッキリ書けるみたいです。
/comments
/posts/1/comments
/users/1/comments
# config/routes.rb:
Foo::Application.routes.draw do
resources :comments
resources :posts do
resources :comments, controller: 'posts/comments'
end
resources :users do
resources :comments, controller: 'users/comments'
end
end
# app/controllers/comments_controller.rb:
class CommentsController < ApplicationController
def index
@comments = Comment.all
end
end
# app/controllers/posts/comments_controller.rb:
class Posts::CommentsController < ApplicationController
def index
@comments = Post.find(params[:post_id]).comments
end
end
# app/controllers/users/comments_controller.rb:
class Users::CommentsController < ApplicationController
def index
@comments = User.find(params[:user_id]).comments
end
end
$ rake routes
(snip)
comments GET /comments(.:format) comments#inde
post_comments GET /posts/:post_id/comments(.:format) posts/comments#index
user_comments GET /users/:user_id/comments(.:format) users/comments#index
(snip)
おおお、これはスッキリ!
Stack Overflow脳の恐怖。
Railsの設定ファイルを環境毎に書けるプラグインをいつも見失う。なんて名前だったっけ?
rails configとか検索し辛いワードなのでここに記す。(via @fakestarbabyさん)
railsjedi/rails_config - GitHub
SinatraやPadrinoに対応してるのにrails_configとは是如何に。