отладка активного ресурса - PullRequest
6 голосов
/ 05 марта 2012

Я пытаюсь заставить активный ресурс (на Rails 3.2) работать с Freebase API, и мне пока не очень повезло. Как я могу отладить рельсы, чтобы увидеть, что происходит, и убедиться, что запрос правильно сформирован?

Я думаю, что суффикс .json вызывает ошибку, но я не знаю, как проверить, что происходит?

Ошибка:

ActiveResource::ResourceNotFound: Failed.  Response code = 404.  Response message = Not Found.

Код:

class Freebase < ActiveResource::Base
  class << self # also tried without this, same result
    def element_path(id, prefix_options = {}, query_options = nil)
      prefix_options, query_options = split_options(prefix_options) if query_options.nil?
      "#{prefix(prefix_options)}#{collection_name}/#{id}#{query_string(query_options)}"
    end

    def collection_path(prefix_options = {}, query_options = nil)
      prefix_options, query_options = split_options(prefix_options) if query_options.nil?
      "#{prefix(prefix_options)}#{collection_name}#{query_string(query_options)}"
    end
  end


  self.site = "https://www.googleapis.com/freebase/v1/"
  self.format = :json

  #https://www.googleapis.com/freebase/v1/search?query=nirvana&indent=true

  #Freebase.get('search', :query => 'nirvana')



end

UPDATE:

Хорошо, я обнаружил, что две вещи идут не так ...

1) Сборник-путь, который я пытаюсь заменить, не работает вообще ... он все еще привязывает .json к каждому запросу. 2) https://www.googleapis.com:443/freebase/v1/freebases/search.json?query=nirvana После этого он использует FreeBase ... есть идеи?

Я также пытался это исправить:

Удалить расширение .xml из запроса ActiveResource

Но он также не удалил суффикс JSON.

ОБНОВЛЕНИЕ ОБНОВЛЕНИЕ:

Добавлено ниже предлагаемое обновление, которое дает правильный путь, но теперь я получаю

GET https://www.googleapis.com:443/freebase/v1/search/?query=monkey
--> 200 OK 2732 (693.3ms)
NoMethodError: undefined method `collect!' for #<Hash:0x007f9bde674900>

Ответы [ 6 ]

17 голосов
/ 09 марта 2012

Добавьте ActiveResource::Base.logger = Logger.new(STDERR) в ваш config / application.rb (Rails 3.x).

Вы получите вывод как:

POST http://localhost:3000/freebase.json
--> 201 Created 0 (15.8ms)

Это показывает метод и код ответа ...

4 голосов
/ 10 марта 2012

ActiveResource не умер, но по отношению к ActiveRecord я могу понять, почему вы так думаете, это определенно нелюбимый и обездоленный пасынок.

Возможно, вам лучше использовать что-то вроде Faraday_Middleware илиHTTPParty.Первое мое личное предпочтение.Если вы не извлекаете данные из другого Rails-приложения или приложения с идеальным спокойным поведением, такого как Rails (чего нет у Freebase), ActiveResource обычно доставляет больше хлопот, чем стоит.

Сказав это, вы можетеВыполните то, что вы хотите, не переписывая методы класса, выполнив:

  self.site = "https://www.googleapis.com/"
  self.format = :json

  def self.search(word)
    self.find(:all, :from => "/freebase/v1/search/", :params => { :query => word })
  end
1 голос
/ 14 марта 2012

NoMethodError: undefined method 'collect!' for #<Hash:0x007f9bde674900> Кажется, ошибка на рельсах https://github.com/rails/rails/issues/2318. У меня была похожая проблема, но предоставленные хаки не работали, поэтому мне пришлось немного их настроить, вы можете найти мой ответ здесь .

1 голос
/ 14 марта 2012

ActiveResource имеет довольно узкий вариант использования.Возможно, вы захотите использовать более общий интерфейс для работы с Freebase.

Некоторый код из API FreeBase платформы *1003* может быть полезен.

1 голос
/ 14 марта 2012

ActiveResource ожидает, что эта конечная точка вернет данные в очень специфическом формате.

Долгое время мы использовали ActiveResource в моей компании для взаимодействия между приложениями. Однако в последнее время мы начали склоняться к HTTParty, потому что он выполняет намного меньше магии вуду и, как правило, является очень небольшим упражнением в выдергивании волос.

Вот пример того, как мы сейчас используем HTTParty:

module CoreResources
  class Job
    include HTTParty
    base_uri Rails.configuration.core_resource_uri
    basic_auth Rails.configuration.core_resource_user, Rails.configuration.core_resource_password

    def self.search(entity)
      get("/api/v1/jobs.json", :query => {:entity_id => entity.id})
    end

    def self.find(id)
      result = get("/api/v1/jobs/#{id}.json")
      raise CoreResources::JobNotFound.new if result.response.code == "404"
      raise "Unexpected response from resource job find: #{result.response.code} #{result.response.to_s}" if result.response.code =~ /^(?:4|5)..$/
      result
    end
  end
end

Проблема с ActiveResource заключается в том, что он берет очень специально созданную разметку json или xml и создает на ее основе объекты ActiveResource и вложенные объекты. У него возникают проблемы с вызовом collect, потому что что-то в ответе json должно было быть отформатировано как перечислимое, а не (вероятно, родительский узел должен был быть массивом или чем-то, не уверен), что заставляет его взрываться.

С HTTParty вы получаете для работы коллекцию, проанализированную json.

Мне достаточно легко сделать это:

jobs = CoreResources::Job.search(my_entity)
puts jobs.inspect

# [{
#    "id" => 4,
#    "created_by_id" => 12,
#    "description" => "I like pie"
# },
# {
#    "id" => 5",
#    "created_by_id" => 12,
#    "description" => "Mmm, cake"
# }]

Который позволяет мне получать доступ к заданиям через простой массив / хэш-конструкцию jobs[0].fetch("description"), в отличие от ActiveResource: jobs[0].description. ActiveResource медленнее уничтожает эти коллекции, излишне забирает у них память и рекомендует вам дублировать код, который должен обслуживаться только конечной точкой в ​​вашей модели ActiveResource (опять же, если вы используете сторонний API, вы можете иметь другого выбора нет, но я никогда не получал ARes для взаимодействия со сторонними API).

Мы столкнулись с множеством других проблем ActiveResource, когда он выполняет бессмысленное динамическое создание имен классов на основе вложенных ресурсов с вашей конечной точки, но половину времени делает это неправильно ... Это действительно просто беспорядок.

Мораль истории: гораздо больше поклонника HTTParty сейчас. Эта конечная точка, вероятно, просто не возвращает данные в правильном формате, и если это не так, ActiveResource станет хакфестом, чтобы заставить его правильно читать.

0 голосов
/ 07 января 2019

enter image description here

Чтобы получить подробные данные для входа в систему для ActiveResource необходимо пропатчить метод запроса внутри гема ( method .

поместите приведенные ниже файлы внутрь config/initializers, вы получите http метод, путь, тело запроса, хедеры запроса

тело ответа и заголовок уже есть, есливам нужно. doc

config / initializers / activeresource_patch.rb

module ActiveResource
  class Connection
    private
      def request(method, path, *arguments)
        result = ActiveSupport::Notifications.instrument("request.active_resource") do |payload|
          payload[:method]      = method
          payload[:request_uri] = "#{site.scheme}://#{site.host}:#{site.port}#{path}"
          payload[:request_path] = path
          payload[:request_body] = arguments[0]
          payload[:request_headers] = arguments[1]
          payload[:result]      = http.send(method, path, *arguments)
        end
        handle_response(result)
      rescue Timeout::Error => e
        raise TimeoutError.new(e.message)
      rescue OpenSSL::SSL::SSLError => e
        raise SSLError.new(e.message)
      end
  end
end

config / initializers / activeresource_logger.rb

Rails.application.configure do

  def activeresource_logger
  @activeresource_logger ||= Logger.new("#{Rails.root}/log/activeresource_logger.log")
  end

  ActiveSupport::Notifications.subscribe('request.active_resource')  do |name, start, finish, id, payload|
   if Rails.env.development?
    activeresource_logger.info("====================== #{start} : #{payload[:method].upcase} ======================")
    activeresource_logger.info("PATH: #{payload[:request_path]}")
    activeresource_logger.info("BODY: #{payload[:request_body]}")
    activeresource_logger.info("HEADERS: #{payload[:request_headers]}")
    # activeresource_logger.info("STATUS_CODE: #{payload[:result].code}")
    # activeresource_logger.info("RESPONSE_BODY: #{payload[:result].body}")
   end
  end

end
...