かなり開発寄りなWebディレクターのブログ 企画から運用まで、ウェブの話題全部入り。株式会社一騎 公式ブログ。

271月/120

fail2ban の導入ではまった2点


一定のルールに従ってアクセスを自動的に遮断してくれる fail2ban を導入しようとしたところ、非常に基本的なところで2点はまったのでメモ。

CentOS 5.5

> yum install fail2ban
> /etc/init.d/fail2ban start

だけで大丈夫かと思ったのですが、実験してみても ban されません。

原因は2点、いずれも jail.conf[ssh-iptables] セクション。

1. enable = false になっていた

デフォルトでオンになっているものと思っていました…(というかどこかにそう書いてあった)。

2. logpath = /var/log/sshd.log になっていた

自分の環境では /var/log/secure でした…。

51月/120

Rails3: ActiveRecord で association の一覧を取得する


association を再帰的にコピーする recursive_dup を実装したくて調べてみたところ、ActiveRecord::Reflection::ClassMethods に reflect_on_all_aggregations がありました。

ActiveRecord::Base は ActiveRecord::Reflection を include していますので、ModelName.reflect_on_all_aggregations で全ての association を取得することができるようです。

ちなみに引数として、:has_many, :has_one など association のタイプを渡すことができます。また、各 association の詳細は、ModelName.reflect_on_aggregation(:association_name) で取得することができます。

2112月/110

Rails3: accepts_nested_attributes_for と inverse_of


accepts_nested_attributes_for を使うと、ひとつのフォームで親モデルと子モデルを同時に生成できるので便利です。

ところが、子モデルの方に

validates :親モデル_id,
  presence: true

を指定していると、親モデルが永続化されていない状態だと親モデル自体が存在しないとみなされてしまい、子モデルが invalid になる→親モデルも invalid になって親モデルを永続化できない、という問題が発生しました。

調べてみたところ、has_one, has_many, belongs_to には inverse_of オプションがあり、このケースではこちらが有効なようです。

親モデルの方に、

has_many :子モデルs, inverse_of: :親モデル

と指定します。

さらに、子モデルのバリデーションを、

validates :親モデル, # 親モデル_id ではない
  presence: true

とすると、親モデル.子モデルs.build で生成された子モデルに関しては、親モデルが(永続化前でも)既に存在しているとみなされ、子モデルと親モデルを同時に save することが可能になります。

1912月/110

Ruby: Stack level too deep


うっかり send メソッドを定義してしまったせいでした。

Tagged as: No Comments
1512月/110

Rails 3.1: accepts_nested_attributes_for 周りの TIPS 2点


:all_blank

:reject_if オプションで、ネストされたモデルを保存しない条件を指定できますが、その際に :all_blank が「値が全て空の場合に」のショートカット(というか定数)として利用できます。

accepts_nested_attributes_for :profile
  if_reject: :all_blank

field.object.new_record?

便利な :all_blank 定数ですが、削除のための _destroy チェックボックスが新規レコードにも表示されてしまっていると、_destroy = 0 の 0 は blank ではないため reject されません。

そこで、新規レコードには _destroy チェックボックスを表示しないようにします。

FormBuilder の保有している ActiveRecord オブジェクトには object プロパティでアクセスできますので、

<% unless field.object.new_record? %><%= field.check_box :_destroy %><% end %>

とすれば OK ですね。

912月/110

Rails 3.1 のローカライズヘルパーにデフォルト値をセット可能にする


Rails 3.1 の l ヘルパーこと localize ヘルパーはデフォルト値をセットできないため、オブジェクトが nil かどうかで分岐をさせないといけないことが多々あり不便なので改造します。

以下の内容で config/initializers にファイルを作成しましょう。

module ActionView::Helpers::TranslationHelper
  def localize_with_default(object, options = {})
    default = options.delete(:default)

    if object.nil?
      default
    else
      localize_without_default(object, options)
    end
  end
  alias_method_chain :localize, :default
  alias :l :localize
end
<%= l(date, :format => :long, :default => '-' %>

こんな感じにすると、date が nil の場合は :default に設定した値が表示されます。

簡単な改修ですがなかなか便利です。

912月/110

Androidアプリが最もダウンロードされるのは日曜の夜


Android-Market-Growth

100億ダウンロード到達に関して、参考になりそうな情報があったのでメモ。

Sunday Night Is Most Popular Time to Download Android Apps

The U.S. is not the most app crazed country either — it ranked fourth behind South Korea (no. 1), Hong Kong (no. 2) and Taiwan (no. 3). Rounding out the top ten includes Singapore (no. 5), Sweden (no. 6), Israel (no. 7), Denmark (no. 8), the Netherlands (no. 9) and Norway (no. 10).

アプリが活発に利用(DL?)されているのは、1位:韓国、2位:香港、3位:台湾、4位:アメリカ、5位:シンガポール、とアジアが強い。

Meanwhile, the top categories for Android app downloads include games (25.6%), entertainment (12.2%), tools (11.7%), music (4.28%) and social (4.08%).

ダウンロード数が多いカテゴリは、ゲーム(25.6%)、エンタメ(12.2%)、ツール(11.7%)、音楽(4.28%)、ソーシャル(4.08%)。

But the most interesting tidbits were associated with how Android owners use their apps. About 12 billion miles are navigated on Google Maps each year — which is equivalent to more than 37,000 trips to the moon — and 100 million words are translated every week in 200 different countries on Google Translate.

年間120億マイル(月までの距離の37,000倍以上)のナビゲーションと、200カ国で毎週1億語の翻訳が利用されている。

As for when most people download apps, searching through the Android Market the night before the work week starts is evidently a common activity. The most popular time to download an Android app is 9:00 p.m. on Sunday, while the least popular time to do so is just seven hours later at 4:00 a.m. Monday morning.

アプリが最も多くダウンロードされている時間帯は日曜の午後9時、最も少ない時間帯は月曜の深夜4時。

Tagged as: No Comments
912月/110

ウェブ開発に便利な Chrome のシークレットモード


Google Chrome シークレットモード

Google Chrome には履歴や Cookie を残さずにブラウザを利用できる、シークレットモードというモードがあります。

他人に知られずに閲覧したい場合は、Google Chrome のシークレット モードを使用できます。シークレット モードは次のように機能します:

  • シークレット モードで開いたウェブページやダウンロードしたファイルは、閲覧履歴やダウンロード履歴に記録されません。
  • 新しい Cookie は、開いているすべてのシークレット ウィンドウを閉じるとすべて削除されます。
  • シークレット モードの使用中に変更した Google Chrome のブックマークや全般設定はすべて保存されます。

主にアレなサイトを閲覧するための機能かとは思うのですが、ウェブアプリ開発にも何かと便利です。

  • キャッシュや Cookie を削除した状態での動作確認が簡単にできる
  • ログイン、ログアウト状態を同時に開いておくことができる
  • ブラウザウィンドウ間でログイン状態が共有されないので、SNSなど、複数のユーザーのインタラクションの動作確認が簡単にできる

複数のブラウザを使い分けてもよいのですが、やはり開発には使い慣れたブラウザが一番です。

シークレットモードの起動方法は、キーボード ショートカットの Ctrl+Shift+N(Windows、Linux、Chrome OS)、⌘-shift-N(Mac)、またはツールメニューから「新しいシークレットウィンドウ」です。

Mac の場合は、Dock の Chrome アイコンを右クリック→「新規シークレットウィンドウ」で直接シークレットウィンドウを開くことも可能です。

拡張機能をオンにする

拡張機能

シークレットモードでは拡張機能はデフォルトですべてオフになっています(拡張機能が閲覧履歴をどう利用するか分からないためでしょう)。オンにするには、拡張機能の一覧画面で各機能の左側の三角をクリックすると「シークレットモードでの実行を許可する」チェックボックスが表示されますので、これをチェックします。

関連情報

Tagged as: No Comments
712月/110

Write failed: Broken pipe 対策


~/.ssh/config に以下を追記します(ファイルがなければ作成します)。

Host *
  ServerAliveInterval 30

ちなみに、ServerAliveCountMax を設定するように書いてある記事も散見されますが、こちらは切断までのリトライ回数ですので、ServerAliveInterval を適切な長さに設定してやれば不要(のはず)です。

Tagged as: , No Comments
712月/110

Rails 3.1: accepts_nested_attributes_for + fields_for の中で label の日本語化


accepts_nested_attributes_for と fields_for を使った、ネストされたモデルのフォームを作成した際、子モデルの label(= fields_for の中の label) に対して i18n が効かない(ラベルが日本語化されない)問題に対応してみました。

原因は、accepts_nested_attributes_for と fields_for  を使っていると i18n のキーが以下のようになってしまい、これに Rails 3.1 の FormBuilder が対応していないためです。

helpers.label.proposal[conditions_attributes][0][message_attributes].body

なので、上のようなキーを以下のように変更してあげているという内容です。

helpers.label.proposal.conditions_attributes.message_attributes.body

いつものように、initializer で FormBuilder の動作を修正するため initializers/action_view.rb を下記の内容で作成しました。

module ActionView::Helpers
  class InstanceTag
    # accepts_nested_attributes_for + fields_for の中で
    # ラベルの日本語化が正常に動作しない問題に対応
    def to_label_tag(text = nil, options = {}, &block)
      options = options.stringify_keys
      tag_value = options.delete("value")
      name_and_id = options.dup

      if name_and_id["for"]
        name_and_id["id"] = name_and_id["for"]
      else
        name_and_id.delete("id")
      end

      add_default_name_and_id_for_value(tag_value, name_and_id)
      options.delete("index")
      options["for"] ||= name_and_id["id"]

      if block_given?
        label_tag(name_and_id["id"], options, &block)
      else
        content = if text.blank?
          method_and_value = tag_value.present? ? "#{method_name}.#{tag_value}" : method_name
          # この行のみ修正
          I18n.t("helpers.label.#{object_name}.#{method_and_value}".gsub(/\[\d+\]/, '').gsub(/\[([^\[\]]+)\]/, '.\1'), :default => "").presence
        else
          text.to_s
        end

        content ||= if object && object.class.respond_to?(:human_attribute_name)
          object.class.human_attribute_name(method_name)
        end

        content ||= method_name.humanize

        label_tag(name_and_id["id"], content, options)
      end
    end
  end
end

これで、

jp:
  helpers:
    label:
      proposal:
        proposal_conditions_attributes:
          message_attributes:
            body

こんな感じに日本語化ファイルを作成しておけば無事日本語化がなされます。

本当は helpers ではなく activerecode の方のキーで実装したかったのですが、解析がうまくいかずに断念しました。orz