【问题标题】:Trying to filter results by a string attribute in rails尝试通过rails中的字符串属性过滤结果
【发布时间】:2015-09-23 18:29:47
【问题描述】:

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

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

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

这是我的食谱控制器:

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

我在“食谱”视图文件夹中拥有不同的类别视图,蔬菜、肉类、家禽、海鲜和开胃菜。所有视图都是空的,除了一些文本只是说“蔬菜食谱将在此处列出。”、“肉类食谱将在此处列出。”、“海鲜食谱将在此处列出。”等。

我知道我的要求可能是一项艰巨的任务,所以你们能提供的任何帮助我都会非常感激。如果您需要更多信息,请告诉我。

【问题讨论】:

    标签: ruby-on-rails scope


    【解决方案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

    添加以下路线,(在 resources :recipes 之前)

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

    请注意,对于 as: :recipes_category,您可以使用 recipes_category_path 帮助程序来引用此路径

    现在我们需要将 category 动作添加到 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】:

      使用这样的命名范围

      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 
      

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

          【解决方案4】:

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

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

          'get recipe/:recipe' 
          

          并将该参数(字符串)传递给 show 函数。 这样您就可以像这样访问特定的食谱:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-09-24
            • 2016-11-02
            • 1970-01-01
            • 1970-01-01
            • 2017-08-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多