在Rails中添加用户收藏

时间:2016-11-23 04:21:46

标签: ruby-on-rails ruby associations favorites

我正在开发一个Rails应用程序,允许用户使用Food2Fork API搜索和浏览食谱。

版本: Rails 5.0.0.1,ruby 2.3.1p112(2016-04-26修订版54768)[x64-mingw32]

我有用户模型,配方模型和收藏夹模型。我试图允许登录到他们找到的最喜欢的食谱的用户。要明确的是,搜索和浏览都可以使用配方,以及登录/注销用户,因此我知道这不是用户自己或访问API的问题。

尝试实现此收藏系统时,打开视图时出现以下错误(代码位于底部):

undefined method `relation_delegate_class' for Recipe:Class

用户模型:

class User < ApplicationRecord

    has_secure_password 

    has_many :favorites
    has_many :favorite_recipes, through: :favorites, source: :favorited, source_type: 'Recipe'

end

食谱模型:

require 'httparty'

class Recipe
include HTTParty

#define API base URL and key for project
ENV['FOOD2FORK_API_KEY'] = 'api_key_here' # (this was edited so I don't make my key public)
base_uri 'http://food2fork.com/api'
default_params key: ENV['FOOD2FORK_API_KEY']
format :json

#search method
def self.for term        
    get('/search', query: { q: term }) ["recipes"]
end

#show method
def self.find term
    get('/get', query: { rId: term }) ["recipe"]
end

def self.browse term
    get('/browse', query: { q: term }) ["recipes"]#random number
end

end

最喜欢的型号:

class Favorite < ApplicationRecord
  belongs_to :user
  belongs_to :favorited, polymorphic: true
 end

用户控制器:

class UsersController < ApplicationController

  def new
  @user = User.new
end

def create 
  @user = User.new(user_params) 
  if @user.save
    session[:user_id] = @user.id 
    redirect_to '/home' 
  else 
    redirect_to '/register' 
  end 
end

private
  def user_params
    params.require(:user).permit(:username, :email, :password, :location, :fname, :lname)
  end

end

食谱控制器:

class RecipesController < ApplicationController
  def search
    @search_term = params[:ingredient]
    @recipes = Recipe.for(@search_term)
  end

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

  def browse
    @rand_num = params[:random]
    @rand_recipes = Recipe.for(@rand_num)
  end

end

最喜欢的控制器:

class FavoriteRecipesController < ApplicationController
     before_action :set_recipe

  def create
    if Favorite.create(favorited: @recipe, user: current_user)
      redirect_to @recipe, notice: 'Recipe favorited'
    else
      redirect_to @recipe, alert: 'Something went wrong.'
    end
  end

  def destroy
    Favorite.where(favorited_id: @recipe.rId, user_id: current_user.id).first.destroy
    redirect_to @recipe, notice: 'Recipe unfavorited.'
  end

  private

  def set_recipe
    @recipe = Recipe.find(params[:recipe_id] || params[:id])
  end
end

数据库架构:

ActiveRecord::Schema.define(version: 20161123033852) do

  create_table "favorite_recipes", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.integer  "recipe_id"
    t.integer  "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "favorites", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.integer  "user_id"
    t.string   "favorited_type"
    t.integer  "favorited_id"
    t.datetime "created_at",     null: false
    t.datetime "updated_at",     null: false
    t.index ["favorited_type", "favorited_id"], name: "index_favorites_on_favorited_type_and_favorited_id", using: :btree
    t.index ["user_id"], name: "index_favorites_on_user_id", using: :btree
  end

  create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    t.string   "username"
    t.string   "email"
    t.string   "password_digest"
    t.decimal  "location",        precision: 10
    t.string   "fname"
    t.string   "lname"
    t.datetime "created_at",                     null: false
    t.datetime "updated_at",                     null: false
  end

  add_foreign_key "favorites", "users"
end

最后,在recipes / show.html中的视图:

 <% this_recipe = @recipe %>
 <div class="container">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>

    </div>

  </div>
<div class="container-fluid bg-grey" style="text-align:center">
<h1><%= this_recipe["title"] %></strong></h1>
<% if (this_recipe.nil? or this_recipe == []) %>
<p> <h2><strong>Sorry</b>, that recipe doesn't exist.</h2></p>
<% else %>
<center><div class="recipebox" style="padding:20px;margin:10px; border:1px solid orange; background:white;width:75%">
    <div class="row">
<div class="col-md-6">
    <p><%= link_to(image_tag(this_recipe["image_url"], height: '400', width: '400'), this_recipe["source_url"])%><br/>
(<%= link_to("View Recipe Source", this_recipe["source_url"]) %>)</p>
</div>
<div class="col-md-6">
<h2>Ingredients:</h2>
<% ingredients = this_recipe["ingredients"] %>
 <% ingredients.each do |i| %>
 &#0149; <%= i %> <br/>
 <% end %>

<p>
<%- unless current_user.favorite_recipes.exists?(id: @recipe.rId) -%>
<%= link_to 'Add to favorites', favorite_recipes_path(recipe_id: @project), method: :post %>
<%- else -%>
<%= link_to 'Remove from favorites', favorite_recipe_path(@recipe), method: :delete %>
<%- end -%>

</div>


 <% end %>
</center>
</div>
</div>

    </div>

我不确定我是否没有正确地关联模型,我没有正确传递信息,或者究竟是什么导致了这个错误。感谢您解决这个问题的任何帮助。

修改

跟踪:

activerecord (5.0.0.1) lib/active_record/relation/delegation.rb:106:in `relation_class_for'
activerecord (5.0.0.1) lib/active_record/relation/delegation.rb:100:in `create'
activerecord (5.0.0.1) lib/active_record/associations/collection_association.rb:47:in `reader'
activerecord (5.0.0.1) lib/active_record/associations/builder/association.rb:111:in `favorite_recipes'
app/views/recipes/show.html.erb:32:in `_app_views_recipes_show_html_erb___356804060_113751160'
actionview (5.0.0.1) lib/action_view/template.rb:158:in `block in render'
activesupport (5.0.0.1) lib/active_support/notifications.rb:166:in `instrument'
actionview (5.0.0.1) lib/action_view/template.rb:348:in `instrument'
actionview (5.0.0.1) lib/action_view/template.rb:156:in `render'
actionview (5.0.0.1) lib/action_view/renderer/template_renderer.rb:54:in `block (2 levels) in render_template'
actionview (5.0.0.1) lib/action_view/renderer/abstract_renderer.rb:42:in `block in instrument'
activesupport (5.0.0.1) lib/active_support/notifications.rb:164:in `block in instrument'
activesupport (5.0.0.1) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (5.0.0.1) lib/active_support/notifications.rb:164:in `instrument'
actionview (5.0.0.1) lib/action_view/renderer/abstract_renderer.rb:41:in `instrument'
actionview (5.0.0.1) lib/action_view/renderer/template_renderer.rb:53:in `block in render_template'
actionview (5.0.0.1) lib/action_view/renderer/template_renderer.rb:61:in `render_with_layout'

日志:

ActionView::Template::Error (undefined method `relation_delegate_class' for Recipe:Class):
    29:  <% end %>
    30:
    31: <p>
    32: <%- unless current_user.favorite_recipes.exists?(id: @recipe.rId) -%>
    33: <%= link_to 'Add to favorites', favorite_recipes_path(recipe_id: @recipe), method: :post %>
    34: <%- else -%>
    35: <%= link_to 'Remove from favorites', favorite_recipe_path(@recipe), method: :delete %>

app/views/recipes/show.html.erb:32:in `_app_views_recipes_show_html_erb___356804060_113751160'
  Rendering C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout
  Rendering C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
  Rendered C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (6.0ms)
  Rendering C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
  Rendered C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.9ms)
  Rendering C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
  Rendered C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (2.0ms)
  Rendered C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/actionpack-5.0.0.1/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (1241.0ms)

2 个答案:

答案 0 :(得分:0)

对于基本用途,这是通过has_and_belongs_to_many关系完成的。参见:

http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

如果您想了解有关收藏模式的更多信息,而不仅仅是用户收藏食谱的事实,您可以将其分解为自己的类。

(警告:从头开始打字,尚未经过测试......但想法就在那里)

class Favorite
  belongs_to :user
  # has a recipe_id field that's linked to the id of Recipe on Food2Fork API

  def recipe
    #... code to get a recipe from id ...
  end
end

class User
  has_many :favorites

  def favorite!(recipe)
    self.favorites.create(:recipe_id => recipe.id)
  end
end

答案 1 :(得分:0)

我按照this教程,轻松地在我的应用中设置了一个优惠系统。您可以使用以下实现并在您的应用程序中进行设置。