Запрос части модели Rails с URL - PullRequest
0 голосов
/ 09 марта 2019

У меня есть модель Rails под названием Tasks, которая имеет только один атрибут: resource_id. Это относится к идентификатору Resource (другая модель) на другом сайте Rails, работающем по другому URL-адресу с другой базой данных.

Когда вы запрашиваете Resource (например, http://localhost:3020/resources/23.json), он возвращает ресурс в формате JSON, например:

{
  "title": "Hello",
  "description": "Lorem ipsum..."
}

Я хочу иметь возможность ссылаться на запрошенный ресурс на моем текущем веб-сайте Rails (с Task) следующим образом:

# returns a Task with `resource_id: 23`
@task = Task.find(1)

# refers to the Resource from the other Rails server
@task.resource.title

Как я могу заставить Rails получать Resource в то же время, когда он находит Task из локальной базы данных?

Я попытался создать атрибут resource в task.rb, который запрашивает Resource, когда он вызывается так:

require 'net/http'

class Task < ApplicationRecord
  def resource
    res = Net::HTTP.get(URI.parse('http://localhost:3020/resources/' + resource_id.to_s + '.json'))
    JSON.parse(res)
  end
end

Однако, это выполняется каждый раз Я звоню task.resource, что очень медленно. Могу ли я просто запросить Resource один раз и сохранить его локально в каком-то псевдоатрибуте (я не знаю, как он называется)?

Ответы [ 3 ]

1 голос
/ 09 марта 2019

Запрос всего содержимого таблицы внешней базы данных не является эффективным.Но вы можете добавить кеширование для вашего контроллера:

например, вы можете использовать кеширование с redis:

require 'net/http'

class Task < ApplicationRecord
  def resource
    res = $redis.fetch(:resource, expires_in: 1.hour) do
      Net::HTTP.get(URI.parse('http://localhost:3020/resources/' + resource_id.to_s + '.json'))
      JSON.parse(res)
    end
  end
end
0 голосов
/ 09 марта 2019

Вот как я решил свой вопрос:

Во-первых, добавьте строковый атрибут к Task с именем resource_string.

task.rb

require 'net/http'

class Task < ApplicationRecord
  def resource
    JSON.parse(resource_string)
  end

  after_find do |task|
    task.resource_string = request_resource task
  end

  private

  def request_resource(task)
    Net::HTTP.get(URI.parse('http://localhost:3020/resources/' + task.resource_id.to_s + '.json'))
  end
end

Затем вы можете получить доступ к ресурсу следующим образом:

@task = Task.find(1)
@task.resource['title']

Он сделает запрос только один раз и запишет его в атрибут resource_string после вызова метода find.

0 голосов
/ 09 марта 2019

Вам необходимо добавить ассоциацию к Задачам и Ресурсам:

в task.rb:

  has_many: :resources

в resource.rb:

  belongs_to: :task

Эти ассоциацииавтоматически добавлять методы, такие как метод ресурсов, в модели: https://guides.rubyonrails.org/association_basics.html

Затем в действии вашего контроллера используйте: include для объединения двух таблиц:

@tasks = Task.includes(:resource)

См. здесь: https://apidock.com/rails/ActiveRecord/QueryMethods/includes

и здесь для объяснения: https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...