Rails勉強会@東京第34回メモ

はじめて Rails勉強会に参加させていただきました!

以下自分用メモです

Scaffoldの半歩先へ

db:migrateは管理画面用途等既存のDBにアクセスするのであれば使えない?

  • モデルは最初にrailsが起動したときにSHOW TABLESで定義を認識する
  • プライマリキがidというのが前提等いろいろ制約がある

デザイナとやりとりするには erbは不向き?

  • バリバリのデザイン
    • その他のテンプレートを選ぶべし
    • お勧めは?

特にこのセッションと関係ないけど 
app/view/todos/index.html.erbで
凄く気になったので
なぜ link_to 'Show', model

/controllers/[model.id]
になるのか?
actionpack-2.1.2/lib/action_view/helpers/url_helper.rb
から読み進めていって

      def link_to(name, options = {}, html_options = nil)
        url = case options
          when String
            options
          when :back
            @controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
          else
            self.url_for(options)
          end

optinsがモデル(Object)なのでself.url_for(options)

      def url_for(options = {})
        options ||= {}
        case options
        when Hash
          options = { :only_path => options[:host].nil? }.update(options.symbolize_keys)
          escape  = options.key?(:escape) ? options.delete(:escape) : true
          url     = @controller.send(:url_for, options)
        when String
          escape = true
          url    = options
        else
          escape = false
          url    = polymorphic_path(options)
        end

またまたoptinsがモデル(Object)なのでpolymorphic_path
以下インラインでいろいろ追ってみる
actionpack-2.1.2/lib/action_controller/polymorphic_routes.rb

    def polymorphic_path(record_or_hash_or_array, options = {})
      options[:routing_type] = :path
      polymorphic_url(record_or_hash_or_array, options)
    end

    def polymorphic_url(record_or_hash_or_array, options = {})
      if record_or_hash_or_array.kind_of?(Array)
        record_or_hash_or_array = record_or_hash_or_array.dup
      end

      #record   = record_or_hash_or_array
      record    = extract_record(record_or_hash_or_array)
      #format   = nil
      format    = extract_format(record_or_hash_or_array, options)
      #namespace= ""
      namespace = extract_namespace(record_or_hash_or_array)
      #args = [model]の状態?
      args = case record_or_hash_or_array
        when Hash;  [ record_or_hash_or_array ]
        when Array; record_or_hash_or_array.dup
        else        [ record_or_hash_or_array ]
      end

      #new_record?ではないからinflectin = :singular ?
      inflection =
        case
        when options[:action].to_s == "new"
          args.pop
          :singular
        when record.respond_to?(:new_record?) && record.new_record?
          args.pop
          :plural
        else
          :singular
        end

      args.delete_if {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
      args << format if format
      
      named_route = build_named_route_call(record_or_hash_or_array, namespace, inflection, options)
      #todo_path(*args)が呼ばれる
      send!(named_route, *args)
    end

    def extract_record(record_or_hash_or_array)
      case record_or_hash_or_array
        when Array; record_or_hash_or_array.last
        when Hash;  record_or_hash_or_array[:id]
        else        record_or_hash_or_array
      end
    end

    def extract_format(record_or_hash_or_array, options)
      if options[:action].to_s == "formatted" && record_or_hash_or_array.is_a?(Array)
        record_or_hash_or_array.pop
      elsif options[:format]
        options[:format]
      else
        nil
      end
    end

    def extract_namespace(record_or_hash_or_array)
      return "" unless record_or_hash_or_array.is_a?(Array)

      namespace_keys = []
      while (key = record_or_hash_or_array.first) && key.is_a?(String) || key.is_a?(Symbol)
        namespace_keys << record_or_hash_or_array.shift
      end

      namespace_keys.map {|k| "#{k}_"}.join
    end

    def build_named_route_call(records, namespace, inflection, options = {})
      unless records.is_a?(Array)
        record = extract_record(records)
        route  = ''
      else
        record = records.pop
        route = records.inject("") do |string, parent|
          if parent.is_a?(Symbol) || parent.is_a?(String)
            string << "#{parent}_"
          else
            string << "#{RecordIdentifier.send!("singular_class_name", parent)}_"
          end
        end
      end

      if record.is_a?(Symbol) || record.is_a?(String)
        route << "#{record}_"
      else
        route << "#{RecordIdentifier.send!("#{inflection}_class_name", record)}_"
      end
      #debugしてみたら 
      #action_prefix(options) == ""
      #namespace == ""
      #route == "todo_"
      #routing_type(options) == "path"
      #つまり"todo_path"
      action_prefix(options) + namespace + route + routing_type(options).to_s
    end

actionpack-2.1.2/lib/action_controller/record_identifier.rb
#singular_class_nameは結局モデル名がかえってくる

    def singular_class_name(record_or_class)
      model_name_from_record_or_class(record_or_class).singular
    end

    private
      def model_name_from_record_or_class(record_or_class)
        (record_or_class.is_a?(Class) ? record_or_class : record_or_class.class).model_name
      end

結局 todo_pathが呼ばれるところまででわからなくなってしまった。。。。

Rails API

ActiveSupport
  • DateTimeは1.9で100倍早くなった
  • acts_like?
  • Float::Rounding
    • roud_with_precision
    • 1.9でpresitionあるけどあんまり役に立ってないのでとりあえず削除 復活予定
  • CleanWithin
    • トラバーサル対策?
string.gsub(%r{[\w. ]+(/[\w. ]+)+(\.rb)?(\b|$)}) do |path|
  new(path).cleanpath
end
  • String
    • "hoge".hoge?がtrueになる拡張
    • Rails.env.development?等に使われてる
  • append_featuresっていうのがよく出てくるけど バージョンを考慮する意味っぽい
  • http://www.ruby-lang.org/ja/man/html/Module.html
  • ActiveSupport::Testing
  • Builder::CSSなんてのがある
    • index.css.builder なんてことができるっぽい
  • Dir#user_home
  • DispatchServlet
    • WEBRick用のdispatchメソッド
  • HTML::Selector
    • Hpricotが使えないとき等に
  • Object拡張
    • with_options これで囲ってやると子供のメソッド呼び出しすべてに指定したoptionを追加してくれる
  • WinでRubyはI/Oがめちゃめちゃ遅い(10倍くらい遅い)
ActionView::Helper
  • CapcharHelper
    • erbを事前評価してあとで使う
  • TextHelper
    • word_wrap
      • 自動折り返し
<pre>
<%= word_wrap("一二三四五六七八九十" * 10,10) -%>
</pre>

こんな感じで一...十 毎に折り返されると思いきや。。まったく変化なし
後で調べる

pluginのセッション
  • 日本語じゃない情報収集に関して
  • 継続してプラグイン中心セッションへ
  • 日本語じゃない情報収集に関して
  • 困っていることを皆さんがひとつづつ言ってdiscusstion形式