2013-05-22 4 views
3

Я получаю NoMethodErrors, когда работает мой DeltaSynWorker. Это происходит в приложении, которое было создано как ревизия действующего в настоящее время приложения. Я не являюсь оригинальным программистом, и я прихожу к нему с фона Java (я упоминаю об этом, потому что возможно, что я пропускаю что-то очень очевидное для других). Я не могу понять, почему NoMethodeError бросается, когда код очень похож на код, который в настоящее время отлично работает в другом веб-приложении.Rails - NoMethodError

Ошибка:

NoMethodError: undefined method `client' for #<ApiRequestBuilder:0x0000000705a8f0> 

delta_sync_worker.rb

class DeltaSyncWorker < SyncWorker 

    include Sidekiq::Worker 
    sidekiq_options queue: "delta_syncs" 

    def perform(subscriber_id, client_id) 

     sleep(10) 
     current_subscriber = ApiSubscriberDecorator.decorate(Subscriber.find(subscriber_id)) 
     Time.zone = current_subscriber.time_zone 
     client = ApiClientDecorator.decorate(Client.find(client_id)) 
     arb = ApiRequestBuilder.new(URI.parse(SR_HOST + '/servlet/sync/process')) 

     if arb.client(:subscriber => current_subscriber, :client => client) 

     arb.transmit 

     if arb.success? 
      current_subscriber.touch(:sync_updated_at) 
      decorated_client = ClientDecorator.decorate(client.model)   
      ConfirmationsSyncWorker.perform_in(1.hours, current_subscriber.id) 
     else 
      error_params = {:subscriber => current_subscriber.id, :response_body =>   arb.response.body, :request_body => arb.request.body, :sync_type => "DeltaSyncWorker"} 
      Airbrake.notify(:error_class => "sync_error", :error_message => "Sync Error: #{arb.response.message}", :params => error_params) 
     end 
     end 
    end 
    end 

api_request_builder.rb

require 'nokogiri' 
class ApiRequestBuilder < AbstractController::Base 
    include AbstractController::Rendering 
    include AbstractController::Layouts 
    include AbstractController::Helpers 
    include AbstractController::Translation 
    include AbstractController::AssetPaths 

    self.view_paths = "app/api" 

    attr_accessor :request_body, :request, :response, :append_request_headers, :request_method, :url 

    def initialize(url, *args) 
    @url = url 
    if args 
     args.each do |arg| 
     arg.each_pair{ |k,v| instance_variable_set("@#{k.to_s}", v) } 
     end 
    end 
    end 

    # this will search for an api request template in api/requests, render that template and set any instance variables 
    def method_missing(meth, *args, &block) 

    if lookup_context.template_exists?("requests/#{meth.to_s}") 

     if args 
     args.each do |arg| 
      arg.each_pair{|k,v| instance_variable_set("@#{k.to_s}", v) } 
     end 
     end 

     @request_body = (render :template => "requests/#{meth.to_s}") 
    else 
     super 
    end 

    end 

    def transmit 
    @request_method ||= "Post" 
    @request = "Net::HTTP::#{@request_method}".constantize.new(@url.path) 
    @request['x-ss-user'] = @subscriber.sr_user if @subscriber &&  @subscriber.sr_user.present? 
    @request['x-ss-pwd'] = @subscriber.sr_password if @subscriber && @subscriber.sr_password.present? 

    unless @append_request_headers.nil? 
     @append_request_headers.each_pair{ |k,v| @request[k] = v } 
    end 
    @request.body = @request_body if request_body? && @request.request_body_permitted? 

    @http = Net::HTTP.new(@url.host, @url.port) 
    @http.use_ssl = true 
    @http.verify_mode = OpenSSL::SSL::VERIFY_NONE 
    @response = @http.request(@request) 

    end 

    def success? 
    if @response.code == 200.to_s 
     return true 
    else 
     return false 
    end 
    end 

    def request_body? 
    unless @request_body.nil? 
     return true 
    else 
     return false 
    end 
    end 
end 

Я смотрел на другие вопросы NoMethodError, но я не могу найти ответ, который, как мне кажется, относится к моей ситуации. Любая помощь приветствуется. Благодаря!

ответ

1

method_missing поймает отправленные сообщения, для которых не существует никакого способа определить, и призыв к super в конце будет проходить его до стандартного method_missing поведения Руби, которая является то, что вы видите (NoMethodError). Однако это происходит только в том случае, если условие if не выполняется, что, как я подозреваю, происходит здесь, и объясняет, почему он работает в некоторых ситуациях, но не в других. Вызов :client, не найдя подходящих методов вдоль цепочки наследования, будет искать шаблон под названием «запросы/клиент» - попробуйте добавить этот шаблон и посмотреть, устраняет ли это проблему.

+0

Хорошо, я следую тому, что вы говорите. В пути «api/requests /» существует как шаблон «_client.xml.api», так и шаблон «client.xml.api». Возможно, что-то не так с самим шаблоном? – s0dz

+0

Может быть. Я бы попробовал добавить некоторые 'puts' -процессы внутри' method_missing', чтобы вы могли наблюдать управление потоком, т. Е. Шаблон 'puts 'существует' 'в' '' '' '' '' '' и шаблон 'puts' не найден '' в 'else' , –

+0

А, ок. Отличная идея. Я попробую это. Благодаря! – s0dz

1

Я знаю, что я видел это раньше, и я чувствую, что это было не то, что казалось, но, в основном, отсутствует метод, просто перехватывает вызов метода, а когда вы вызываете arb.client, он улавливается отсутствующим методом и поэтому пытается отобразить api/client.xml.arb или api независимо от типа файла. - Обратите внимание, что в каталоге инициализаторов должен быть файл с именем somethig, например api_template_handler.rb или arb_temmplate_handler.rb, что позволяет рельсам видеть этот тип шаблона в каталоге представления - убедитесь, что он существует первым. Также Sidenote, _client.xml.api частичный используется другой запрос АФИ в этой директории (полная синхронизация),

Для отладки Id начать, над следующей строкой

if lookup_context.template_exists?("requests/#{meth.to_s}") 

Добавить заявление журнала

Если значение true, тогда проблема заключается в ошибке не попадает должным образом из-за отсутствия метода. Если false, то рабочий sidekiq неправильно загружает направляющие, или путь просмотра не добавляется в пути просмотра рельсов.

Если это правда, я предполагаю, что это может иметь какое-то отношение к не загруженной клиентской модели или атрибут на не существующей клиентской модели, которую пытается вызвать строитель, и ошибка каким-то образом вздымается до api query builder class.

О, также, просто общие вещи, но убедитесь, что redis и sidekiq работают, и перезапустите пассажир, если это не местная среда.

Сообщите мне, как это.

+0

Несмотря на то, что я добавляю эту строку (а также помещая похожие записи журналов в разные места), я фактически не был свидетелем выхода в production.log. Я подтвердил, что redis и sidekiq работают, и я перезапустил пассажира через: 'touch/webapps/rackapp/tmp/restart.txt' Я вижу, как работник в Sidekiq пытается обработать задание, но затем не работает и идет в очередь повторов. – s0dz

+0

Для того, что стоит, я также попробовал следующее в консоли Rails в рабочей среде на рабочем сервере: 'RAILS_ENV = производственный пакет exec rails console', затем ' include ActionView :: LookupContext :: ViewPaths' then ' helper.lookup_context.template_exists? ("request/client.xml.api") ' Что дало: ' => false' – s0dz