gpt4 book ai didi

ruby-on-rails - 遇到 Ruby mixin 模块的规范问题

转载 作者:太空宇宙 更新时间:2023-11-03 17:44:45 24 4
gpt4 key购买 nike

我对 mixin 模块没有很好的经验。那么,如果我的问题显得有些幼稚,请见谅。

我正在创建一些模块来将项目与具有 REST API 的音乐服务(如 Spotify)集成。所有这些模块都包括我创建的另一个名为 APIClientBuilder 的混合模块,它提供了一个用于创建 API 端点的小型 DSL。

lib/integrations/api_client_builder.rb

require 'rest-client'

module APIClientBuilder

attr_accessor :api_client, :endpoint, :url, :param

def api_client(api_name)
end

def fetch_client(api_name)
end

def api_endpoint(endpoint_name)
end

def fetch_endpoint(api_name,endpoint_name)
end

def method=(meth)
end

def url=(endpoint_url)
end

def param(param_name,param_value)
end

def call(api_name,api_endpoint,token,*extra_params)
end

end

lib/integrations/spotify.rb

require_relative 'api_client_builder'

module SpotifyIntegration

include APIClientBuilder

def base_url
'https://api.spotify.com/v1'
end

def random_state_string
(0..10).map { (65 + rand(26)).chr }.join
end

api_client('spotify') do |apic|

apic.api_endpoint('request_authorization') do |ep|
ep.method = :get
ep.url = "https://accounts.spotify.com/authorize"
ep.param("client_id",SPOTIFY_KEY)
ep.param("response_type","code")
ep.param("redirect_uri","http://localhost:3000")
end

apic.api_endpoint('my_playlists') do |ep|
ep.method = :get
ep.url = "#{base_url}/me/playlists"
end

end

end

我的想法是在我的 Controller 中加入这样的东西:

app/controllers/api/v1/users_controller.rb

require 'integrations/spotify.rb'

class UsersController < ApplicationController

include SpotifyIntegration

end

然后可以访问 SpotifyIntegration 中的方法,并通过它访问 APIClientBuilder 中的方法。

碰巧我用一个非常简单的测试编写了以下规范文件:

spec/lib/integrations/spotify_integration_spec.rb

require 'rails_helper'

require 'integrations/spotify'

class SpotifyClientTester
include SpotifyIntegration
end

RSpec.describe SpotifyIntegration do

context 'Auxiliary methods' do

it 'Two calls to random_state_string shall generate two different strings' do
obj = SpotifyClientTester.new
s1 = obj.random_state_string
s2 = obj.random_state_string
expect(s1).not_to eq(s2)
end

end

end

但是当我运行它时我得到了

undefined local variable or method base_url for SpotifyIntegration:Module (NameError)

我不确定我错过了什么。也许我应该使用 extend 而不是 include。我总是对此感到困惑。

有人可以让我走上正确的道路吗?整个下午我都在与这个错误作斗争。

最佳答案

你在滥用 mixins。在经典继承不适合向对象添加一组功能的情况下使用混合。

例如:

module Commentable
extend ActiveSupport::Concern

included do
has_many :comments, as: :commentable
end
# ...
end

class Video < ApplicationRecord
include Commentable
end

class Hotel < ApplicationRecord
include Commentable
end

正如您在这个例子中看到的,您用其他模块扩展 一个模块,并在类中包含 模块。使用经典继承来添加共享行为充其量是尴尬的,因为这两个类是苹果和梨。

在您的特定情况下,您应该改为使用经典继承,而不是将 API 客户端混入 Controller 中。相反,您的 Controller 应该将其作为一个独特的对象来调用。

class APIClient
# Implement shared behavior for a REST api client
end

class SpotifyClient < APIClient
# ...
end

class FoosController < ApplicationController
def index
client = SpotifyClient.new
@foos = client.get_something
end
end

为什么不应该将 API 客户端混合到 Controller 或模型中?由于单一职责原则以及使用较小的部分做有限数量的事情比创建上帝类更可取的事实。

关于ruby-on-rails - 遇到 Ruby mixin 模块的规范问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42380460/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com