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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

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

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

593閲覧

rails6でindexアクションでのみ子モデルに保存した画像を表示することができないため、呼び出して一覧表示できるようにしたい。

hero_1111

総合スコア13

Ruby

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

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2022/04/12 19:09

質問失礼致します。

rails6でレッスンを投稿して募集できる機能を作ろうとしているのですが、子モデルの画像を呼び出したく、lesson_controllerでshowアクション内では呼び出せるのですが、index内で呼び出すことができません。

プログラミング初心者のため、初歩的なミスかもしれませんがお教えいただけますと嬉しいです。お手を煩わせてしまいすみません。

schema.rb

ruby

1 create_table "lesson_images", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| 2 t.string "image" 3 t.integer "lesson_id" 4 t.datetime "created_at", precision: 6, null: false 5 t.datetime "updated_at", precision: 6, null: false 6 end 7 8 create_table "lessons", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t| 9 t.string "title", null: false 10 t.text "explain", null: false 11 t.integer "price", null: false 12 t.bigint "saler_id" 13 t.bigint "buyer_id" 14 t.datetime "created_at", precision: 6, null: false 15 t.datetime "updated_at", precision: 6, null: false 16 t.bigint "user_id" 17 end 18 19

lesson.rb

ruby

1class Lesson < ApplicationRecord 2 belongs_to :user 3 has_many :lesson_images, dependent: :destroy 4end

lesson_image.rb

ruby

1class LessonImage < ApplicationRecord 2 belongs_to :lesson 3 mount_uploader :image, ImageUploader 4end

routes.rb

ruby

1Rails.application.routes.draw do 2 3 root to: 'toppages#index' 4 5 devise_for :users, controllers: { 6 :registrations => 'users/registrations', 7 :sessions => 'users/sessions', 8 :passwords => 'users/passwords' 9 } 10 11 get 'users/show' => 'users#show' 12 resources :users, only: [:show, :index] 13 14 resources :messages, only: [:create] 15 16 resources :rooms, :only => [:create, :show, :index] 17 18 resources :lessons 19end

lesson_controller.rb

ruby

1class LessonsController < ApplicationController 2 before_action :ensure_current_user, :only => [:edit, :update] 3 before_action :set_lesson, :only => [:show, :edit, :update] 4 5 def index 6 @lessons = Lesson.includes(:lesson_images).page(params[:page]).per(5) 7 end 8 9 def show 10 @user = User.find_by(id: @lesson.user_id) 11 @lesson_images = @lesson.lesson_images 12 end 13 14 def new 15 @lesson = Lesson.new 16 @lesson_images = @lesson.lesson_images.build 17 end 18 19 def create 20 @lesson = Lesson.new(lesson_params) 21 if @lesson.save 22 redirect_to lessons_path 23 else 24 render :new 25 end 26 end 27 28 def edit 29 end 30 def update 31 if @lesson.update(lesson_params) 32 redirect_to lesson_path 33 else 34 render :edit 35 end 36 end 37 38 def destroy 39 lesson = Lesson.find(params[:id]) 40 if lesson.user_id == current_user.id 41 if lesson.destroy 42 redirect_to lessons_path, notice: "削除が完了しました" 43 else 44 redirect_to lessons_path, alert: "削除が失敗しました" 45 end 46 end 47 end 48 49 private 50 def lesson_params 51 params.require(:lesson).permit(:title,:explain,:price,lesson_images_attributes: [:id, :lesson_id, :image]).merge(user_id: current_user.id) 52 end 53 54 def ensure_current_user 55 lesson = Lesson.find(params[:id]) 56 if lesson.user_id != current_user.id 57 redirect_to action: :index 58 end 59 end 60 61 def set_lesson 62 @lesson = Lesson.find(params[:id]) 63 end 64end 65

index.html.erb

ruby

1<div class="row row-cols-1 row-cols-md-3 g-4"> 2 <div class="col"> 3 <div class="card"> 4 5 <% @lessons.each do |lesson| %> 6 <p><a href="/lessons/<%= lesson.id %>"><%= lesson.title %></a></p> 7 <p><%= lesson.price %></p> 8 <p><%= lesson.explain %></p> 9 <p><%= lesson.user_id %>さん</p> 10 11 <% if lesson.lesson_image.image.blank? %> 12 <%= image_tag "" %> 13 <% else %> 14 <%= image_tag lesson.lesson_images.image.url %> 15 <% end %> 16 17 <%= paginate @lessons %> 18 <% end %> 19 20 </div> 21 </div> 22</div>

show.html.erb

ruby

1<p><%= @lesson.title %></p> 2<p><%= @lesson.price %></p> 3<p><%= @lesson.explain %></p> 4<p><%= @lesson.user_id %></p> 5 6<% @lesson_images.each do |lesson_image| %> 7 <% if lesson_image.image.blank? %> 8 <%= image_tag "" %> 9 <% else %> 10 <%= image_tag lesson_image.image.url %> 11 <% end %> 12<% end %> 13 14 15<% if user_signed_in? %> 16 <%= link_to "編集", edit_lesson_path %> 17 <%= link_to '削除', lesson_path(@lesson.id),method: :delete %> 18<% end %>

image_uploader.rb

ruby

1class ImageUploader < CarrierWave::Uploader::Base 2 # Include RMagick or MiniMagick support: 3 # include CarrierWave::RMagick 4 include CarrierWave::MiniMagick 5 6 # Choose what kind of storage to use for this uploader: 7 storage :file 8 # storage :fog 9 10 # Override the directory where uploaded files will be stored. 11 # This is a sensible default for uploaders that are meant to be mounted: 12 def store_dir 13 "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 14 end 15 16 # Provide a default URL as a default if there hasn't been a file uploaded: 17 def default_url(*args) 18 # # For Rails 3.1+ asset pipeline compatibility: 19 # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) 20 'default_lesson.png' 21 # "/images/fallback/" + [version_name, "default.png"].compact.join('_') 22 end 23 24 # Process files as they are uploaded: 25 # process scale: [200, 300] 26 # 27 # def scale(width, height) 28 # # do something 29 # end 30 31 # Create different versions of your uploaded files: 32 # version :thumb do 33 process resize_to_fit: [300, 300] 34 # end 35 36 # Add an allowlist of extensions which are allowed to be uploaded. 37 # For images you might use something like this: 38 39 def extension_allowlist 40 %w(jpg jpeg png) 41 end 42 43 # Override the filename of the uploaded files: 44 # Avoid using model.id or version_name here, see uploader/store.rb for details. 45 # def filename 46 # "something.jpg" if original_filename 47 # end 48end

エラー文

undefined method `lesson_image' for #<Lesson id: 1, title: "テスト1", explain: "これはテストです1", price: 1000, saler_id: nil, buyer_id: nil, created_at: "2021-11-23 03:14:01.001941000 +0000", updated_at: "2021-11-23 03:14:01.001941000 +0000", user_id: nil> Did you mean? lesson_images lesson_images=

試したこと
▷lesson_image.imageに画像が保存されていない場合にエラーを吐いているのかと思い、if文で保存されていない場合は画像を表示しなくてもエラーを吐きました。

▷またアップローダーがうまくマウントできないのかと思い、画像ではなくidのみを呼び出した際もエラーがでました。

@lessonsのなかに全てのデータが入ってしまっていて特定のパラメーターを呼び出せていないからlesson_imageが認識されていないのかとおもったのですが、each文で取り出す際にひとつひとつ呼び出せるものではないのでしょうか?

それとも子モデルの呼び出しにはなにか特殊な方法が必要だったりするのでしょうか?
お手数をおかけしますが、よろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

エラーメッセージのとおりです。lesson_imageなんていう単数形のメソッドはありません。

投稿2022/04/12 23:25

maisumakun

総合スコア145123

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2022/04/12 23:27

lesson_imagesという名前のとおり、ファイルは複数個ある可能性があります。lesson_imagesをeachで回すなりして必要なファイルを取得してください。
hero_1111

2022/04/13 09:17

ご丁寧にお答え頂きありがとうございます! lessonをeachで回しているのにどうしてlesson.lesson_imageをひとつひとつ呼び出せないのかと思っていましたがlesson_imagesでeachを回す必要があったのですね。 知らずに質問してしまいすみません。 ありがとうございました!
guest

0

ベストアンサー

has_many :lesson_images, ですから 複数イメージが添付されてます。
ので、
lesson.lesson_image はないですね。 lesson.lesson_images です。
lesson.lesson_images は LessonImageの配列ですので、これには image はありません。
lesson.lesson_images.each で 表示するか lesson.lesson_images.first.image で一つだけ表示するか、ですね

投稿2022/04/12 23:26

winterboum

総合スコア23284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hero_1111

2022/04/13 09:13

そうだったんですね。 てっきり親モデルをeachで回せばそれに紐づいた子モデルが呼び出されるものだと思っていました。 こちらの知識不足ですみません! ご丁寧にお答えいただき助かりましたありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問