質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.49%

  • Ruby

    7893questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

rails アソシエーションで動作がうまくいかなくなる際の対処法

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 143

takeke

score 38

ecサイトのオーダー関連の質問させていただいた者です。
https://teratail.com/questions/124047

今色々やっているのですがいまだにいい結果が出ていませんが、そこで新たに質問が出来たのでさせて頂きます。

先ほどの質問では注文の際の情報を新たなテーブルを作って、後から何が注文されたかなど見れるようにと思ったのですが、色々やっていくうちに、新たなテーブルを作らなくてもデータを引き出せるようになりました。そこで問題が起きるのですが、アソシエーションでカートの中の商品(line_items)とオーダー(orders)を関連づけているのですが、これがうまく動作しません。

今までは関連付けしないで作っていたのですが、これを関連づけしたところ、rails c コマンド内にて必要なデータの全て得ることができました。しかしrails sでアプリを動かそうとするとカート機能動かなくなってしまいます。

ブラウザ上では何も起こらず、クロームの検証でみるとサーバーエラーが起きています。ターミナル上ではテンプレートエラーが出ていて該当箇所と思われる部分を修正方法がわからないのでとりあえず消してみたのですがうまくいきませんでした。

以下エラー内容やコード載せます。

クロームの検証

POST http://localhost:3000/line_items?product_id=27 500 (Internal Server Error)

Rails.ajax @ rails-ujs.self-817d9a8cb641f7125060cb18fefada3f35339170767c4e003105f92d4c204e39.js?body=1:189
Rails.handleRemote @ rails-ujs.self-817d9a8cb641f7125060cb18fefada3f35339170767c4e003105f92d4c204e39.js?body=1:546
(anonymous) @ rails-ujs.self-817d9a8cb641f7125060cb18fefada3f35339170767c4e003105f92d4c204e39.js?body=1:146

ターミナル

ActionView::Template::Error (No route matches {:action=>"decrease", :controller=>"line_items", :id=>#<LineItem id: nil, product_id: 27, cart_id: 175, created_at: nil, updated_at: nil, quantity: 1, order_id: nil>}, possible unmatched constraints: [:id]):
     7:     <dd class="item_price test1"><%= number_to_currency( line_item.product.price, :locale => 'jp') %></dd>
     8:     <dd class="test1 test2">&times; <%= line_item.quantity %> 個 =</dd>
     9:     <dd class="test1 test2 price_item">   <%= number_to_currency( line_item.total_price, :locale => 'jp')  %></dd>
    10:     <dd class="test1 test2 test3"><%= button_to '-', decrease_line_item_path(line_item), :method => :put, remote: true %></dd>
    11:     <dd class="test1 test2 test3"><%= button_to '+', increase_line_item_path(line_item), :method => :put, remote: true %></dd><br><hr>
    12:     <!-- <td><%#= button_to '削除', line_item, :method => :delete %></td> -->
    13: </dl>

app/views/line_items/_line_item.html.erb:10:in `_app_views_line_items__line_item_html_erb___6180940__636402918'
app/views/carts/_cart.html.erb:4:in `_app_views_carts__cart_html_erb__325764855__636433798'
app/views/layouts/application.html.erb:136:in `_app_views_layouts_application_html_erb__754154700_109666420'
app/controllers/line_items_controller.rb:43:in `block (2 levels) in create'
app/controllers/line_items_controller.rb:36:in `create'


指摘されていると思われる:action=>"decrease"と、アクションincrease使っている箇所のviewを削除した後のターミナル

Started POST "/line_items?product_id=28" for 10.0.2.2 at 2018-04-29 11:15:06 +0000
Processing by LineItemsController#create as JS
  Parameters: {"product_id"=>"28"}
  Cart Load (2.1ms)  SELECT  "carts".* FROM "carts" WHERE "carts"."id" = ? LIMIT ?  [["id", 175], ["LIMIT", 1]]
  Product Load (1.6ms)  SELECT  "products".* FROM "products" WHERE "products"."id" = ? LIMIT ?  [["id", 28], ["LIMIT", 1]]
  LineItem Load (2.5ms)  SELECT  "line_items".* FROM "line_items" WHERE "line_items"."cart_id" = ? AND "line_items"."product_id" = ? LIMIT ?  [["cart_id", 175], ["product_id", 28], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  Product Load (1.4ms)  SELECT  "products".* FROM "products" WHERE "products"."id" = ? LIMIT ?  [["id", 28], ["LIMIT", 1]]
   (0.1ms)  rollback transaction
  Rendering line_items/new.html.erb within layouts/application
  Rendered line_items/_form.html.erb (1.3ms)
  Rendered line_items/new.html.erb within layouts/application (24.9ms)
  LineItem Load (2.0ms)  SELECT "line_items".* FROM "line_items" WHERE "line_items"."cart_id" = ?  [["cart_id", 175]]
  Product Load (1.8ms)  SELECT  "products".* FROM "products" WHERE "products"."id" = ? LIMIT ?  [["id", 25], ["LIMIT", 1]]
  Rendered collection of line_items/_line_item.html.erb [2 times] (5.2ms)
  Rendered carts/_cart.html.erb (31.0ms)
Completed 200 OK in 1235ms (Views: 1210.1ms | ActiveRecord: 11.6ms)

line_items_controller.rb

class LineItemsController < ApplicationController
  skip_before_action :authorize, only: :create
  before_action :set_line_item, only: [:show, :edit, :update, :destroy]

  def index
    @line_items = LineItem.all
  end

  def show
      @line_item = LineItem.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @line_item }
    end
  end

  def new
    @line_item = LineItem.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @line_item }
    end
  end

  def edit
      @line_item = LineItem.find(params[:id])
  end

  def create
      @cart = current_cart
      product = Product.find(params[:product_id])
    @line_item = @cart.add_product(product.id)

    respond_to do |format|
      if @line_item.save
        # format.html { redirect_to store_url, notice: 'Line item was successfully created.' }
        format.html { redirect_to store_url}
        format.js { @current_item = @line_item}
        format.json { render json: @line_item, status: :created, location: @line_item }
      else
        format.html { render action: "new" }
        format.json { render json: @line_item.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
      @line_item = LineItem.find(params[:id])

    respond_to do |format|
      if @line_item.update(line_item_params)
        format.html { redirect_to @line_item, notice: 'Line item was successfully updated.' }
        format.json { render :show, status: :ok, location: @line_item }
      else
        format.html { render :edit }
        format.json { render json: @line_item.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
      @line_item = LineItem.find(params[:id])
    @line_item.destroy
    respond_to do |format|
      format.html { redirect_to store_url, notice: 'Line item was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  def decrease
      @cart = current_cart
      @line_item = @cart.decrease(params[:id])

      respond_to do |format|
          if @line_item.save
              format.html{redirect_to store_url}
              format.json{head :ok}
          else
              format.html{render action: "edit"}
              format.json{render json: @line_item.errors, status: :unprocessable_entity}
          end
      end
  end

  def increase
      @cart = current_cart
      @line_item = @cart.increase(params[:id])

      respond_to do |format|
          if @line_item.save
              format.html{redirect_to store_url}
              format.json{head :ok}
          else
              format.html{render action: "edit"}
              format.json{render json: @line_item.errors, status: :unprocessable_entity}
          end
      end
  end

  private
    def set_line_item
      @line_item = LineItem.find(params[:id])
    end

    def line_item_params
      params.fetch(:line_item, {})
    end
end


line_item.rb

class LineItem < ApplicationRecord
    belongs_to :order #←これをなくすと動作はうまくいきます。ただしデータが引き出せなくなります
    belongs_to :product
    belongs_to :cart

    def total_price
        product.price * quantity
    end
end


order.rb

class Order < ApplicationRecord
    PAYMENT_TYPES = ["現金","クレジットカード","注文書"]
    has_many :line_items, dependent: :destroy
    has_many :order_items, dependent: :destroy

    belongs_to :user


    validates :name, :address, :email,:user_id, presence: true
    validates :pay_type, inclusion: PAYMENT_TYPES

    default_scope -> { order(created_at: :desc) }

    def add_line_items_from_cart(cart)
        cart.line_items.each do |item|
            item.cart_id = nil
            line_items << item
        end
    end
end


該当箇所は以上なのですが、何かお気付きの箇所などありましたらご助言いただけると助かります。他のデータも必要でしたら載せますのでおっしゃってください。
よろしくお願いいたしますm(._.)m

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

自己解決できました。
今回の問題は、line_itemとorder間のvalidationの問題でした。

アソシエーションを組んでいて、カートに商品を入れる際に(line_item)をcreateすることになるのですが(line_item)はbelongs_to :orderなのでorderがないと存在できなかったのです。なのでここでエラーでした。結論としてこのエラーを回避、orderがなくてもcreateできるようにすればOKでした!なのでcreateの記述でsaveをsave(validate: false)だけで通るようになりました。

かなり迷ったので重ねて質問してしまいましたのでそちらも載せて起きます
https://teratail.com/questions/124188

ありがとうござしましたm(._.)m

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    7893questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。