Monday, October 12, 2009

Rails Application - Reading Tracks (2)

users_controller.rb - Tracks reading.

user_controller.rb

Track applicationでユーザー(admin)を登録した時のコンソール出力から何が起きているか確認してみる。
まず,user_controller.rb のアクション new の内容を確認する。

  # GET /users/new
  def new
    if User.no_users_yet?
      @page_title = "TRACKS::Sign up as the admin user"
      @heading = "Welcome to TRACKS. To get started, please create an admin account:"
      @user = get_new_user
    elsif @user && @user.is_admin?
      @page_title = "TRACKS::Sign up a new user"
      @heading = "Sign up a new user:"
      @user = get_new_user
    else # all other situations (i.e. a non-admin is logged in, or no one is logged in, but we have some users)
      @page_title = "TRACKS::No signups"
      @admin_email = User.find_admin.preference.admin_email
      render :action => "nosignup", :layout => "login"
      return
    end
    render :layout => "login"
  end
userがまだ未定義なので,Title と headline,Userモデルのインスタンスを確保している。そして,最後にある render :layout => "login" が view の提供のキーとなるだろう。ActionController::Baseのrenderメソッドを確認すると,"login"というカスタムレイアウトを用いれ,response bodyを作成していることがわかる。ここで,app/views/layout/login.html.erb の中身を見てみる。
@page_title というのが出てきた。先ほど指定した @page_title が埋めこまれている。おそらく <%= render :partial => "shared/footer" %> は共通のfooterを埋めこんでいるのだろう。
さて,<%= yield %> は何ものか?これはActionController::Layoutのクラスメソッドの説明を読んで考えてみると,どうやらtitleとかfooterは共通にしたいけど,login 画面は個別のviewを埋めこみたいと考えているのだろうか。ここで,"/users/new" リクエストでアクセスしてきたことを思いだす。app/views/users/new.html.erb が定義されてあった。 ここでユーザーAccount Signupのviewを生成しているのだなと確認できる。
さて,submitボタンを押したときに,コンソール画面には以下の内容が表示されている。

192.168.1.102 - - [08/Oct/2009:22:52:51 JST] "POST /users HTTP/1.1" 302 92
http://192.168.1.101:3000/users/new -> /users
再び users_controller.rb に戻ろう。"POST /users" リクエストなので,create メソッドが実行される。create メソッドの内容は以下の通り。

  # Example usage: curl -H 'Accept: application/xml' -H 'Content-Type: application/xml'
  #               -u admin:up2n0g00d
  #               -d 'usernameabc123'
  #               http://our.tracks.host/users
  #
  # POST /users
  # POST /users.xml
  def create
    if params['exception']
      render_failure "Expected post format is valid xml like so: usernameabc123."
      return
    end
    respond_to do |format|
      format.html do
        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end
        
        user = User.new(params['user'])
        unless user.valid?
          session['new_user'] = user
          redirect_to :action => 'new'
          return
        end

        first_user_signing_up = User.no_users_yet?
        user.is_admin = true if first_user_signing_up
        if user.save
          @user = User.authenticate(user.login, params['user']['password'])
          @user.create_preference
          @user.save
          session['user_id'] = @user.id if first_user_signing_up
          notify :notice, "Signup successful for user #{@user.login}."
          redirect_back_or_home
        end
        return
      end
      format.xml do
        unless User.find_by_id_and_is_admin(session['user_id'], true)
          render :text => "401 Unauthorized: Only admin users are allowed access to this function.", :status => 401
          return
        end
        unless check_create_user_params
          render_failure "Expected post format is valid xml like so: usernameabc123."
          return
        end
        user = User.new(params[:request])
        user.password_confirmation = params[:request][:password]
        if user.save
          render :text => "User created.", :status => 200
        else
          render_failure user.errors.to_xml
        end
        return
      end
    end
  end  

Signup » を押すと,POSTリクエストが生成され,Rails アプリケーションには

<request><login>username</login><password>abc123</password></request>
とvalidなXML形式がcontrollerに送られている模様。誰がXML形式に成形しているのだろうか?

No comments: