尝试通过rails

时间:2015-09-23 18:29:47

标签: ruby-on-rails scope

我对Rails相对较新,我正在尝试从头开始创建一个菜谱应用程序/网站,我没有关注任何教程或类似的东西。无论如何......我仍处于网站的早期阶段,但现在我想要显示所有不同种类食谱的索引列表。但我想过滤列表,例如:

如果我点击导航栏上的“蔬菜”按钮,我想进入一个只显示不同蔬菜食谱的索引页面。

我已经开始为食谱添加一个字符串属性,称为“类别”,因此我将能够区分肉类,海鲜,家禽,开胃菜和蔬菜食谱。我的目标是只需要一个控制器的“配方”,并且在索引操作中能够有条件地过滤参数。从而根据食物的“类别”过滤列表。但我不确定该怎么做。

这是我的RecipesController:

class RecipesController < ApplicationController
  def index
    @recipes = Recipe.all
  end

  def show
     @recipe = Recipe.find(params[:id])
  end

  def new
  end

  def edit
  end

end

这是我的路线档案:

Rails.application.routes.draw do
  resources :recipes
  get 'vegetables' => 'recipes#vegetables'
  get 'poultry' => 'recipes#poultry'
  get 'meat' => 'recipes#meat'
  get 'seafood' => 'recipes#seafood'
  get 'appetizers' => 'recipes#appetizers'

  devise_for :users

  get 'about' => 'welcome#about'

  root to: 'welcome#index'

end

以下是包含导航栏的应用程序布局文件:

<!DOCTYPE html>
<html>
<head>
  <title>Mrs. P's Cookbook</title>
  <link href='https://fonts.googleapis.com/css?family=Mate+SC' rel='stylesheet' type='text/css'>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>
  <div class="top-banner">
   <h1 class="banner-logo"> <%= link_to "Mrs. P's Cookbook", root_path %></h1>
   <nav>
    <%= link_to "POULTRY", poultry_path, class: "nav-link" %> |
    <%= link_to "MEAT", meat_path, class: "nav-link" %> |
    <%= link_to "SEAFOOD", seafood_path, class: "nav-link" %> |
    <%= link_to "APPETIZERS", appetizers_path, class: "nav-link" %> |
    <%= link_to "VEGETABLES", vegetables_path, class: "nav-link" %> |
    <%= link_to "ABOUT", about_path, class: "nav-link" %>
  </nav>

        <% if current_user %>
          Hello <%= current_user.email %>! <%= link_to "Sign out", destroy_user_session_path, method: :delete %>
        <% else %>
          <%= link_to "Sign In", new_user_session_path %> or
          <%= link_to "Sign Up", new_user_registration_path %>
        <% end %>
  </div>
<div class="white-field">
  <%= yield %>
    </div>
</body>
</html>

这是我的Recipe.rb模型文件:

class Recipe < ActiveRecord::Base
  has_many :comments

end

这是我的食谱表:

  create_table "recipes", force: :cascade do |t|
    t.string   "title"
    t.text     "body"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string   "category"
  end

我在配方视图文件夹中有不同的类别视图,蔬菜,肉类,家禽,海鲜和开胃菜。所有的观点都是空的,除了一些文字只是说“蔬菜食谱将在这里列出。”,“肉类食谱将在这里列出。”,“海鲜食谱将列在这里。”等。

我知道我所要求的可能是一个很高的要求,所以你们可以提供任何帮助我将非常感激。如果您需要更多信息,请告诉我。

4 个答案:

答案 0 :(得分:1)

使用像这样的命名范围

class Recipe < ActiveRecord::Base

scope :by_category, lambda {|cat|
    where(category: cat)
}
...
end

然后你可以打电话

Recipe.by_category("Vegetables")

你也可以这样做:

scope :vegetables, lambda {
    where(category: "Vegetables")
}

然后致电

Recipe.vegetables 

答案 1 :(得分:1)

我想出了两个可能的解决方案(其中很多!:))

解决方案1 ​​

一种解决方案可能是使用查询字符串。路线文件是

Rails.application.routes.draw do
  resources :recipes

  devise_for :users

  get 'about' => 'welcome#about'

  root to: 'welcome#index'

end

现在创建带有类别的链接作为参数。在您看来:

...
  <nav>
    ['poultry','meat','seafood','appetizers','vegetables'].each do |category|
      <%= link_to category.upcase, 
                  recipes_path(category: category), 
                  class: "nav-link" %> |
    end
    <%= link_to "ABOUT", about_path, class: "nav-link" %>
  </nav>
...

在控制器中,您可以捕获类别,查询其他答案中已显示的模型。例如

class RecipesController < ApplicationController
  def index
    @recipes = params[:category].blank? : Recipe.all :
               Recipe.where(category: params[:category])
  end

  ...
end

但如果您想自定义单个类别的视图,那就不那么优雅了。

解决方案2

添加以下路线(在资源:食谱之前)

Rails.application.routes.draw do
  get 'recipes/:category' => 'recipes#category', as: :recipes_category
  resources :recipes
  ...
end

请注意,使用 as :: recipes_category ,您可以使用 recipes_category_path 帮助

引用此路径

现在我们需要将类别操作添加到 RecipesController

class RecipesController < ApplicationController
  ...

  def category
    @recipes = Recipe.where(category: params[:category])
  end

  ...
end

link_to中的路径将更改为

 ...
 <%= link_to category.upcase, 
             recipes_category_path(category: category), 
             class: "nav-link" %> |
 ...

恕我直言,如果你想自定义你的视图而不关心参数的存在,那么它会更干净,而且网址看起来更漂亮:)。

期待

正如@ denys281已经提出的那样,类别字段闻起来像一个单独的实体,与具有N:1关系的食谱相关。

这两个模型将具有关联

class Recipe < ActiveRecord::Base
  belongs_to :category
end

class Category < ActiveRecord::Base
  has_many :recipes
end

通过这种方式,您可以通过调用

轻松获得所有类别
Category.all

类别的食谱
@category = Category.find(2)
@recipes = @category.recipes

这实际上取决于你想要达到的目标。我希望我能就这个论点给你一些想法。

关于使用 Slim 的其他建议,我不同意。它只是语法糖,它不是标准的,它会让你感到困惑:你会发现的大部分代码都有标准语法。

在使用其他工具之前先弄清楚,它会让您更好地了解背后的机制,更好地了解该工具是否能解决您的需求以及如何自定义它。

我建议你阅读官方的rails指南,无数的博客和文章,并尝试阅读其他人编写的代码(感谢开源!)。

答案 2 :(得分:0)

我认为你需要使用一些教程,这样你就会看到最佳实践等等。另外我认为你应该读一些关于关系数据库的好书。

  1. 使用slim;
  2. 创建类别表。食谱belongs_to:类别。类别has_many:食谱。检查association basics;
  3. 如何获取您可以查看的食谱Active Record Query Interface(像Recipe.where(category_id:params [:id]));
  4. 另请查看partials

答案 3 :(得分:0)

您的路线应与控制器中的功能一致,因此当您有“食谱#肉”的路线时,您的控制器将寻找“肉”功能和“肉”视图

我会删除这些路线,并有一个名为

'get recipe/:recipe' 

并将该参数(字符串)传递给show函数。 通过这种方式,您可以访问特定的配方:

@recipes = Recipe.where("category = ?", params[:recipe])