Skip to content

Instantly share code, notes, and snippets.

@coderberry
Created June 1, 2023 15:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coderberry/1b3fcca27e9fba4d5e3d0c61f90eb012 to your computer and use it in GitHub Desktop.
Save coderberry/1b3fcca27e9fba4d5e3d0c61f90eb012 to your computer and use it in GitHub Desktop.
ChatGPT explains how to avoid using `send`

Prompt

I have a Rails app with two models that are associated:

class Person < ApplicationRecord
  has_many :pets
  has_many :toys
end

class Pet < ApplicationRecord
  belongs_to :person
end

I want to fetch an instance variable in Pet from an instance of Person, however I am using metaprogramming to do this. I am using the following code:

    <% if form.object.send(association).present? %>
      <%= image_tag form.object.send(association).send(preview_url_attribute), class: options[:image_classes] %>
    <% end %>

In the above example, form.object is an instance of Person. association is the name of the association between A and B (e.g. :pets), and preview_url_attribute is the name of the attribute in Pet that I want to fetch (e.g. :breed).

Is there a better way to do this without using send?

ChatGPT Response

Yes, there is a more concise and readable way to fetch the desired attribute in the associated model without using send. Instead, you can leverage the association methods provided by ActiveRecord associations.

Assuming you have the following code:

class Person < ApplicationRecord
  has_many :pets
  # ...
end

class Pet < ApplicationRecord
  belongs_to :person
  # ...
end

And you want to fetch the preview_url_attribute from the associated pets in the Person model.

You can simplify the code in the view as follows:

<% if form.object.association(association).loaded? && form.object.association(association).any? %>
  <%= image_tag form.object.association(association).first.public_send(preview_url_attribute), class: options[:image_classes] %>
<% end %>

Here's what changed:

  1. Instead of using send(association) to fetch the associated records, you can use association(association) provided by ActiveRecord associations. This method returns an instance of ActiveRecord::Associations::CollectionProxy, which provides access to the associated records.

  2. The loaded? method checks if the association has been loaded. This ensures that the associated records are fetched only if they are already loaded, avoiding additional queries.

  3. The any? method checks if there are any associated records present. This ensures that the code block is executed only when there are associated records available.

  4. Finally, first is used to fetch the first associated record, and public_send(preview_url_attribute) is used to retrieve the value of the desired attribute.

By using the association and the methods provided by ActiveRecord associations, you can achieve the desired result in a more readable and idiomatic way without relying on send.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment