3

私が構築しようとしている機能により、ユーザーはレストランを訪れることができます。

ユーザー、場所、およびレストランのモデルがあります。場所には多くのレストランがあります。

user_id 属性と restaurant_id 属性を持つ Visits モデルと、create メソッドと destroy メソッドを持つ visits_controller を作成しました。

問題は、実際の Visit レコードを作成できないことです。これを達成する方法について何か考えはありますか?それとも、間違った方法で進んでいますか。

ルーティング エラー

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
4

2 に答える 2

1

ここには多くの問題があります。VisitController1 つ目は、のcreateアクション (およびアクションの同一の行destroy)の次のコード行です。

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

paramshashであるため、バインドの束ではなく、(もしあれば) キーを渡す必要がありkey => valueます。あなたがおそらく意味していたのは:

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

フィルター メソッドの前に初期化@userする@restaurantので、ここにアクセスする必要はありませんparams

ただし、このコード行はまだ少し奇妙です。レコードを作成し、数行後にそれを保存しているためです ( if @visit.save)。これは冗長です。Visit.createレコードを開始して保存するため、後で保存してもほとんど意味がありません。おそらくやりたいことは、最初に新しいVisitwith を開始しVisit.new、それを保存することです:

def create

  @visit = Visit.new(:user_id => @user.id, :restaurant_id => @restaurant.id)

  respond_to do |format|
    if @visit.save
    ...

次に気付くのは@locationcreateアクションで a を開始していないのに、ここでそれを参照していることです。

format.html { redirect_to location_restaurants_path(@location), notice: 'Visit created.' }

すべてのレストランルートの場所が必要になるため (restaurantはネストされたリソースであるため)、次のbefore_filterようにメソッドを作成することもできfind_restaurantます。

before_filter :find_location

...

def find_location
  @location = Location.find(params[:location_id])
end

次の問題は、あなたのビューでは、あなたがofと of をlocation_restaurant_path渡されることです。ここには 2 つの問題があります。まず、最初の引数はユーザーではなく場所でなければなりません ( の順序と一致します)。次の問題は、メソッドの場合、オブジェクトの ID ではなく、実際のオブジェクトを渡す必要があることです。最後に がありますが、ここでは HTTP メソッドを参照しているため、必要なものは次のとおりです。idcurrent_userrestaurantlocation_restaurant_path_pathmethod: :createmethodmethod: :post

link_to 'Visit', location_restaurant_visits_path(@location, restaurant.id), method: :post

ここでビューで使用できるようにするには、find_location前にフィルターを追加する必要があります。RestaurantController@location

他にも問題があるかもしれませんが、これらは最初にすべきことです。

于 2012-12-01T05:14:00.473 に答える
0

location_idであり、パス定義は、そのパスにルーティングするためにそこに非 nil 値を強制することをnil述べていません。子の属性から派生できるかどうかを指定(/:location_id)せずに新しいルートを作成します (つまり、 a は自身の を既に知っているa を参照します)。location_idrestaurant_idRestaurantlocation_id

于 2012-12-01T05:38:51.877 に答える