Hatena::Grouprubyist

うんたらかんたらRuby RSSフィード

2010-03-09Logger!!!

Logger!!!

| Logger!!! - うんたらかんたらRuby を含むブックマーク はてなブックマーク - Logger!!! - うんたらかんたらRuby

Railscasts - The Logger

より


ログのカラーリングをオフ

ansi escape sequenceを非表示にしたい場合

(本番環境では不要という場合など)

#environment.rb
  config.active_record.colorize_logging = false

script/console

script/console時にログを標準出力にする方法。

.irbrc

if ENV.include?('RAILS_ENV') && !Object.const_defined?('RAILS_DEFAULT_LOGGER')
  require 'logger'
  RAILS_DEFAULT_LOGGER = Logger.new(STDOUT)
end

最近script/consoleをよく使用するようになって

SQLのログが掃かれるようにしたいなぁと、思っていたところ。

ありがたい。


ログを空(0bytes)にする

rake log:clear


ログのフォーマットの変更方法

やってみるも、、、
# environment.rb
class Logger
  def format_message(level, time, progname, msg)
    "#{time.to_s(:db)} #{level} -- #{msg}\n"
  end
end

おお、やっぱ簡単にできるんだなと早速やってみたが、、、

変化無し。

どうやらRails1.x時代のやり方らしい。

Processing MemosController#index (for 127.0.0.1 at 2010-03-08 01:06:09) [GET]
  Memo Load (1.1ms)   SELECT * FROM "memos" LIMIT 10 OFFSET 0
Rendering template within layouts/application
Rendering memos/index
Rendered memos/_sidebar (0.7ms)
Completed in 126ms (View: 119, DB: 1) | 200 OK [http://localhost/memos]

いろいろ調べて

フォーマットの変更は思うようにできたけど纏めんの面倒なので

続きは明日。

トラックバック - http://rubyist.g.hatena.ne.jp/rochefort/20100309

2010-03-08script/console

script/console

| script/console - うんたらかんたらRuby を含むブックマーク はてなブックマーク - script/console - うんたらかんたらRuby

Railscasts - Console Tricks

より


期待せずに見たが、知らんことだらけだった。


--sandbox

rollbackしてくれると。

$ ruby script/console --help
Usage: console [environment] [options]
    -s, --sandbox                    Rollback database modifications on exit.
        --irb=[irb]                  Invoke a different irb.
        --debugger                   Enable ruby-debugging for the console.


y

なんぞ。yamlに変換してくれるんか。

>> m = Memo.all
=> [#<Memo id: 1, title: "a", body: "", created_at: "2010-02-28 06:56:26", updated_at: "2010-02-28 06:56:26">, #<Memo id: 2, title: "aaa", body: "bbb", created_at: "2010-02-28 06:56:39", updated_at: "2010-02-28 06:56:39">]
?> y m
--- 
- !ruby/object:Memo 
  attributes: 
    created_at: 2010-02-28 06:56:26
    title: a
    body: ""
    updated_at: 2010-02-28 06:56:26
    id: "1"
  attributes_cache: {}

- !ruby/object:Memo 
  attributes: 
    created_at: 2010-02-28 06:56:39
    title: aaa
    body: bbb
    updated_at: 2010-02-28 06:56:39
    id: "2"
  attributes_cache: {}

=> nil

ri y

--------------------------------------------------------------- Kernel#y
     y( object, *objects )
------------------------------------------------------------------------
     Prints any supplied _objects_ out in YAML. Intended as a variation
     on +Kernel::p+.

       S = Struct.new(:name, :state)
       s = S['dave', 'TX']
       y s

     _produces:_

       --- !ruby/struct:S
       name: dave
       state: TX

methods検索

controllerの〜pathってなんだっけって時はgrepも使える。

?> app.class
=> ActionController::Integration::Session

?>app.methods.grep(/_path$/).sort
=> ["edit_memo_path", "edit_polymorphic_path", "formatted_edit_memo_path", "formatted_memo_path", "formatted_memos_path", "formatted_new_memo_path", "formatted_polymorphic_path", "hash_for_edit_memo_path", "hash_for_memo_path", "hash_for_memos_path", "hash_for_new_memo_path", "memo_path", "memos_path", "new_memo_path", "new_polymorphic_path", "polymorphic_path"]

_

前回の実行結果が出力可能

>> y _
--- 
- edit_memo_path
- edit_polymorphic_path
- formatted_edit_memo_path
- formatted_memo_path
- formatted_memos_path
- formatted_new_memo_path
- formatted_polymorphic_path
- hash_for_edit_memo_path
- hash_for_memo_path
- hash_for_memos_path
- hash_for_new_memo_path
- memo_path
- memos_path
- new_memo_path
- new_polymorphic_path
- polymorphic_path
=> nil
トラックバック - http://rubyist.g.hatena.ne.jp/rochefort/20100308

2010-03-07rescue_action_in_publicを使用したエラーハンドリング

rescue_action_in_publicを使用したエラーハンドリング

| rescue_action_in_publicを使用したエラーハンドリング - うんたらかんたらRuby を含むブックマーク はてなブックマーク - rescue_action_in_publicを使用したエラーハンドリング - うんたらかんたらRuby

Railscasts - Handling Exceptions


rescue_action_in_publicが紹介されていた。

以前、存在しないpathを指定した際に404を出力させる方法 - うんたらかんたらRuby - Rubyist

で書いた方式とは別に、既存のrescue_action_in_publicをoverrideさせることで実現している。


やり方

# controller
  protected
  def local_request?
    false
  end

  def rescue_action_in_public(exception)
    case exception
    when ActiveRecord::RecordNotFound
      render :file => "#{RAILS_ROOT}/public/404.html", :status => 404
    else
      super
    end
  end

よくわからんのでactionpackのソースを見てみた

local_request?って何よ(まぁメソッド名で想像つくけど)。

/opt/local/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/rescue.rb

rescue_action_in_public
      # Overwrite to implement public exception handling (for requests
      # answering false to <tt>local_request?</tt>).  By default will call
      # render_optional_error_file.  Override this method to provide more
      # user friendly error messages.
      def rescue_action_in_public(exception) #:doc:
        render_optional_error_file response_code_for_rescue(exception)
      end

コメントにも、overrideする際は、local_request?をfalseにしろと。


render_optional_error_file

一応デフォで呼ばれるrender_optional_error_file

      # Attempts to render a static error page based on the
      # <tt>status_code</tt> thrown, or just return headers if no such file
      # exists. At first, it will try to render a localized static page.
      # For example, if a 500 error is being handled Rails and locale is :da,
      # it will first attempt to render the file at <tt>public/500.da.html</tt>
      # then attempt to render <tt>public/500.html</tt>. If none of them exist,
      # the body of the response will be left empty.
      def render_optional_error_file(status_code)
        status = interpret_status(status_code)
        locale_path = "#{Rails.public_path}/#{status[0,3]}.#{I18n.locale}.html" if I18n.locale
        path = "#{Rails.public_path}/#{status[0,3]}.html"

        if locale_path && File.exist?(locale_path)
          render :file => locale_path, :status => status, :content_type => Mime::HTML
        elsif File.exist?(path)
          render :file => path, :status => status, :content_type => Mime::HTML
        else
          head status
        end
      end

噂のlocal_request?
      # True if the request came from localhost, 127.0.0.1. Override this
      # method if you wish to redefine the meaning of a local request to
      # include remote IP addresses or other criteria.
      def local_request? #:doc:
        request.remote_addr == LOCALHOST && request.remote_ip == LOCALHOST
      end

rescue_action_without_handler

local_request?の呼出し元。

      def rescue_action_without_handler(exception)
        log_error(exception) if logger
        erase_results if performed?

        # Let the exception alter the response if it wants.
        # For example, MethodNotAllowed sets the Allow header.
        if exception.respond_to?(:handle_response!)
          exception.handle_response!(response)
        end

        if consider_all_requests_local || local_request?
          rescue_action_locally(exception)
        else
          rescue_action_in_public(exception)
        end
      end

ここでlocal用とそれ以外でエラーのレンダリングを分けている。(動画にも出てくるが一応試してみた。後述。)

どうやら、consider_all_requests_localってのは、

config/environments/development.rb などの各環境で定義している↓らしい。

config.action_controller.consider_all_requests_local = true

つまり、これとlocalhost(127.0.0.1)両方見て判断している。



rescue_action_locally
      # Render detailed diagnostics for unhandled exceptions rescued from
      # a controller action.
      def rescue_action_locally(exception)
        @template.instance_variable_set("@exception", exception)
        @template.instance_variable_set("@rescues_path", RESCUES_TEMPLATE_PATH)
        @template.instance_variable_set("@contents",
          @template.render(:file => template_path_for_local_rescue(exception)))

        response.content_type = Mime::HTML
        render_for_file(rescues_path("layout"),
          response_code_for_rescue(exception))
      end

rescue_action

一応更なる呼出し元。

rescue_action > rescue_action_without_handler > rescue_action_without_handler

      # Exception handler called when the performance of an action raises
      # an exception.
      def rescue_action(exception)
        rescue_with_handler(exception) ||
          rescue_action_without_handler(exception)
      end



個人的には

rescue_action_in_publicは、overrideされることが前提という印象を持った。

local_request?のoverrideも実害無いし、そもそもどのエラーを表示するかっていうのは

environments以下で定義できるので、この方式でいいような気がする。


例外処理なんて当然どこでもやってるんだろうから、ossのコードでもあとで見てみるか。

実践レベルのベストプラクティス欲しいなぁ。既にあるのかな。

あと、気軽にoverrideできるけど、やってokかどうかの判断っつーの難しいなぁ。



おまけ

rescue_action_locallyとrescue_action_in_publicをそれぞれ実行してみた。

local

config.action_controller.consider_all_requests_local = true で実行。

f:id:rochefort:20100307153404j:image


public

config.action_controller.consider_all_requests_local = false かつ

local_request?をoverrideして実行。

f:id:rochefort:20100307153405p:image

2010-03-06named routesメモ

named routesメモ

| named routesメモ - うんたらかんたらRuby を含むブックマーク はてなブックマーク - named routesメモ - うんたらかんたらRuby

Railscasts - Named Routes

Railscasts - Custom REST Actions

より


なんとなくrails使ってると(scaffoldすると自動でmap.resourcesされるから)〜path/〜urlって時々出てくるけど

そこらへんは、routes.rbで設定してたと。


メモ

map.home "", :controller => 'hoge', :action => 'index'
→home_url  #/
  home_path #http://localhost:3000
map.fuga_archive 'tasks/:year/:month', :controller => 'fuga', :action => 'archive'
→fuga_archive_path
  fuga_archive_url
map.resources :projects
→project_path(project)
  edit_project_path(project)
  project_path(project), :method => :delete  
  new_project_path

map.resourcesの書き方。collection/memberを指定。

map.resources :tasks, :collection => { :completed => :get }, :member => { :complete => :put }
→complete_task_path(task)
  completed_tasks_path
トラックバック - http://rubyist.g.hatena.ne.jp/rochefort/20100306

2010-03-04previewボタンを付ける方法

previewボタンを付ける方法

| previewボタンを付ける方法 - うんたらかんたらRuby を含むブックマーク はてなブックマーク - previewボタンを付ける方法 - うんたらかんたらRuby

Railscasts - Multibutton Form

より。

previewは結構使うんじゃないかな。


やってみた

view

通常のsubmitに加えprevie_buttonというnameで追加。

表示部は、params[:preview_button]がある場合のみ表示ロジックを記載。

<% if params[:preview_button] %>
  <%= textilize @project.description %>
<% end %>
...
<%= submit_tag 'Create' %>
<%= submit_tag 'Preview', :name => 'preview_button' %>

controller

params[:preview_button]がある場合はnewへrender。

def create
  @project = Project.new(params[:project])
  if params[:preview_button] || !@project.save
    render :action => 'new'
  else
    flash[:notice] = "Successfully created project."
    redirect_to project_path(@project)
  end
end

更新(edit/update)も同様の方法で実装可能。

動画ではform_remote_for / submit_to_remote も紹介。

トラックバック - http://rubyist.g.hatena.ne.jp/rochefort/20100304