繁体   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