PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Friday, October 21, 2022

[FIXED] how to retrieve data from the database using the has_many association

 October 21, 2022     has-many, ruby-on-rails, ruby-on-rails-5     No comments   

Issue

I have

message table

and

message_pictures

table(It belongs to the message table) and what I want to do is retrieve each messsge pictures (if there is any) from the

message_controller

.

How can I do it. I have surfed the web but found little scanty explanations on it.

This is the message class(model)

class Message < ApplicationRecord
  belongs_to :user
  has_many :message_pictures, dependent: :destroy
  accepts_nested_attributes_for :message_pictures
end

This is the message_pictures class(model)

class MessagePicture < ApplicationRecord
  belongs_to :message, optional: true
  mount_uploader :message_pictures, PictureUploader
end

and this is the index method of the message_controller class

def index
    @user = User.find(current_user.id)#414, 449, 494
    @messages = @user.messages.paginate(page: params[:page])
    #@messages = @messages.message_pictures.paginate(page: params[:page])
end

You can see the line 4 of the index method to see the way I did mine but its not working


Solution

I believe what you need is has_many ... :through

app/models/user.rb

class User < ApplicationRecord
  # ...
  has_many :messages, dependent: :destroy
  has_many :message_pictures, through: :messages
end

app/controllers/messages_controller.rb

class MessagesController < ApplicationController
  # ...

  def index
    @user = User.find(current_user.id)
    @messages = @user.messages.paginate(page: params[:page])
    @message_pictures = @user.message_pictures
  end
end

has_many ... :through simplifies the retrieving of "nested" children records via "SQL JOINS", of which normally you would have done it in a longer (more explicit way) like the following (which also works):

class MessagesController < ApplicationController
  # ...

  def index
    @user = User.find(current_user.id)
    @messages = @user.messages.paginate(page: params[:page])
    @message_pictures = MessagePicture.joins(message: :user).where(
      messages: { # <-- this needs to be the table name, and not the association name, and is why it is in plural form
        users: { # <-- this needs to be the table name, and not the association name, and is why it is in plural form
          id: @user.id
        }
      }
    )
  end
end

Update: Alternative Solution

Looking back at your question, I have a feeling you'd only want @message_pictures that corresponds to @messages and not to all@user.messages, because I noticed you have pagination for the messages. I'll do it like this instead:

app/controllers/messages_controller.rb

class MessagesController < ApplicationController
  # ...

  def index
    @user = User.find(current_user.id)

    # the `includes` here prevents N+1 SQL queries, because we are gonna loop
    # through each `message_picture` in each `message` record (see index.html.erb below)
    @messages = @user.messages.includes(:message_pictures).paginate(page: params[:page])
  end
end

app/views/messages/index.html.erb (example)

<h1>Messages:</h1>
<% @messages.each do |message| %>
  <section>
    <h2>Message:</h2>
    <p><%= message.content %></p>

    <h3>Message Pictures:<h3>
    <div>
      <% message.message_pictures.each do |message_picture| %>
        <% message_picture.message_pictures.each do |message_picture_attachment| %>
          <%= image_tag message_picture_attachment.url.to_s %>
        <% end %>
        <br>
      <% end %>
    </div>
  </section>    
<% end %>

^ Above assumes MessagePicture is using carrierwave. P.S. It looks to me there's something wrong with how you defined your models, because your message has many message_pictures, while each of the message_picture also has many attached message_picture carrierwave attachments (assuming you used the "multiple-file" upload set up for carrierwave because you used mount_uploader :message_pictures, PictureUploader instead of mount_uploader :message_picture, PictureUploader. The model problem I think is because it's like this: message < message_pictures < message_pictures attachments, but (depending on your use-case), it should probably be just like message < message_pictures - message_picture attachment, or just simply message < message_pictures attachments



Answered By - Jay-Ar Polidario
Answer Checked By - Katrina (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing