超自己満足プログラミング このページをアンテナに追加 RSSフィード

2011-05-31

[] ハッシュの値を宣言と同時に参照する方法

久々に更新しますが、かなり自分用のメモですorz


ruby だと以下のように書くのをperlでどう書けばいいのか。。

# ruby
# 無名ハッシュ(という呼び方でいいかわからないけど)を作成と同時に値を引っ張る
{:k1 => 'v1', :k2 => 'v2'}[:k2]  # ==> "v2"

一応、こんな感じで書けたけど、リファレンスにせずに引っ張る方法はわからず。。

# perl
{k1 => 'v1', k2 => 'v2'}->{k2}  # ==> "v2"

(k1 => 'v1', k2 => 'v2'){k2}  # syntax error...

配列だとrubyと同じ感じでできるんだけどな〜。

# ruby
# 無名配列を作成と同時に値を引っ張る
%w[one two three][1]  # ==> "two"
# perl
qw(one two three)[1]  # ==> "two"

2011-02-25

[] image_tagで付加される画像タイムスタンプを、production環境でも画像ファイル更新されたタイミング更新されるようにする

image_tagで画像を表示した際に、srcの後ろに付くタイムスタンプ

基本的には File.mtime(image_path) なので、画像ファイルの最終更新時刻です。

image_tag 'rails.png'  #=> <img src="/images/rails.png?1298610241" alt="Rails" />

なので、developement環境では画像ファイルをtouchしてあげたりすると、タイムスタンプ更新されます。

しかし、production環境ではtouchしても更新されません。(passengerなり、サーバリスタートすれば更新されます)


なぜこうなるかは、ActionView::Helpers::AssetTagHelper の rails_asset_id メソッドを見るとわかります。

# File actionpack/lib/action_view/helpers/asset_tag_helper.rb
        def rails_asset_id(source)
          if asset_id = ENV["RAILS_ASSET_ID"]
            asset_id
          else
            if @@cache_asset_timestamps && (asset_id = @@asset_timestamps_cache[source])
              asset_id
            else
              path = File.join(ASSETS_DIR, source)
              asset_id = File.exist?(path) ? File.mtime(path).to_i.to_s : ''

              if @@cache_asset_timestamps
                @@asset_timestamps_cache_guard.synchronize do
                  @@asset_timestamps_cache[source] = asset_id
                end
              end

              asset_id
            end
          end
        end

最初1回は、File.mtime(path) をちゃんと取ってくれるのですが、

その際に、@@asset_timestamps_cache[source] = asset_id で、キャッシュして、

以降は、そのキャッシュが使われます。


で、@@cache_asset_timestamps が何かを見ると

# File actionpack/lib/action_view/helpers/asset_tag_helper.rb
      def self.cache_asset_timestamps
        @@cache_asset_timestamps
      end

      # You can enable or disable the asset tag timestamps cache.
      # With the cache enabled, the asset tag helper methods will make fewer
      # expense file system calls. However this prevents you from modifying
      # any asset files while the server is running.
      #
      #   ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
      def self.cache_asset_timestamps=(value)
        @@cache_asset_timestamps = value
      end

      @@cache_asset_timestamps = true

booleanの値です。

さらにセッターの上に今回の答えがコメントで書かれてますが、

ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false すれば、

毎回 File.mtime(path) してくれるようになります。


なので、initializersとかに、適当ファイルを作って、

# config/intializers/cache_asset_timestamp.rb とか
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false

だけ書いておけば、production環境でもtouchしたらタイムスタンプ更新されるようになります。


ちなみに、development環境は、config/environments/development.rb で

config.cache_classes = false

になってると思いますが、cache_classesがfalseだと、

ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false

が実行されるので、development環境では何もしなくてもタイムスタンプ更新されるっぽいです。

2011-02-17

[] jpmobileを使って、au/softbankでも、controller内で、ドコモ絵文字マッピング済みのutf8値を得る方法

非常にわかりにくいタイトルですが、

ユーザテキストフォームに絵文字を入れて送ってきたときの話しです。

以下のようなコードがあった際に、

class HogeController < ApplicationController
  mobile_filter

  def hoge
    # 例えば、ドコモの「晴れ」に対応する絵文字は、jpmobileの
    # before_filterを通った、actionの時点で、
    #   docomo   : \xEE\x98\xBE
    #   au       : \xEE\x92\x88
    #   softbank : \xEF\x81\x8A
    # となっている
  end
end

そのままhogeアクションviewで表示するなら、jpmobileのafter_filterがかかって、

docomo   : \xF8\x9F (sjis)
au       : \xF8\x9F (sjis)
softbank : \xEE\x98\xBE (utf8)

になるのですが、hogeアクションの中で、au/softbankでもdocomoの値を手に入れるにはどうしたらよいでしょうか。


一応、下記の方法で手に入れることが出来たので、メモっておきます。

class HogeController < ApplicationController
  mobile_filter

  def hoge
    # strが変換したい文字列とすると
    str = Jpmobile::Emoticon::utf8_to_unicodecr(str)
    str = Jpmobile::Emoticon::unicodecr_to_external(str, Jpmobile::Emoticon::CONVERSION_TABLE_TO_DOCOMO, false)
    # これで strは
    #   docomo   : \xEE\x98\xBE
    #   au       : \xEE\x98\xBE
    #   softbank : \xEE\x98\xBE
    # となります
  end
end

単純に、jpmobileのafter_filterをかけているだけですが、

unicodecr_to_externalの3つ目の引数をfalseにしてutf8-->sjis変換を行なわないようにしています

2010-12-13

[] 主キー(primary key)の id を任意に指定して、createする

# ruby script/console

# 普通に指定しても無視される
>> User.create(:id => 100)
=> #<User id: 1, created_at: "2010-12-13 02:47:03", updated_at: "2010-12-13 02:47:03">

# ブロックで指定すると
>> User.create do |u|
?>   u.id = 100
>> end
=> #<User id: 100, created_at: "2010-12-13 02:48:22", updated_at: "2010-12-13 02:48:22">

使う機会は・・・orz

2010-11-25

[] sqlite3-ruby の version が 1.2.x だと、select AS名前を指定したときに integer 型のカラムのはずが string 型で取れてくる件

sqlite3-ruby : version 1.2.5

$ rails testapp1
$ cd testapp1
$ ruby script/generate model user
$ rake db:migrate
$ ruby script/console
>> User.create
=> #<User id: 1, created_at: "2010-11-25 08:49:43", updated_at: "2010-11-25 08:49:43">
>> User.first.id.class
=> Fixnum
>> User.find(:first, :select => "id AS user_id").user_id.class
=> String  # あらら

sqlite3-ruby : version 1.3.0

$ rails testapp2
$ cd testapp2
$ ruby script/generate model user
$ rake db:migrate
$ ruby script/console
>> User.create
=> #<User id: 1, created_at: "2010-11-25 08:57:44", updated_at: "2010-11-25 08:57:44">
>> User.first.id.class
=> Fixnum
>> User.find(:first, :select => "id AS user_id").user_id.class
=> Fixnum  # OK

まぁ findで:selectを使うことがそうないし、ましてAS使うこととかほぼないですが。


ちなみに rails は 2.3.10