[英]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.