no meu aplicativo ruby on rails, quando altero meu código (por exemplo, altere a linha 5 de i = f1
para i = f2
recebo este erro:
NoMethodError in Api::V1::AppController#login
undefined method `f2' for #Master::Utilities:0x00007fdb6ceb42c8
este é o meu código
class Api::V1::AppController < ApplicationController
def login
c = Master::Utilities.new
i = c.f1
z = c.f2
render json: {m: 'login' , msg: "hello" , data: "#{z} - #{i}" } , status: :ok
end
end
desfazer a alteração não resolve o problema. depois de receber esse erro, reinicio o Puma e tudo fica bem novamente sem alterar o código.
esses são meus códigos
lib\master\utilities.rb
module Master class Utilities Dir[File.join(__dir__, 'code', '*.rb')].each { |file| require file } end end
lib\master\código\1.rb
module Master class Utilities def f1 "Function 1" end end end
lib\master\código\2.rb
module Master class Utilities def f2 "Function 2" end end end
Eu uso este código para config\application.rb
carregar automaticamente meu código
config.paths.add Rails.root.join('lib').to_s, eager_load: true
Sou novo no ruby on rails e acho que tenho um pequeno erro no meu código, mas não consigo descobrir onde.
obrigado
O que está errado aqui é que, quando você edita o arquivo, o rails vê a chamada
Master::Utilities.new
e recarrega a definição deMaster::Utilities
. Mas quando chega a esta parte:...Veja que, por exemplo, já
lib/master/code/1.rb
foi carregado . (require
não recarrega arquivos que já estão carregados!).Portanto, nenhuma das definições de método está sendo definida e, portanto, efetivamente você acaba com uma
Master::Utilities
classe sem métodos de instância.Uma correção rápida e mínima seria substituir o acima
require
porload
, para dizer explicitamente "sempre carregue o arquivo, mesmo que tenha sido carregado antes":No entanto, gostaria de apontar que esta é uma maneira muito incomum de estruturar o código em ruby/rails; e você provavelmente se beneficiaria mais seguindo uma abordagem mais convencional.
Que benefício/lógica existe em dividir a definição de uma única classe em vários arquivos? Se você quiser procurar onde um método está definido, não seria mais fácil tê-los todos em um só lugar ou dividi-los em módulos lógicos ?
Se você seguir a convenção de "apenas definir a classe em um local e fazer com que o nome da classe corresponda ao nome do arquivo", o carregamento antecipado em trilhos funcionará sem problemas imediatamente. Por exemplo, talvez você possa fazer:
Ou:
Ou se você realmente deseja ter todos os métodos em uma classe enorme, com carregamento automático de todos os arquivos em uma pasta (mesmo que isso pareça muito desorganizado para mim!), Você pode escrever alguma metaprogramação - por exemplo, usando para converter os nomes de arquivo
String#classify
para seus nomes de módulo.