为什么我不能在同类中使用私人方法?如何修复我的代码以防止错误?
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(未定义的方法`fields_of_model'for carRegistration ::基础:班级):
我认为您在这里遇到了许多问题。
首先,您将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örgWMittag希望说:
我是那些喜欢指出的红宝石纯粹主义者之一,在Ruby中没有类方法。不过,我完全很好,只要所有各方都完全理解了这是口用使用, colloququalial colloququal 。换句话说,如果您知道没有类方法之类的东西,而术语"类方法"只是" singleton" singleton类的实例方法的简短,则是一个实例
Class
",然后没有问题。但是否则,我只看到它阻碍了理解。
所有各方都完全理解了术语 class方法在俗语中使用。
,因为您在 def
- end
rause中写下了方法不是;你应该像
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.