0

I have a non activerecord rails model:

class Document
  attr_accessor :a, :b
  include ActiveModel::Model

  def find(id)
    initialize_parameters(id)
  end

  def save
    ...
  end

  def update
    ...
  end

  private

  def initialize_parameters(id)
    @a = 1
    @b = 2
  end
end

In order to find the Document, I can use:

Document.new.find(3)

So, to get it directly I changed the find method to

def self.find(id)
  initialize_parameters(id)
end

And I get the following error when I run

Document.find(3)

undefined method `initialize_parameters' for Document:Class

How can I make this work?

2
  • Did one of the answers work for you? Commented Feb 26, 2018 at 5:14
  • Yes! Now I understood how it works. Commented Feb 28, 2018 at 8:27

2 Answers 2

3

You can't access an instance method from a class method that way, to do it you should instantiate the class you're working in (self) and access that method, like:

def self.find(id)
  self.new.initialize_parameters(id)
end

But as you're defining initialize_parameters as a private method, then the way to access to it is by using send, to reach that method and pass the id argument:

def self.find(id)
  self.new.send(:initialize_parameters, id)
end

private

def initialize_parameters(id)
  @a = 1
  @b = 2
end

Or just by updating initialize_parameters as a class method, and removing the private keyword, that wouldn't be needed anymore.

Sign up to request clarification or add additional context in comments.

Comments

1

This:

class Document
  attr_accessor :a, :b

  def self.find(id)
    initialize_parameters(id)
  end

end

Is not trying to "access class method from instance method" as your title states. It is trying to access a (non-existent) class method from a class method.

Everything Sebastian said is spot on.

However, I guess I would ask: 'What are you really trying to do?' Why do you have initialize_parameters when ruby already gives you initialize that you can override to your heart's content? IMO, it should look something more like:

class Document
  attr_accessor :a, :b, :id

  class << self

    def find(id)
      new(id).find
    end

  end

  def initialize(id)
    @a = 1
    @b = 2
    @id = id
  end

  def find
    # if you want you can:
    call_a_private_method
  end

private

  def call_a_private_method
    puts id
  end

end

1 Comment

I'm trying to achieve the same behavior as an activerecord model has

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.