生涯未熟

生涯未熟

プログラミングをちょこちょこと。

RailsによるアジャイルWEBアプリケーション開発第3版勉強!#6

前回はカタログアプリケーションを完成させました。
今回はカートアプリケーションの作成に入りたいと思います。



・セッション

カートアプリケーションを作成する前に、カートというからには入れた商品を記憶せねばなりません。
方法としてはURLの末尾にセッション識別子を割り込ませるやり方とcookieを使った方法があります。
今回はcookieを使った方法を検討してみます。

まずはデータ保存用にマイグレーションを生成しましょう。

>rake db:sessions:create

そして、このマイグレーションを適用させます。

>rake db:migrate


そうすることで、データベースにsessionsというテーブルが追加されました。
次に、このアプリケーションのセッションがデータベースを使うように設定します。
設定ファイルはconfig/environment.rbです。

  # Use the database for sessions instead of the cookie-based default,
  # which shouldn't be used to store highly confidential information
  # (create the session table with "rake db:sessions:create")
  # config.action_controller.session_store = :active_record_store

という部分を探し、その一番下の行を#を消して有効にしてください。
そうすることでデータベースに入れるようにすることを有効にします。


さらに、environment.rb内のconfig.action_controller.session = {...}という部分でcookieの保存に関する名前上の問題点を解決してくれていますが、これをデータベースにも適用とするならばapp/controllers/application.rbを変更します。

  protect_from_forgery  #:secret => '7a2dd41cca0d42aeca1d2d12f0f805bc'

この1文の#を消せばセッションデータがデータベースに格納されるようになります。
尚、この設定はscript/serverを再起動しないと適用されませんので注意です。


・カート及びセッション

カートとセッションを絡め合わせるにはまずカートオブジェクトに対してセッションを割り当て、また同じカートオブジェクトが必要になった時にはそれを見つけ出すという必要があります。
それを実現するためstoreコントローラ内にfind_cartメソッドを追加します。

  private

   def find_cart
        unless session[:cart]   #セッションにカートが無い場合
          session[:cart] = Cart.new #新しいカートを追加
        end
        session[:cart] #既存のカートまたは新しいカートに戻る
   end

これをstore_controller.rbに付け加えてください。
今回カートはクラスとして考えているので.newでカートを生成しています。


・カートの作成

まずは、モデルにカートについてのモデルを作成します。
app/models/cart.rbファイルを作成しましょう。

class Cart
 attr_reader :items
 def initialize
  @items = []
 end

 def add_product(product)
  @items << product
 end
end

attr_readerはそのitemsを参照するメソッドを定義しています。
そして今回の見どころはカートに入れるボタンで商品のidを渡す受け渡す皿が出来たということです。

もしカートに入れるボタンを次のように実装するとします。

<%= button_to "カートに入れる", :action => 'add_to_cart', :id => product %>

app/views/store/index.html.erbに追記するのであればあとはactionの部分を作るのみです。

それではapp/controllers/store_controller.rb内にactionメソッドを付け足しましょう。

   def add_to_cart
    product = Product.find(params[:id])
    @cart  =find_cart
    @cart.add_product(product)
   end

まずparamsオブジェクトを用い、idパラメータを取得してきて、Productモデルからfindでそのidを持つ商品を探索、結果をローカル変数のproductに代入。

そして、前に実装したfind_cartを使ってカート内を探索または生成をしてインスタンス変数cartに代入。

@cartを使い、該当カートに商品を追加するという流れです。


paramsオブジェクトにはブラウザ上で渡されたパラメータが全て詰まっており、指定することで色々とパラメータを取り出すことが出来ます。

一つ注意として、privateと書かれている上にadd_to_cartメソッドを実装してください。
何故ならadd_to_cartはクラス外から呼ばれるためprivateだと呼ばれなくなるためです。


それでは、ブラウザでカートに入れるボタンを押してみましょう!



わ、わぁ〜お。
これは、テンプレートが無いと怒られているのですがadd_to_cartは処理を終えた後の表示としてadd_to_cartに対応するテンプレートを探します
しかし、そんなものはまだ作成していませんので怒られたワケです。

では、解決するためにテンプレートを作っちゃいましょう。

<h2>Pragmaticカート</h2>
<ul>
 <% for item in @cart.items %>
  <li><%=h item.title %></li>
 <% end %>
</ul>

というapp/views/store/add_to_cart.html.erbを作成することで以下の画面に変化するはずです。


Pragmatic Project Automationがたくさんあるのは更新する度に同じ商品を追加していっているためです。(ついつい面白がって何回もやってしまったの図です)





今回はここまで。
次回はこの重複の問題を解決し、さらにカートを改良していきます。