简体   繁体   中英

Ruby inheritance, method not being passed to a child class

I've got a ruby exercise, and cannot quite get past one point. When I run the tests, it throws undefined method "attribute" for CommentSerializer:Class . Though, there is such a method defined in serializer.rb , from which it's being inherited.

Am I missing something about inheritance in ruby here?

Note : I am neither allowed to add any gems other than the two listed below, nor to modify any file other than serializer.rb .

Here are the files:

Gemfile:

gem 'rspec'
gem 'pry'

app/comment.rb:

Comment = Struct.new(:id, :body)

app/comment_serializer.rb:

require_relative "serializer"

class CommentSerializer < Serializer
  attribute :id
  attribute :body
end

app/serializer.rb:

class Serializer
  def initialize(object)
    @obj = object
  end

  def serialize
    obj.members.inject({}) do |hash, member|
      hash[member] = obj[member]
      hash
    end
  end

  def attribute(key)
  end

  private

  def obj
    @obj
  end
end

spec/comment_serializer_spec.rb:

require "date"
require_relative "spec_helper"
require_relative "../app/comment"
require_relative "../app/comment_serializer"

RSpec.describe CommentSerializer do
  subject { described_class.new(comment) }

  let(:comment) do
    Comment.new(1, "Foo bar")
  end

  it "serializes object" do
    expect(subject.serialize).to eq({
      id: 1,
      body: "Foo bar",
    })
  end
end

If you call something like attribute in the body of the class definition then it happens in the class context at that exact moment , as in:

class Example < Serializer
  # This is evaluated immediately, as in self.attribute(:a) or Example.attribute(:a)
  attribute :a
end

There must be a corresponding class method to receive that call, as in:

class Serializer
  def self.attribute(name)
    # ...
  end
end

Since you're inheriting that method it will be defined prior to calling it, but that's not the case if you have something like:

class Example
  attribute :a # undefined method `attribute' for Example:Class (NoMethodError)

  def self.attribute(name)
  end
end

The method is defined after it's called, so you get this error. You must either reverse the order, define first, call second, or put it into a parent class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM