Ruby學習筆記6: 動態web app的創建(3)--多Model之間的交互

We first built a static site which displayed a static image using only a Controller and a View. This is our Etsy landing page page.javascript

Then we built the Categories page, with a Model (manages data), Controller (manages decisions) and View (manages display). The Categories pages allows us to display dynamic content so users can browse through different Categories that can be updated regularly.css

Now we will build the Products page, which will allow users to browse through Products in our Etsy app. To create this, we'll be creating a new Model, Controller, and View.html

Now, because have more than one Model, we will also learn how Models interact with each other through associations.java

前面咱們完成的ruby on rails app 的靜態、動態網頁開發,實現了數據庫增刪改查的操做,熟悉了MVC結構的工做機理。本文在前面的基礎上,要新增一個Prodect的Model,從而體現多model交互的功能。

數據庫

====================================canvas

Product Page 的效果以下:

瀏覽器


Let's review our Request-Response Cycle one more time.ruby

Again, in our Products page, we're using a database just like we did for Categories.服務器

  • Our browser will first make a request to the server. The server handles the requests by talking to our Rails application.
  • Second, the route takes the request and finds the right Controller and method to handle the request.
  • Third, the Controller gathers data directly from our Model. It assembles the data in methods and then passes it on the View.
  • Finally, the View packages the information and sends it back to our browser.
      

Request-Response Cycle的工做機理:

1. 瀏覽器發送請求到服務器,服務器處理請求,怎麼處理:跟Rails App 說:有個請求來了!
2. the routes 拿到請求,找到正確的Controller和Method,來處理這個請求。
3. Controller 開始收集數據,從Model裏收集,在Methods裏組裝數據,完了就傳遞給View
4. 最後,View把全部的信息打包好,包括數據,樣式,文本,圖片各類。。。傳回給瀏覽器。

========================================
markdown

下面開始咱們Making Product Page

This page will list all products that users buy - like shoes or craft paper. Users will be able to browse through products and find what they like.
When we created a Model for Categories, we were able to add information about our categories. For Products, we will also create a Model so we can add information about our products, such as a product name or price.

1. Generate the product model

we generate a model like this:(in terminal)

rails generate model product

Remember that Model names are always singular.
When we generate a Product Model, we create corresponding Model and Migration files. Let's first focus on the product model.

2. build the association between two models

Since we have more than one Model, a Category Model and a Product Model, we can build the association between the two.
Why do we need associations? As you create the Etsy app, you want to make sure that certain Products are associated with a Category. What if we want to put our painting in the Art category, or a toy in the Kids category?
Associations do just this. They tell us how parts of our app relate to other parts.Association(關聯)就是解決咱們app的一些parts和另外一些parts 是怎麼個關係。
How do we create associations? The most basic type is a has_many and belongs_to relationship, where 'one thing' has many 'other things'. Imagine a Person and their Pets. The Person has_many Pets, and Pets belongs_to the Person.怎麼來建立一個關聯呢?
最基本的類型就是 has_many 和 belongs_to 關係。has_many 就是 ‘一個東西’ 有不少 ‘其餘東西們’ ,設想,一我的和他的寵物們。就是這我的has_many 寵物們,而且,寵物們 belongs_to 這我的。

In the Person Model we type:

class Person has_many :pets
end

In the Pet Model, we type:

class Pets belongs_to :person
end


In our case, our Category has many products, and Product belongs to category:

class Category has_many :products
end

In the Pet Model, we type:

class Products belongs_to :category
end
** app/models/category.rb:
class Category < ActiveRecord::Base
	has_many :products
end
同時,
** app/models/product.rb:
class Product < ActiveRecord::Base
	belongs_to :category
end

3. prepare our Products Migration table

Now that our Product Model is set up, we need to prepare our Products Migration table so that it has the right columns.

If you recall from the Categories Migration, we do this in two steps:

a. Add columns to our Products Migration table

b. Type bundle exec rake db:migrate in the terminal

In this case, there's one more column that we will add. Now that we have an association, we need to tell our Models that our Product Model belongs to our Category Model by adding areferences column.

we had a Product that belonged to a Category, we would add t.referencesto our Pet table to look like this:


in our Products Migration table, we will :references to Category. We always add references to the table thatbelongs_to something else.[從model裏添加references to 主model.] 這裏咱們就是產品model的文件裏,Reference to Category, buz product model belongs to category model.

1. 文件**db/migrate/20140626211017_create_products.rb:

class CreateProducts < ActiveRecord::Migration
  def change
    create_table :products do |t|
        t.string :product_name  #string
        t.text :description     #text
        t.float :price          #float
        t.string :thumburl      #string
        t.references :category  #references
        t.timestamps            #timestamps is required.
    end
  end
end

2. In terminal, run bundle exec rake db:migrate to migrate your database. Press Enter.


$ bundle exec rake db:migrate
== 20140626211017 CreateProducts: migrating ===================================
-- create_table(:products)
   -> 0.0013s
== 20140626211017 CreateProducts: migrated (0.0013s) ==========================

$ 

4. Add seed data for our Products

Now that we have columns, let's add seed data for our Products. If you recall there are also two steps for this:

a. We add seed data in our seeds.rb file

b. We run rake db:seed in the terminal (bundle exec rake db:seed)

We already added most of the Products seed data for you. This time with one small change. Since each product belongs to a specific category, we'll also be adding a category_id at the end for art.

Let's look at some seed data:

Product.create(product_name: 'Spanish Canvas Painting', description: 'La Fuente de Monteforte Painting Acrylic', price: 79.00, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/e/eb/144-la_fuente_de_Monforte_V.jpg', category_id: art.id)

As we can see, each of our Product columns has an entry. We also have category_id: art.id, referencing that this product belongs to the art category.

** db/seeds.rb:
# This file should contain all the record creation needed to seed the database with its default values.
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
#
# Examples:
#
#   cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
#   Mayor.create(name: 'Emanuel', city: cities.first)

	art = Category.create(name: 'Art', thumburl: 'http://upload.wikimedia.org/wikipedia/commons/e/eb/144-la_fuente_de_Monforte_V.jpg')
	home_and_living = Category.create(name: 'Home & Living', thumburl: 'http://ihomedecorsideas.com/wp-content/uploads/2014/04/diy_network_homemade_coat_rack_.jpg')
	jewelry = Category.create(name: 'Jewelry', thumburl: 'http://upload.wikimedia.org/wikipedia/commons/f/ff/Midyat_Silver_Jewelry_1310103_Nevit.jpg')
	women = Category.create(name: 'Women', thumburl: 'https://c1.staticflickr.com/9/8255/8660920433_57a184d9d1_z.jpg')
	men = Category.create(name: 'Men', thumburl: 'http://upload.wikimedia.org/wikipedia/commons/d/d5/Fullbrogue_(Grenson).jpg')
	kids = Category.create(name: 'Kids', thumburl: 'http://upload.wikimedia.org/wikipedia/commons/e/e0/Artist%27s_Paint_Brushes_Adapted_With_Photoshop._Surrey_UK.jpg')
	vintage = Category.create(name: 'Vintage', thumburl: 'https://c2.staticflickr.com/8/7402/9426557291_139134efaa_z.jpg')
	weddings = Category.create(name: 'Weddings', thumburl: 'http://hostingessence.com/wp-content/uploads/2012/04/green-wedding.jpg')
   craft_supplies = Category.create(name: 'Craft Supplies', thumburl: 'http://bit.ly/1w1uPow')

   #Art
   Product.create(product_name: 'Russian Acrylic', description: 'Acrylic on Canvas', price: 59.00, thumburl: 'http://bit.ly/1nDkJZw', category_id: art.id)

   Product.create(product_name: 'Spanish Canvas Painting', description: "La Fuente de Monteforte Painting Acrylic", price: 79.00, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/e/eb/144-la_fuente_de_Monforte_V.jpg',
      category_id: art.id)
   Product.create(product_name: 'French Acrylics & Pastel Canvas', description: "Jeanne d'Arc Arrivant a l'ile Bouchard", price: 122.00, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/3/36/2004_Yuri-Yudaev_Before-the-City-Gate_Acrylic-on-canvas_40x40cm.jpg', category_id: art.id)

   # Home & Living

  Product.create(product_name: 'Art Deco Glass', description: "Before-the-City-Gate Acrylic-on-canvas", price: 1599.00, thumburl: 'http://ihomedecorsideas.com/wp-content/uploads/2014/04/diy_network_homemade_coat_rack_.jpg', category_id: home_and_living.id)
   Product.create(product_name: 'Rustic Homemade Coatrack', description: "Coatrack made of Maple Tree Branches", price: 288.00, thumburl: 'https://c2.staticflickr.com/6/5308/5821079295_4580e3c8d3_z.jpg', category_id: home_and_living.id)
   Product.create(product_name: 'Forest Wood Coffee Table', description: "Chista Natural Wood Rustic Collection", price: 299.00, thumburl: 'https://c1.staticflickr.com/3/2777/4033647409_3c04157d86.jpg', category_id: home_and_living.id)

   # Jewelry

   Product.create(product_name: 'Vintage Rhinestone Earrings', description: "Lightweight Rhinestone Earrings in Sterling Silver Setting", price: 9.00, thumburl: 'http://fc03.deviantart.net/fs70/f/2011/340/0/5/dangle_ear_rings_stock_png_by_doloresdevelde-d4idyev.png', category_id: jewelry.id)
   Product.create(product_name: 'Moon Turquoise Ring', description: "Mediyat Silver" , price: 39.99, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/f/ff/Midyat_Silver_Jewelry_1310103_Nevit.jpg', category_id: jewelry.id)
   Product.create(product_name: 'Greek Gold Necklace', description: "Greek Gold Plated Necklace", price: 4570.00, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/0/02/Ancient_greek_jewelry_Staatliche_Antikensammlungen_Room_10_06.jpg', category_id: jewelry.id)


   # Women

   Product.create(product_name: 'Chloe Frill Yellow Dress' , description: "Vintage yellow dress with floral design. Lightweight with frill on skirt.", price: 59.99, thumburl: 'https://c1.staticflickr.com/9/8255/8660920433_57a184d9d1_z.jpg', category_id: women.id, )
   Product.create(product_name: 'Autumn Knitted Sweater with Silver Buttons', description: "Knitted Crop Sweater with Silver Buttons", price: 45.99, thumburl: 'https://c2.staticflickr.com/4/3049/2353463988_c9d8cde436_z.jpg?zz=1', category_id: women.id)
   Product.create(product_name: 'Rucksack', description: "Rucksack Schweizer Armee 1960.", price: 39.99, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/a/a1/Image-2D_and_3D_modulor_Origami.jpg', category_id: women.id)

   # Men

   Product.create(product_name: 'Grenson Shoes', description: "Fullbrogue Grenson Shoes.", price: 105.00, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/d/d5/Fullbrogue_(Grenson).jpg', category_id: men.id)
   Product.create(product_name: 'Color Fringed Scarf', description: "Men’s Fringed Scarf in Pumpkin Toffee Grey.", price: 19.99, thumburl: 'https://c2.staticflickr.com/4/3437/3832752067_c6c3631d44_z.jpg?zz=1', category_id: men.id)
   Product.create(product_name: 'Pork Pie Hat', description: "Classic Pork Pie Hat from the 1940s.", price: 110.00, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/0/05/Brown_Porkpie_Hat.JPG', category_id: men.id)


   # Kids

   Product.create(product_name: 'Peruvian Hats', description: "Handmade Peruvian Winter Hats for Children.", price: 15.00, thumburl: 'https://c2.staticflickr.com/8/7020/6498656815_3937483e21_z.jpg', category_id: kids.id)
   Product.create(product_name: 'Norev Toy Car', description: "Classic Norev Model Toy Car for Children", price: 17.00, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/6/61/Norev_4cv.jpg', category_id: kids.id)
   Product.create(product_name: 'Stickle Bricks', description: 'Toy Stickle Brick Building Blocks Set', price: 21.99, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/f/f1/Stickle_bricks.jpg', category_id: kids.id)


   # Vintage

   Product.create(product_name: 'Anders Brown Leather Bag', description: "Vintage Leather with White Trim.", price: 79.99, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/3/3d/Gesellenst%C3%BCck_Lederhandwerk.jpg', category_id: vintage.id)
   Product.create(product_name: 'Cambridge Red Footsies', description: "Red Vintage Leather Shoes Children with Brown Laces and White Trim", price: 45.99, thumburl: 'https://c1.staticflickr.com/3/2587/3797274851_8199f17d01.jpg', category_id: vintage.id)
   Product.create(product_name: 'Voightlander Camera', description: "Voightlander Vintage Camera with Metal Case", price: 179.00, thumburl: 'http://upload.wikimedia.org/wikipedia/commons/6/67/A_vintage_Voigtl%C3%A4nder_Vito_B_camera.jpg', category_id: vintage.id)

   # Weddings

   Product.create(product_name: 'Green Wedding Decor', description: "Forest Dream Wedding Decoration Ideas", price: 27.00, thumburl: 'http://hostingessence.com/wp-content/uploads/2012/04/green-wedding.jpg', category_id: weddings.id)
   Product.create(product_name: 'Embossed Soap Wedding Favors', description: "Lavendar Handmade Soap decorated with elegant nature design. ", price: 4.50, thumburl: 'https://c1.staticflickr.com/1/203/518233215_cb4d2af38f_z.jpg?zz=1', category_id: weddings.id)
   Product.create(product_name: 'Handmade Centerpieces', description: "Handmade Wedding Tea Cup Centerpieces for Your Guests", price: 35.00, thumburl: 'http://indiefixx.com/wp-content/uploads/2011/06/GR_teacupcenterpieces.jpg', category_id: weddings.id)

   # Craft Supplies

   Product.create(product_name: 'Korean Indasong Craft Paper', description: "Origami Paper Kit", price: 17.00, thumburl: 'http://commons.wikimedia.org/wiki/File:Vesta_sewing_machine_IMGP0718.jpg', category_id: craft_supplies.id)
   Product.create(product_name: 'Handmade Gift Wrap', description: "Esoterica Handmade Supplies", price: 14.00, thumburl: 'http://commons.wikimedia.org/wiki/File:Vesta_sewing_machine_IMGP0718.jpg', category_id: craft_supplies.id)
   Product.create(product_name: 'Lollipot Flavor Kit', description: "Flavor Kit for Celebration Lollipops and Gifts", price: 21.00, thumburl: 'http://commons.wikimedia.org/wiki/File:Vesta_sewing_machine_IMGP0718.jpg', category_id: craft_supplies.id)

In terminal type: bundle exec rake db:seed
$ bundle exec rake db:seed $ 
$ bundle exec rake db:seed
$ 
Now that we have a Model, we can create our Products Controller and Views. The Controller methods ensure that we serve dynamic content to the Products View. We can change the information users see.

5. Create our Controller

We saw this diagram when we created our Categories Controller. The good news is that our Products Controller will use the same pattern. We will use Create, Read, Update, and Delete to change information, commonly called CRUD.

Remember that five of these methods, index, show, new, edit, delete have Views as indicated here.

Take a look at the image below. It lists the Create, Read, Update, and Delete methods and what they do.
   

咱們有Model了,要創建Products 的Controller,跟Category同樣。
咱們要Products頁面是動態的,包含8個methods, This way, we can 改變咱們products的信息。
咱們就從5個有對應view的methods開始。在Terminal裏:

rails generate controller products index show new edit delete

Here we list the five main methods that have Views.

$ rails generate controller products index show new edit delete
create  app/controllers/products_controller.rb
 route  get 'products/delete'
 route  get 'products/edit'
 route  get 'products/new'
 route  get 'products/show'
 route  get 'products/index'
invoke  erb
create    app/views/products
create    app/views/products/index.html.erb
create    app/views/products/show.html.erb
create    app/views/products/new.html.erb
create    app/views/products/edit.html.erb
create    app/views/products/delete.html.erb
invoke  test_unit
create    test/controllers/products_controller.rb
invoke  helper
create    app/helpers/products_helper.rb
invoke    test_unit
create      test/helpers/products_helper_test.rb
invoke  assets
invoke    coffee
create      app/assets/javascripts/products.js.coffee
invoke    scss
create      app/assets/stylesheets/products.css.scss
$  
** app/controllers/products_controller.rb文件裏,接下來就要寫methods了。

6. Add the method keep our data secure

We'll need to give our Products a secure way of fetching information from our Model.

We'll create a strong parameters method that will keep our data secure. This private method prevents someone from altering the information we store in our Product Model.
**app/controllers/products_controller.rb文件裏,加入:

private
def product_params  #strong params method, based on the name of the Model: 'product'
 params.require(:product).permit(:product_name, :description, :price, :thumburl)#requires the Model name, and permits the columns
end
As you can see a strong params method (i.e. product_params) will be based on the name of the Model. Here, params requires the Model name (product) and permits the columns stored in our Migration table (product_name, description, price and thumburl).

7. Add the main controller methods: index, show, new, edit and delete

Now it's time to create our main controller methods again: index, show, new, editand delete. Lucky for us, Rails is built on a series of patterns. We'll be using many of the same patterns we used before!
三個文件:
1. Controller: app/controllers/products_controller.rb
2. Routes: config/routes.rb
3. Views:
      index:     app/views/products/index.html.erb
      show:     app/views/products/show.html.erb
      new:     app/views/products/new.html.erb
      edit:     app/views/products/edit.html.erb
      delete:     app/views/products/delete.html.erb
=========
>> 先準備好Routes:  config/routes.rb
----
Rails.application.routes.draw do
  get '/' => 'pages#home'

  resources :categories
  get 'categories/:id/delete' => 'categories#delete', :as => :categories_delete

#this takes care of our main controller routes for products
  resources :products
  get 'products/:id/delete' => 'products#delete', :as => :products_delete
end
----

>> 再一個個寫Controller和Views

    7.1 For index:

    Controller:
    ----

    define index
      @products = Product.all
    end
    ----

    View:
    ----
<h1>Listing products</h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Description</th>
      <th>Price</th>
      <th>Thumburl</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @products.each do |product|%>
    <!--# iterate through @products %>-->
      <tr>
        <td><%= product.product_name%></td>
        <td><%= product.description %></td>
        <td><%= product.price %></td>
        <% if product.thumburl %>
          <%= image_tag product.thumburl %>
        <% end %>
        <td><%= link_to 'Show', product %></td>
        <td><%= link_to 'Edit', edit_product_path(product) %></td>
        <td><%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>

<br>

<%= link_to 'New Product', new_product_path %>

We're getting closer! The index page you made has all the right information, but this time around we added some style to the page. It now includes the supporting HTML for your Views.

Let's try adding the index view for categories again, now with style. Here again we would iterate through all Products and print out the name and the thumburl.
**文件

app/views/products/index.html.erb :

<%= render 'shared/topnav' %>
<br>
<br>
<br>

<h1>Listing products</h1>

<% @products.in_groups_of(3).each do |products| %>
  <% products.select! {|x| !x.nil?} %>
  <div class='row'>
    <% products.each do |product| %>
      <div class='col-md-4'>
        <div class="thumbnail">
            <img src= <%= product.thumburl %> >
            <div class="caption">
              <span class="listing-title"><%= product.product_name %></span>
              <span class="listing-desc"><%= product.description %></span>
              <span class="listing-price"><%= number_to_currency(product.price) %></span>
              <span><%= link_to "Edit", edit_product_path(product.id) %></span>
              <span><%= link_to "Delete", products_delete_path(:id => product.id) %></span>
            </div>
          </div>
      </div>
    <% end %>
  </div>
<% end %>
<br>

<%= link_to 'New Product', new_product_path %>



<%= render 'shared/footer' %>


    7.2For show method

The show method finds an object by its id, and stores it in @product. Let's create the show method in our controller. Using our Pet example, it looks like this:

  def show #request: localhost:8000/products/1
      @product = Product.find(params[:id])
  end
We still need a view! We just want to show one product on a page. Let's go ahead and make the view for show.
To do this, we'll be printing out the attributes that we stored in our instance variable @product. We add . and the attributes name after each attribute we print out.

***app/views/products/show.html.erb:

<p>
  <strong>Product name:</strong>
  <%= @product.product_name%>
</p>

<p>
  <strong>Description:</strong>
  <%= @product.description %>
</p>

<p>
  <strong>Price:</strong>
  <%= @product.price %>
</p>

<p>
  <strong>Thumburl:</strong>
  <%= @product.thumburl%>
</p>

<%= link_to 'Edit', edit_product_path(@product) %> |
<%= link_to 'Back', products_path %>

 7.3 Prepare  _form.html.erb file

在準備接下來的new/edit method以前,咱們還須要準備好 _form.html.erb 文件:app/views/products/_form.html.erb

<%= form_for(@product) do |f| %>

  <div class="product_name">
		<%= f.label :productname %><br>  <!--爲何這裏不能有空格呢?-->
		<%= f.text_field :product_name %>
  </div>
  <div class="description">
		<%= f.label :description %><br>
		<%= f.text_field :description %>

  </div>
  <div class="price">
		<%= f.label :price %><br>
		<%= f.text_field :price %>

  </div>
  <div class="thumburl">
		<%= f.label :thumburl %><br>
		<%= f.url_field :thumburl %>

  </div>
  <div class="actions">
		<%= f.submit %>

  </div>
<% end %>

7.4 Create the new method

*** app/controllers/products_controller.rb :

  def new  #localhost:8000/products/new
		@product = Product.new
  end
  def create
  	@product = Product.new(product_params)
  	if @product.save
  		redirect_to(:action => 'index')
  	else
  		render('new')
  	end
  end

View: ***file:    app/views/products/new.html.erb

<%= render 'shared/topnav' %>

<h1>New Product</h1>

<!-- Render form here -->
<%= render 'form' %>

<%= link_to 'Back', products_path %>

<%= render 'shared/footer' %>

7.5 Create the edit method 

Controller: file ***  app/controllers/products_controller.rb 
  def edit  #localhost:8000/products/1/edit
		@product = Product.find(params[:id])
  end
  def update
  	@product = Product.find(params[:id])
  	if @product.update_attributes(product_params)
  		redirect_to(:action => 'show', :id => @product.id)
  	else
  		render('index')
  	end
  end

 View: app/views/products/edit.html.erb

<%= render 'shared/topnav' %>

<h1>Edit Product</h1>

<!-- Render form here -->
<%= render 'form' %>

<%= link_to 'Back', products_path %>

<%= render 'shared/footer' %>


7.6 Create the delete method 

Controller:
  def delete
  	@product = Product.find(params[:id])
  end
  
  def destroy
  	Product.find(params[:id]).destroy
  	redirect_to(:action => 'index')
  end

View: ** app/views/products/delete.html.erb
<p>
  <strong>Product name:</strong>
  <%= @product.product_name %>
</p>

<p>
  <strong>Description:</strong>
  <%= @product.description %>
</p>

<p>
  <strong>Price:</strong>
  <%= @product.price %>
</p>

<p>
  <strong>Thumburl:</strong>
  <%= @product.thumburl %>
</p>

<%= link_to 'Delete', products_delete_path(:id => @product.id) %> |
<%= link_to 'Edit', edit_product_path(@product) %> |
<%= link_to 'Back', products_path %>

8. Conbine two Models together

Before we finish, one final piece remains. We have a Products page and a Categories page, but right now they live entirely separate from one another.

Instead, we want our users to be able to go to a Category, click on show, and access the Products in that Category. If a user clicks on show in the Art Category, we should see the Art products that belong here.

We can do this by nesting嵌套 Products in our Categories show method. Since we have an association, we can list out all the products that belong to that category.
爲了讓咱們點擊art這個category的show時,能夠列出在art下的全部product,也就是要讓product 按 art 分類。此時咱們要把Products嵌套在Category下面,咱們已經有association了,因此能夠list out all the products that belong to that category.
*** app/controllers/categories_controller.rb

def show
  @category = Category.find(params[:id])
  @products = @category.products #new code we write, this works cuz we hava an association #store the products of a given category in an instance variable @product
end
Here @products = @category.products is the new code we write. This works because we have an association. Our code knows that certain products belong to a Category. We mentioned that Category in our seed data. 這裏好玄乎啊!咱們的代碼知道某個產品是屬於哪一個category的,在咱們的seed data裏,咱們提到了那個product所屬的Category. 牛!因此,咱們就加了這行代碼,從而: In categories_controller.rb, in the Categories show method, add code to store the products of a given category in an instance variable @product.

除了嵌套Controller,還要嵌套nesting Views:

The last and final step is to change the View for Categories show to be our Products index. This is because Categories show should now have all the Products for that Category.

Good news. We already wrote the code for this. All we need to do is pass it into a file. We can actually go ahead andreplace the code we wrote for Categories show, with the code for Products index.咱們已經有了products & categories的view,因此咱們要作的是把它們pass into到一個file裏。直接把Category show的代碼替換成code for the Products index.

[Instructions:]
>>Copy all the code from your Products index in index.html.erb and paste it into your Categories show View in show.html.erb. All your previous code in Categories show can be replaced. 把」app/views/products/index.html.erb「中的代碼,所有替換到」app/views/categories/show.html.erb「中,」app/views/categories/show.html.erb「中的代碼能夠不要了。
>>In your browser, visit localhost:8000/categories. On the Index page, under Art, click on Show. This will now show the Art Products in that Category.

可是好像有點問題。點了沒有列出art下面的全部東東。去到了一個categories/1

==========================

Congratulations! You created the Products page of the Etsy app. We created the Model, Controller, and Views for Products.

We generated the Product Model using our terminal. We used associations to define the relationship between the Category and Product table. We added Migration columns and migrated and seeded our database.

We then generated a Products Controller with the index, show, new, edit, and delete methods. This gave us route and View for those methods.

We created Controller methods for all eight of our CRUD actions, and Views for index, show, new, edit, and delete. We also nested our Products in our Categories show View.

Nice job. Now we'll finish our Etsy app by adding Authentication.

相關文章
相關標籤/搜索