簡體   English   中英

Ruby on Rails:未初始化的常量

[英]Ruby on Rails: Uninitialized Constant

我有一個關於從Ruby on Rails項目中的控制器訪問自定義類的問題。

我正在遵循有關將Google Calendar API與我的Rails應用程序集成的教程 ,本節的一部分是創建GoogleCalendarWrapper 我在lib/google_cal_wrapper.rb創建了此文件,但是出現錯誤:

uninitialized constant EventsController::GoogleCalWrapper

這是我在events_controller代碼

  def index
    if user_signed_in?
      @event = current_user.posts.build
      @calendar = GoogleCalWrapper.new(current_user)

      # response = @client.execute(api_method: @service.calendar_list.list)
      # calendars = JSON.parse(response.body)
      # puts(calendars)
    #  @places = Classroom.all.map { |x| x.name }
    else
      @event = Event.new
    end
end

-

#lib/google_cal_wrapper.rb
class GoogleCalWrapper
  def initialize(current_user)
    configure_client(current_user)
  end
  def configure_client(current_user)
    @client = Google::APIClient.new
    @client.authorization.access_token = current_user.token
    @client.authorization.refresh_token = current_user.refresh_token
    puts @client.authorization.refresh_token
    @client.authorization.client_id = ENV['GOOGLE_KEY']
    @client.authorization.client_secret = ENV['GOOGLE_SECRET']
    @client.authorization.refresh!
    @service = @client.discovered_api('calendar', 'v3')

  end
end

-一些額外的信息:

`

#omniauth_callbacks_controller.rb
  def google_oauth2
    @user = User.from_omniauth(request.env["omniauth.auth"])
    if @user.persisted?
      sign_in_and_redirect @user
    else
      session["devise.google_data"] = request.env["omniauth.auth"].except("extra")
      redirect_to root_path
    end
  end

#user.rb
  def self.from_omniauth(auth)
    user = where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      user.email = auth.info.email
      user.first_name = auth.info.first_name
      user.last_name = auth.info.last_name
      user.avatar = auth.info.image # assuming the user model has an image
    end
    user.token = auth.credentials.token
    user.refresh_token = auth.credentials.refresh_token
    if user.valid?
      puts "#{user} saved"
    else
      puts user.errors.full_messages
    end
    return user
  end

我不太喜歡此類的Wrapper名稱,但是,這不是重點。

如果您是我,我會在app下放置一個wrappers文件夾,然后在該文件夾中放置google_cal_wrapper.rb 因此,您最終得到:

app
 |- assets
 |- controllers
 |- ...
 |- wrappers
     |- google_cal_wrapper.rb

這樣,它應該像GoogleCalWrapper一樣自動加載並在您的控制器中GoogleCalWrapper

順便說一句,在我使用google-api-client (和其他api客戶端)的項目中,我將這類services稱為“東西”,並且目錄結構類似於(自然地,將app_nameAppName替換為我正在使用的實際名稱)我當前的應用):

app
 |- assets
 |- controllers
 |- ...
 |- services
 |   |- app_name
 |   |   |- service_base.rb
 |   |- google
 |   |   |- calendar
 |   |   |   |- list_service.rb
 |   |   |- calendar_service.rb
 |   |   |- client_service.rb
 |   |   |- service_base.rb
 |   |- quickbooks
 |   |  |- consumer_service.rb
 |   |  |- service_base.rb
 |   |- ...
 |- ...

我的課程如下所示:

class AppName::ServiceBase

  attr_accessor *%w(
    args
  ).freeze

  # allows you to call Google::Service.call(current_user: current_user)
  # without having to do Google::Service.new(current_user: current_user)
  # which I prefer.
  class << self
    def call(args={})
      new(args).call
    end
  end # Class Methods

  #==================================================================================
  # Instance Methods
  #==================================================================================

    def initialize(args={})
      @args = args
      assign_args
    end

  private

    # creates an attr_accessor for each k,v pair in args. So,
    # for instance, when called like 
    # Google::Service.call(current_user: current_user),
    # the new service instance will have a method called
    # 'current_user' that returns the current_user
    def assign_args
      args.each do |k,v| 
        class_eval do 
          attr_accessor k
        end
        send("#{k}=",v)
      end
    end    

end

Google類的基類:

class Google::ServiceBase < AppName::ServiceBase

  private

    def client
      @client ||= Google::ClientService.call(current_user: current_user)
    end

    def calendar_service
      @calendar_service ||= Google::CalendarService.call(current_user: current_user)
    end

end

一個配置calendar_service的類

class Google::CalendarService < Google::ServiceBase

  #==================================================================================
  # Instance Methods
  #==================================================================================

    def call
      client.discovered_api('calendar', 'v3')
    end

end

用於配置Google客戶端的類

class Google::ClientService < Google::ServiceBase

  delegate *%w(
    token
    refresh_token
  ), to: :current_user

  #==================================================================================
  # Instance Methods
  #==================================================================================

    def call
      [
        :token,
        :refresh_token,
        :client_id 
        :client_secret
      ].each do |client_attribute|
        client.authorization.send("#{client_attribute}=", send(client_attribute))
      end
      client.authorization.refresh!      
      client
    end

  private

    def client 
      @client ||= Google::APIClient.new
    end

    def client_id
      ENV['GOOGLE_CLIENT_ID']
    end

    def client_secret
      ENV['GOOGLE_CLIENT_SECRET']
    end

end

用於獲取calendars_list的類

class Google::Calendar::ListService < Google::ServiceBase

  #==================================================================================
  # Instance Methods
  #==================================================================================

    def call
      # do some stuff like you have commented out in your controller
      # like (naturally, insert code that actually works):
      calendar_service.calendar_list.list
    end

end

因此,您可以在controller

def index
  if user_signed_in?
    @event = current_user.posts.build
    @calendar_list = Google::Calendar::ListService.call(current_user: current_user)
  else
    @event = Event.new
  end
end  

現在,您的控制器不需要了解任何有關JSON.parseresponse.execute信息,也不需要了解Google::Calendar::ListService.call(current_user: current_user)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM