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