从两个ID创建rails记录

时间:2012-12-01 05:02:23

标签: ruby-on-rails activerecord

我正在尝试构建的功能允许用户访问餐厅。

我有用户,位置和餐馆模型。 地点有很多餐馆。

我创建了一个带有user_id和restaurant_id属性的Visits模型,以及一个带有create和destroy方法的visits_controller。

事实是,我无法创建实际的访问记录。有关如何实现这一目标的任何想法?或者我是以错误的方式去做的。

路由错误

No route matches {:controller=>"restaurants", :location_id=>nil}

代码:

路线:

location_restaurant_visits POST   /locations/:location_id/restaurants/:restaurant_id/visits(.:format)     visits#create
 location_restaurant_visit DELETE /locations/:location_id/restaurants/:restaurant_id/visits/:id(.:format) visits#destroy

型号:

class Visit < ActiveRecord::Base
  attr_accessible :restaurant_id, :user_id
  belongs_to :user 
  belongs_to :restaurant
end

查看:

  <% @restaurants.each do |restaurant| %>
    <%= link_to 'Visit', location_restaurant_visits_path(current_user.id, restaurant.id), method: :create %>
    <% @visit = Visit.find_by_user_id_and_restaurant_id(current_user.id, restaurant.id) %>
    <%= @visit != nil ? "true" : "false" %>
  <% end %>

控制器:

class VisitsController < ApplicationController
  before_filter :find_restaurant
  before_filter :find_user

  def create

    @visit = Visit.create(params[:user_id => @user.id, :restaurant_id => @restaurant.id])

    respond_to do |format|
      if @visit.save
        format.html { redirect_to location_restaurants_path(@location), notice: 'Visit created.' }
        format.json { render json: @visit, status: :created, location: @visit }
      else
        format.html { render action: "new" }
        format.json { render json: @visit.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @visit = Visit.find(params[:user_id => @user.id, :restaurant_id => @restaurant.id])
    @restaurant.destroy

    respond_to do |format|
      format.html { redirect_to location_restaurants_path(@restaurant.location_id), notice: 'Unvisited.' }
      format.json { head :no_content }
    end
  end

  private

  def find_restaurant
    @restaurant = Restaurant.find(params[:restaurant_id])
  end

  def find_user
    @user = current_user
  end

end

2 个答案:

答案 0 :(得分:1)

我在这看到很多问题。第一个是VisitController的{​​{1}}操作中的这一行代码(以及create操作中的相同行):

destroy

@visit = Visit.create(params[:user_id => @user.id, :restaurant_id => @restaurant.id]) hash,所以你应该传递一个密钥(如果有的话),而不是一堆params绑定。你的意思是:

key => value

请注意,您在过滤方法之前初始化@visit = Visit.create(:user_id => @user.id, :restaurant_id => @restaurant.id) @user,因此您无需在此处访问@restaurant

但是,这行代码仍然有点奇怪,因为您正在创建一条记录,然后在几行之后保存它(params)。这是多余的:if @visit.save启动并保存记录,因此之后保存记录几乎毫无意义。您可能要做的是首先使用Visit.create发起新的Visit,然后保存:

Visit.new

我接下来要注意的是,您尚未在def create @visit = Visit.new(:user_id => @user.id, :restaurant_id => @restaurant.id) respond_to do |format| if @visit.save ... 操作中启动@location,但是您可以在此处引用它:

create

由于您需要每个餐馆路线的位置(因为format.html { redirect_to location_restaurants_path(@location), notice: 'Visit created.' } 是嵌套资源),您也可以为它创建一个方法和restaurant,就像您使用{{1}一样}:

before_filter

下一个问题是,在您的观看中,find_restaurant传递的是before_filter :find_location ... def find_location @location = Location.find(params[:location_id]) end location_restaurant_pathid。这里有两个问题。首先,第一个参数应该是位置,而不是用户(匹配current_user中的顺序)。下一个问题是,对于restaurant方法,您必须传递实际对象,而不是对象的id。最后,您有location_restaurant_path,但这里的_path指的是HTTP方法,所以您想要的是method: :create

method

您需要在过滤前向method: :post添加link_to 'Visit', location_restaurant_visits_path(@location, restaurant.id), method: :post ,以便在此处的视图中提供find_location

可能还有其他问题,但这些都是一些问题。

答案 1 :(得分:0)

location_idnil,路径定义并没有说(/:location_id)强制非零值以便路由到该路径;如果您可以从子项的属性派生它,则创建一个没有location_id的新路由(即restaurant_id引用已知道其自己的Restaurant的{​​{1}}。