How to make ActiveRecord query faster on production environment running multiple servers?

70 Views Asked by At

How could I rewrite the ActiveRecord query to solve this issue? Im a python programmer and use sqlalchemy, so it would be great if this could be explained from a python perspective. I really just need an idea of how to go about this problem.

I know the issue probably has to do with the connection being opened on every server, hence the slowness when run in production environment compared to single server staging environment. But I dont know how to go about this problem. I'm used to programming in python, where I use sqlalchemy, which is already optimized for this sort of distributed system.

class Board < ActiveRecord::Base
    def messages
        message_ids = Message.where("board_id = ?", self.id).map { |c| c.id }
        message_ids.map { |message_id| Message.find_by_id(message_id) }
    end
end

The ActiveRecord query is optimized to run on both multi-server production and single-server staging environments.

2

There are 2 best solutions below

6
Jay-Ar Polidario On BEST ANSWER

app/models/board.rb

class Board < ActiveRecord::Base
  has_many :messages
end

Above will allow you to do something like:

board = Board.first
board.messages
# => returns a `ActiveRecord::Associations::CollectionProxy` object
#    for beginners, simply treat `ActiveRecord::Associations::CollectionProxy` as
#    if that's an Array object. So you can still do something like

board.messages.first
# => #<Message id: 123, ...>
  • Now you'll also need to add below (but is not required to answer your question)

app/models/message.rb

class Message < ActiveRecord::Base
  belongs_to :board
end

...which will allow you to do:

message = Message.first
message.board
# => #<Board id: 456, ...>

See Rails association docs here

In particular, take note of "implied conventions", like implied foreign_key and class_name values

0
Violeta On

If I am not mistaken, what you're trying to do is select all messages for a particular board.

If that's correct, you can do something like this:

def messages
  Message.where(board_id: self.id)
end

This will retrieve all messages for a particular board.

Now, you can call this method for a board, for example like this:

board = Board.first
board.messages

For more informations, check this reference: https://guides.rubyonrails.org/active_record_querying.html

Hope this helps.