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

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

ただいまの
回答率

88.59%

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

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,408

thesnowman

score 25

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

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

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


具体的に言います。

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

@blog.picture.url

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

@blog.images.picture.url

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

次に以下を試しました。

@blog.images.first.picture.url


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

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

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


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

  create_table "blogs", force: :cascade do |t|
    t.integer "user_id"
    t.text "content"
    t.text "title"
    t.text "category"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "picture"
    t.integer "impressions_count", default: 0
  end

  create_table "images", force: :cascade do |t|
    t.integer "blog_id"
    t.string "picture"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.text "pictures"
  end
コード

Blogモデル

class Blog < ApplicationRecord
  has_many :images, dependent: :destroy
  accepts_nested_attributes_for :images

  is_impressionable counter_cache: true
end

Imageモデル

class Image < ApplicationRecord
  belongs_to :blog, optional: true
  mount_uploaders :picture, PictureUploader
end
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • mingos

    2019/08/23 01:49

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

    キャンセル

  • thesnowman

    2019/08/23 02:31

    すみません!
    migrationファイルだと長くなるので、schema.rbを載せます。

    pictureテーブルはございません。

    @blog.picture とすると、@blogのpicture属性の値が取得できますよね。
    そして@blog.picture.urlとすると、画像URLが取得できますよね。

    そんな感じで、@blog.imagesから取得できないかなぁと考えております。

    キャンセル

  • mingos

    2019/08/23 10:31 編集

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

    キャンセル

回答 2

+1

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

rails consoleで登録してURL取得。

blog = Blog.create!
Image.create!(
  blog: blog,
  picture: open("tmp/sample.png")
)

blog.images.first.picture.url
=> "/uploads/image/picture/1/sample.png"
  • マイグレーション
class CreateBlogs < ActiveRecord::Migration[5.2]
  def change
    create_table :blogs do |t|
      t.timestamps
    end
  end
end

class CreateImages < ActiveRecord::Migration[5.2]
  def change
    create_table :images do |t|
      t.integer :blog_id, null: false
      t.string :picture
      t.timestamps
    end
  end
end
  • モデル
class Blog < ApplicationRecord
  has_many :images
end


class Image < ApplicationRecord
  belongs_to :blog
  mount_uploader :picture, PictureUploader
end
  • アップローダー
class PictureUploader < CarrierWave::Uploader::Base
  include CarrierWave::RMagick

  process resize_to_fit: [800, 800]

  version :thumb do
    process resize_to_fill: [200, 200]
  end

  storage :file

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_whitelist
    %w(jpg jpeg png)
  end

end

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/08/24 11:40

    ありがとうございます!

    違いがあるとすれば、私はマウントするためのメソッドを
    mount_uploaderではなくmount_uploadersというものを使っているんですよね。

    もしかしたら、そのせいかもしれません。

    キャンセル

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 などがあるかどうか。

2) pp @blog.images.first と pp @blog.images.first.picture の結果

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/08/24 11: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={}>


    大変お手数ですが、よろしくお願いいたします!

    キャンセル

  • 2019/08/24 11: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として使えないっぽいです!

    キャンセル

  • 2019/08/24 22:36

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

    キャンセル

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

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

関連した質問

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