[英]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_name
和AppName
替換為我正在使用的實際名稱)我當前的應用):
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.parse
或response
或.execute
信息,也不需要了解Google::Calendar::ListService.call(current_user: current_user)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.