[英]NoMethodError (undefined method) from Private method in class
為什么我不能在課堂上使用私有方法? 如何修復我的代碼以防止錯誤?
module CarRegistration
class Basics < Base
fields_of_model(:car).each do |attr|
delegate attr.to_sym, "#{attr}=".to_sym, to: :car
end
private
car_structure = #array of hashes
def fields_of_model(model)
car_structure.select {|record| record[:model] == model}.map{|record| record[:name]}
end
end
NoMethodError(CarRegistration :: Basics:Class的未定義方法`fields_of_model'):
我認為您在這里遇到了許多問題。
首先,您已經將fields_of_model
定義為實例方法,在這里:
def fields_of_model(model)
car_structure.select {|record| record[:model] == model}.map{|record| record[:name]}
end
但您正在嘗試從班級中調用它:
fields_of_model(:car).each do |attr|
delegate attr.to_sym, "#{attr}=".to_sym, to: :car
end
因此,您需要將fields_of_model
一個類方法,並在調用它之前對其進行定義。 就像是:
module CarRegistration
class Basics < Base
private
car_structure = #array of hashes
class << self
def fields_of_model(model)
car_structure.select {|record| record[:model] == model}.map{|record| record[:name]}
end
end
fields_of_model(:car).each do |attr|
delegate attr.to_sym, "#{attr}=".to_sym, to: :car
end
end
我認為,您還會遇到那個car_structure
變量問題,因為它將超出類方法的范圍。 因此,我認為您需要制作一個類級實例變量。 因此,嘗試一下:
module CarRegistration
class Basics < Base
@car_structure = #array of hashes
class << self
def fields_of_model(model)
@car_structure.select {|record| record[:model] == model}.map{|record| record[:name]}
end
private :fields_of_model
end
fields_of_model(:car).each do |attr|
delegate attr.to_sym, "#{attr}=".to_sym, to: :car
end
end
請注意,我使用private :fields_of_model
將類方法:fields_of_models
私有。
為了演示整個過程,我進行了RSpec測試:
require 'rails_helper'
class Car
attr_accessor *%w(
color
make
year
).freeze
end
module CarRegistration
class Basic
@car_structure = [
{model: :car, name: :color},
{model: :car, name: :make},
{model: :car, name: :year}
]
class << self
def fields_of_model(model)
@car_structure.select {|record| record[:model] == model}.map{|record| record[:name]}
end
private :fields_of_model
end
fields_of_model(:car).each do |attr|
delegate attr.to_sym, "#{attr}=".to_sym, to: :car
end
def car
@car ||= Car.new
end
end
end
RSpec.describe CarRegistration::Basic do
it "has :fields_of_model as a private class method" do
expect(CarRegistration::Basic.public_methods).not_to include(:fields_of_model)
expect(CarRegistration::Basic.private_methods).to include(:fields_of_model)
end
it "responds to :color and :color=" do
expect(car_registration).to respond_to(:color)
expect(car_registration).to respond_to(:color=)
end
it "sets and gets attributes on car" do
expect(car_registration.color).to be_nil
expect(car_registration.car.color).to be_nil
car_registration.color = :red
expect(car_registration.car.color).to eq(:red)
expect(car_registration.color).to eq(:red)
expect(car_registration.instance_variable_get(:@color)).to be_nil
end
end
def car_registration
@car_registration ||= described_class.new
end
運行時產生以下結果:
CarRegistration::Basic
has :fields_of_model as a private class method
responds to :color and :color=
sets and gets attributes on car
Finished in 0.733 seconds (files took 27.84 seconds to load)
3 examples, 0 failures
順便說一句,有外部你們班這個代碼def
- end
是蠻好的,而不是你的問題的根源。 實際上,這很正常。
另外,我會注意到JörgW Mittag希望說:
我是那些喜歡指出Ruby中沒有類方法之類的Ruby Purists的人之一。 不過, 只要各方都充分理解這是一種口語用法,那么以口語方式使用術語類方法 就可以了 。 換句話說,如果你知道有沒有這樣的事,作為一個類的方法和術語“類方法”只是短期的“單身類的對象,它是實例的實例方法
Class
”,再有就是沒問題。 但是否則,我只能看到它妨礙理解。
各方應完全理解,術語“ 類方法”是在其通俗意義上使用的。
因為您未在def
- end
子句中編寫該方法; 你應該這樣寫
def my_method
fields_of_model(:car).each do |attr|
delegate attr.to_sym, "#{attr}=".to_sym, to: :car
end
end
這就是為什么錯誤消息顯示CarRegistration::Basics:Class
而不是CarRegistration::Basics
這是一個有效的示例代碼。 通常不需要在Module
內放置一個類,但是如果您由於某種原因必須這樣做,這是一種方法。
module CarRegistration
class Basics < Object
def run(model)
fields_of_model(model)
end
private
def fields_of_model(model)
puts model
end
end
end
a = CarRegistration::Basics.new
a.run('xyz') # => 'xyz' is printed.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.