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

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

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

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

Q&A

解決済

2回答

1575閲覧

railsで紐付けたテーブルの画像URLを取得する方法

thesnowman

総合スコア154

Ruby on Rails

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

0グッド

1クリップ

投稿2019/08/22 16:20

編集2019/08/23 06:36

ブログの記事投稿機能を作っています。

現在、BlogテーブルとImageテーブルを一対多で関連付けています。
また、ネストしたフォームでImageテーブルに画像を登録できるようにしています。

ここまでは、おそらくうまくいきました
ですが次のステップ、投稿した画像をviewで表示することができません。


具体的に言います。

もし画像を別テーブルにせずにBlogテーブルに保存していたら以下のコードで画像URLが取得できますよね。

ruby

1@blog.picture.url

そこで私は以下のコードでImageテーブル画像のURLを取得できると思いトライしました。

ruby

1@blog.images.picture.url

しかし、これだとそもそも
@blog.imagesが、ActiveRecord::Associations::CollectionProxyというオブジェクトらしくて、.picture.urlが機能しません。

次に以下を試しました。

ruby

1@blog.images.first.picture.url

今度は、@blog.images.first.pictureがarrayオブジェクトだからurlメソッドが使えないと出ました。

他にもいろいろやってるのですができずに混乱しています。

聞きたいことをまとめると、Blogモデルのオブジェクトから関連付けているImageモデルの画像URLを取得したい。
というものです。よろしくお願いいたします。


migrationファイルだと長くなるので、schema.rbを載せます。
blogsのほうにもpictureカラムがありますが気にしないでください。

ruby

1 create_table "blogs", force: :cascade do |t| 2 t.integer "user_id" 3 t.text "content" 4 t.text "title" 5 t.text "category" 6 t.datetime "created_at", null: false 7 t.datetime "updated_at", null: false 8 t.string "picture" 9 t.integer "impressions_count", default: 0 10 end 11 12 create_table "images", force: :cascade do |t| 13 t.integer "blog_id" 14 t.string "picture" 15 t.datetime "created_at", null: false 16 t.datetime "updated_at", null: false 17 t.text "pictures" 18 end 19コード

Blogモデル

ruby

1class Blog < ApplicationRecord 2 has_many :images, dependent: :destroy 3 accepts_nested_attributes_for :images 4 5 is_impressionable counter_cache: true 6end

Imageモデル

ruby

1class Image < ApplicationRecord 2 belongs_to :blog, optional: true 3 mount_uploaders :picture, PictureUploader 4end 5

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

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

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

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

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

mingos

2019/08/22 16:49

マイグレーションファイルの内容を全部見せてもらわないと、 各テーブルがどういう構造なのか第三者には分かりません。 記載の内容からは、blogs, images, picturesの3つのテーブルが関係するように思えますので この3つのテーブルのマイグレーションファイルの内容を載せないと適切な回答は得られにくいかと
thesnowman

2019/08/22 17:31

すみません! migrationファイルだと長くなるので、schema.rbを載せます。 pictureテーブルはございません。 @blog.picture とすると、@blogのpicture属性の値が取得できますよね。 そして@blog.picture.urlとすると、画像URLが取得できますよね。 そんな感じで、@blog.imagesから取得できないかなぁと考えております。
mingos

2019/08/23 01:57 編集

さきほどのコメントを訂正します。 PictureUploaderという記載を見逃していました。 CarrierWaveを使っているんですね。 回答に記載しましたが、実験したところ問題なく出来たので原因が分かりませんでした。
guest

回答2

0

ベストアンサー

最小の構成で実験してみました。
結果的にはblog.images.first.picture.urlで成功しました。

rails consoleで登録してURL取得。

ruby

1blog = Blog.create! 2Image.create!( 3 blog: blog, 4 picture: open("tmp/sample.png") 5) 6 7blog.images.first.picture.url 8=> "/uploads/image/picture/1/sample.png"
  • マイグレーション

ruby

1class CreateBlogs < ActiveRecord::Migration[5.2] 2 def change 3 create_table :blogs do |t| 4 t.timestamps 5 end 6 end 7end 8 9class CreateImages < ActiveRecord::Migration[5.2] 10 def change 11 create_table :images do |t| 12 t.integer :blog_id, null: false 13 t.string :picture 14 t.timestamps 15 end 16 end 17end
  • モデル

ruby

1class Blog < ApplicationRecord 2 has_many :images 3end 4 5 6class Image < ApplicationRecord 7 belongs_to :blog 8 mount_uploader :picture, PictureUploader 9end
  • アップローダー

ruby

1class PictureUploader < CarrierWave::Uploader::Base 2 include CarrierWave::RMagick 3 4 process resize_to_fit: [800, 800] 5 6 version :thumb do 7 process resize_to_fill: [200, 200] 8 end 9 10 storage :file 11 12 def store_dir 13 "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 14 end 15 16 def extension_whitelist 17 %w(jpg jpeg png) 18 end 19 20end

投稿2019/08/23 01:53

編集2019/08/23 01:55
mingos

総合スコア4025

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

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

thesnowman

2019/08/24 02:40

ありがとうございます! 違いがあるとすれば、私はマウントするためのメソッドを mount_uploaderではなくmount_uploadersというものを使っているんですよね。 もしかしたら、そのせいかもしれません。
guest

0

「次に以下を試しました。」 までは まぁそうなるでしょうね という動きでした。
ですので
@blog.images.each do |image |
image.picture.urlをつかってごちょごちょ
end
を薦めようとして、
> @blog.images.first.pictureがarray
なんだぁ?
Uploaderにもおかしい点は見当たらないし。

2つ調べて下さい

  1. public/uploads/picture の下に画像が保存されているかどうか

ls -R public/uploads/picture 
@blog の id を 123 としたときに public/uploads/picture//123/.jpg などがあるかどうか。

  1. pp @blog.images.first と pp @blog.images.first.picture の結果

投稿2019/08/23 06:13

winterboum

総合スコア23329

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

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

thesnowman

2019/08/24 02:11

ご回答ありがとうございます! >>@blog.images.each do |image | >>image.picture.urlをつかってごちょごちょ 私もそれでいけると思ってました。 >>  1) public/uploads/picture の下に画像が保存されているかどうか >> ls -R public/uploads/picture  >> @blog の id を 123 としたときに public/uploads/picture/*/123/*.jpg などがあるかどうか public/uploads/image/pictureの下に 1、2、3・・・・とファイルがあります。 それら中に画像がありますね。 >> 2) pp @blog.images.first と pp @blog.images.first.picture の結果 >> blog.images.first Image Load (0.2ms) SELECT "images".* FROM "images" WHERE "images"."blog_id" = ? ORDER BY "images"."id" ASC LIMIT ? [["blog_id", 1], ["LIMIT", 1]] => #<Image id: 1, blog_id: 1, picture: "[\"タウンロート__1_.jpeg\"]", created_at: "2019-08-20 10:26:44", updated_at: "2019-08-20 10:26:44", pictures: nil> >> blog.images.first.picture Image Load (1.0ms) SELECT "images".* FROM "images" WHERE "images"."blog_id" = ? ORDER BY "images"."id" ASC LIMIT ? [["blog_id", 1], ["LIMIT", 1]]=> [#<PictureUploader:0x0000000004fcd470 @model=#<Image id: 1, blog_id: 1, picture: "[\"タウンロート__1_.jpeg\"]", created_at: "2019-08-20 10:26:44", updated_at: "2019-08-20 10:26:44", pictures: nil>, @mounted_as=:picture, @storage=#<CarrierWave::Storage::File:0x0000000004fcd380 @uploader=#<PictureUploader:0x0000000004fcd470 ...>>, @file=#<CarrierWave::SanitizedFile:0x0000000004fccd40 @file="/home/ec2-user/environment/media/public/uploads/image/picture/1/[\"タウンロート__1_.jpeg\"]", @original_filename=nil, @content_type=nil>, @versions={}> 大変お手数ですが、よろしくお願いいたします!
thesnowman

2019/08/24 02:28

立て続けにすみません、ちょっと進展いたしました。 arrayってことはその中の要素を取り出せば行けるかもと思い @blog.images.first.picture.first.url を使うと一応URLらしきものを取得できました。 >> blog.images.first.picture.first.url Image Load (0.1ms) SELECT "images".* FROM "images" WHERE "images"."blog_id" = ? ORDER BY "images"."id" ASC LIMIT ? [["blog_id", 1], ["LIMIT", 1]] => "/uploads/image/picture/1/%5B%22%E3%82%BF%E3%82%99%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%88%E3%82%99__1_.jpeg%22%5D" ですが、これもこれで .jpegのうしろに「%22%5D」というのがついているせいでURLとして使えないっぽいです!
winterboum

2019/08/24 13:36

%5B%22。。。%22%5D って ["。。。"] ですね。さらに配列か!! mingosさんへのコメントに「mount_uploaderではなくmount_uploaders」とありますが、mount_uploaders で有る必要ってあるのでしょうか?ないとするとmount_uploader になおしてはどうでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問