How do I get the data of a query join in ruby on rails

0

I have this query

@permiso = Permiso.joins(:importador).joins(:producto)

Now I need to get the data in variables to be able to work with them

Currently I get them this way, I need to know what is the right way to do it.

<% @permiso.each do |permiso| %>
   <%= permiso.id %>
   <%= permiso.fecha_emision %>
   <%= permiso.producto.nombre %>
   <%= permiso.importador.telefono %>
<% end %>
    
asked by Daniel-00000 09.10.2018 в 19:55
source

2 answers

0

I will assume that by "what is the correct way to do it? you mean the most effective from the point of view of memory usage and amount of queries to the database.

Answer: My recommendation would be:

@permisos = Permiso.includes(:importador, :producto).all

Why? The goal should be to make the minimum number of queries and save the minimum amount of data in memory.

When you do not use joins or includes and then use data from the associated tables in the view you'll be causing the famous N + 1 Query problem. That is, causing an additional query (or 2 in your case) for each associated data that you load in the view. This is especially serious the longer the list is. In your example, every time your each shows permission.product.name and permission.importer.phone> you would be hitting the database again. Unless you're doing Russian Doll Caching (I do not think that's the case) it's your worst scenario from a performance point of view.

When you do a joins as in your case, you will be filtering the permissions data that have importer and product associates. And the joins can use these tables to further refine your query. For example you could do:

@productos = Producto.joins(:importador).where(importador: {activo: true}) # La query es inventada obviamente porque no conozco tu tabla

joins uses the associated tables for the query, but does not load the information into memory. And it would be perfect if you DO NOT want to use that data later. But in your case you do use them and therefore you are NOT avoiding the N + 1 problem. This you can verify wind your logs.

We have the option of includes . Includes if you reduce the amount of queries and if it loads everything in memory. In your case you would have only 3 queries. It will undoubtedly be the best option from a performance point of view.

A couple of important clarifications:

  • If you only want to have permission results that have an importer and an associated product you should also add a joins to make sure you make an INNER JOIN
  • I changed the name of your variable to @permisos. I recommend using a plural whenever you have a collection of data to avoid confusion.
  • answered by 11.12.2018 в 20:23
    -2

    If what you want is to show the information as you have it in your example then it is not necessary to ask the joins.

    In fact you could do it in the following way and it would still work perfectly

    @permisos = Permiso.all

    And in the view exactly how you have it and you should not have any problem.

    In cases where you would be useful the join if you would have some conditional and only have the values of another of the tables, for example that would like to find the permission according to the importer and the product.

    @permiso = Permiso.joins(:importador, :producto).where(importador:{name:'Importador 1'}, producto:{precio:'15'})

        
    answered by 01.11.2018 в 22:18