#一部解決したので明日以降改定します。
前提・実現したいこと
問題点の主旨
Railsで製品の口コミアプリを開発中です。
口コミ投稿機能を実装中に、Ajaxで通信後の処理が実行されない原因を解明してoption要素の削除・追加したいです。
######学習歴
・CS基礎(キタミ式イラストIT塾 基本情報技術者)
・Linux基礎(Linux標準教科書)
・HTML/CSS/JavaScript基礎(ドットインストール)
・Railsチュートリアル 2週程度
発生している問題・エラーメッセージ
期待する動作
'/reviews/new'ページ
ブランド名(セレクトボックス)で項目選択
↓
選択したブランドに 該当する製品のみ を選択できるようにする。
下記画像で言い換えますと、
↓画像1:投稿画面を開いた直後
↓画像2:ブランド名選択後
↓画像3:product-1 のプルダウンをクリック後
ここでは本来"product-1"が一つだけ表示されれば意図した動作になります。
仮説
大きく分けて二つの問題が原因で実装が進展していないと考えます。
-
問題A: Ajaxで通信が成功した後の処理が実行されない
-
問題B: 上記処理で、option要素追加を実行するコマンドを抽象的にかけない
該当のソースコード
app/javascript/packs/application.js
/* setting */ import Rails from "@rails/ujs" import Turbolinks from "turbolinks" import * as ActiveStorage from "@rails/activestorage" import "channels" Rails.start() Turbolinks.start() ActiveStorage.start() require("jquery/src/jquery") import "bootstrap" /* post form */ /* select Product form after choosing Brand */ $(document).on('turbolinks:load', function () { $(function () { var selectField = $('.js-select_field').on('change', function (){ var brand_id = selectField.val(); $.ajax({ type: 'GET', // リクエストのタイプ url: '/reviews/picks', // リクエストを送信するURL data: { brand_id: brand_id }, // サーバーに送信するデータ dataType: 'json' // サーバーから返却される型 }) .done(function (data) { $('#review_product_id').children().remove(); //製品選択肢を削除 $(data).each(function(i,review) { $('.js-receive_field').append( $("<option>").val(i).text(review.brands.name)); }); }); }); }); });
####Controller
app/controllers/reviews/picks_controller.rb
ruby
1class Reviews::PicksController < ApplicationController 2 def index 3 @reviews = Review.find(params[:brand_id]) 4 respond_to do |format| # リクエスト形式によって処理を切り分ける 5 format.html { redirect_to :root } # html形式の場合 6 format.json { render json: @reviews } # json形式の場合 7 end 8 end 9end
config/routes.rb
Rails.application.routes.draw do devise_for :users, controllers: { registrations: 'users/registrations', sessions: 'users/sessions', users: 'users' } root 'pages#index' get '/about', to: 'pages#about' get '/contact', to: 'pages#contact' resources :users, only: [:index, :show] namespace :reviews do resources :picks, only: :index, defaults: { format: :json } end resources :reviews, only: [:create, :destroy, :new] resources :products resources :brands # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html end
app/controllers/reviews_controller.rb
reviews_controller.rb
1class ReviewsController < ApplicationController 2 before_action :authenticate_user!, only:[:create, :destroy, :new] 3 before_action :correct_user, only:[:destroy] 4 5 def create 6 @review = current_user.reviews.build(review_params) 7 if @review.save 8 redirect_to root_url 9 else 10 render 'pages/show' 11 end 12 end 13 14 private 15 def review_params 16 params.require(:review).permit(:content, :user_id, :product_id) 17 end 18 19 def correct_user 20 @review = current_user.reviews.find_by(id: params[:id]) 21 redirect_to root_url unless current_user 22 end 23end
#####Model
- ER図 (関連するところを抜粋)
db/schema.rb(一部省略)
ruby
1 2 create_table "brands", charset: "utf8mb4", force: :cascade do |t| 3 t.string "name" 4 t.datetime "created_at", precision: 6, null: false 5 t.datetime "updated_at", precision: 6, null: false 6 end 7 8 create_table "products", charset: "utf8mb4", force: :cascade do |t| 9 t.string "name" 10 t.datetime "created_at", precision: 6, null: false 11 t.datetime "updated_at", precision: 6, null: false 12 t.bigint "brand_id", null: false 13 t.index ["brand_id"], name: "index_products_on_brand_id" 14 end 15 16 create_table "reviews", charset: "utf8mb4", force: :cascade do |t| 17 t.text "content" 18 t.bigint "user_id", null: false 19 t.datetime "created_at", precision: 6, null: false 20 t.datetime "updated_at", precision: 6, null: false 21 t.bigint "product_id", null: false 22 t.index ["product_id"], name: "index_reviews_on_product_id" 23 t.index ["user_id", "created_at"], name: "index_reviews_on_user_id_and_created_at" 24 t.index ["user_id"], name: "index_reviews_on_user_id" 25 end 26 27 create_table "users", charset: "utf8mb4", force: :cascade do |t| 28 t.datetime "created_at", precision: 6, null: false 29 t.datetime "updated_at", precision: 6, null: false 30 t.string "name" 31 end 32 33 add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" 34 add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" 35 add_foreign_key "products", "brands" 36 add_foreign_key "reviews", "products" 37 add_foreign_key "reviews", "users" 38end
app/models/review.rb
ruby
1class Review < ApplicationRecord 2 belongs_to :user 3 belongs_to :product 4 validates :user_id, presence: true 5 validates :product_id, presence: true 6 validates :content, presence: true, length: { maximum: 140 } 7end
app/models/product.rb
class Product < ApplicationRecord has_many :reviews belongs_to :brand has_one_attached :image validates :brand_id, presence: true validates :name, presence: true validates :soc_antutu_score, presence: true validates :battery_capacity, presence: true end
app/models/brand.rb
class Brand < ApplicationRecord has_many :products has_one_attached :image validates :name, presence: true, \ uniqueness: true, length: {maximum: 50} end
Views
app/views/layouts/application.html.slim
doctype html html head title | hello app meta[name="viewport" content="width=device-width,initial-scale=1"] = csrf_meta_tags = csp_meta_tag = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' = javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' = stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' body header (省略) = yield = debug(params) if Rails.env.development?
app/views/reviews/new.html.slim
h1 投稿画面 = render 'reviews/form'
app/views/reviews/_form.html.slim
.container .row .col-12.col-md-6.offset-md-3 .card.px-3.my-3 = form_with(model: @review, local: true) do |f| = render 'devise/shared/error_messages', object: f.object .field.py-3 = f.collection_select(:brand_id, @brands, :id, :name, {prompt: "ブランド名"}, {class: "js-select_field form-control"}) .field.pb-3 = f.collection_select(:product_id, @products, :id, :name, {}, {class: "js-receive_field form-control"}) .field.pb-3 = f.text_area :content, placeholder: "Write down some comment.", class: "form-control" .d-grid = f.submit "Post", class: "btn btn-primary mb-3"
試したこと
・(Adblockerなど)ブラウザ側でjavaScriptがブロックされていないか?
=> 確認済。ブロック停止状態になっています。
自分で入力した jQuery のプログラムを、ブラウザーのコンソールから実行しました。セレクター・メソッドが適切か調べるためです。
・option要素が消えるか確認
$('#review_product_id').children().remove(); //製品選択肢を削除 #=> option要素が消えることを確認
・option要素の追加はできるのか確認
動的に追加するために抽象的にすると分からなくなったので、value・文章を指定してoption要素を追加する方法を確認しました。
(function() { $('.js-receive_field').append( $("<option>").val("1").text("select-1")); }); #=> <option value="1">select-1</option>が追加されるのを確認。
・function(data)の data の中身を確認しました。
$(document).on('turbolinks:load', function () { $(function () { var selectField = $('.js-select_field').on('change', function (){ var brand_id = selectField.val(); $.ajax({ type: 'GET', // リクエストのタイプ url: '/reviews/picks', // リクエストを送信するURL data: { brand_id: brand_id }, // サーバーに送信するデータ dataType: 'json' // サーバーから返却される型 }) .done(function (data) { console.log(data); // dataを確認する }); }); });
product_id が確認できるので、これを基にしてproductの名前を追加できないかなと思いました。
補足情報(FW/ツールのバージョンなど)
今回初質問です。アドバイス・質問の仕方などで不適切な点ございましたら、ご遠慮なくご指摘いただけましたら幸いです。
環境等
・AWS Cloud9 (Ubuntu 18.04.5 LTS, Bionic Beaver)
・Rails 6.1.3.1
・Ruby 2.6.6p146
・Bundler version 2.0.2
・gem 3.0.8
Gemfile
1source 'https://rubygems.org' 2git_source(:github) { |repo| "https://github.com/#{repo}.git" } 3 4gem 'rails', '~> 6.1.2', '>= 6.1.2.1' 5gem 'mysql2', '~> 0.5' 6gem 'dotenv-rails' 7gem 'puma', '~> 5.0' 8gem 'sass-rails', '>= 6' 9gem 'webpacker', '~> 5.0' 10gem 'turbolinks', '~> 5' 11gem 'jbuilder', '~> 2.7' 12 13gem 'bootsnap', '>= 1.4.4', require: false 14 15gem 'html2slim' 16gem 'slim-rails' 17 18gem 'bootstrap', '~> 5.0.0.beta1' 19gem 'font-awesome-rails', '~> 4.7', '>= 4.7.0.7' 20 21gem 'devise', '~> 4.7', '>= 4.7.3' 22 23gem 'active_storage_validations' 24gem 'image_processing' 25gem 'mini_magick' 26 27gem 'pry-rails' 28gem 'pry-byebug', '~> 3.7' 29 30gem 'faker', '~> 2.16' 31 32gem 'mimemagic', '~> 0.4.3' 33 34gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 35
####参考にしたURL
- ベースに進めたサイト
・【Rails】Ajaxチュートリアル(Rails + jQuery)~処理の流れを理解しよう!
- jQuery
・ jQuery でセレクトボックスのプルダウン項目(option 要素)を追加/削除する方法
- Rails Ajax
・【Rails】セレクトボックスの選択によって動的に変化するコンテンツの実装
・selectとoptionタグをjQueryを使って動的に追加する
あなたの回答
tips
プレビュー