Beartech
Beartech

Reputation: 6411

Undefined method error for class in Rails method called in controller

My Rails have gotten rather rusty and I'm driving myself crazy trying to figure out something that is probably so basic I can't see the forest for the trees.

I have a form that goes to the create action of my controller. When I save I need to also update some items from another table. I want to wrap it all in a transaction. I thought the preference was to put the transaction in the model. When I do that and try to call the create action it errors out telling me that there is no method for that class.

equip_swaps_controller.rb

 def create
   respond_to do |format|
     @equip_swap = EquipSwap.new(equip_swap_params)
     if @equip_swap.trans_equip_and_save
       format.html { redirect_to @equip_swap, notice: 'Equipment transfer was successfully created.' }
     else
       format.html { render action: 'failure' }
     end
   end
 end

Model equip_swap.rb

def self.trans_equip_and_save
  EquipSwap.transaction do
    Tool.transfer_equipment(self.to_vehicle, self.items_moved)
    self.save
  end
end

Tool model with needed method

def transfer_equipment(location,ids)
  ids.each do |id|
    Tool.find(id).update(location: location)
  end
end

I thought that calling the class method would allow it to execute that method on my instance of the EquipSwap instance @equip_swap. When I try to submit the form and create the new record it tells me that there is no trans_equip_and_save method for Class..... There is something obvious that I'm missing. Help!

Upvotes: 3

Views: 11932

Answers (2)

ashvin
ashvin

Reputation: 2040

Method start with self its call class method and and without self its call instance method, let me give example

Class method
def self.class_method
  # do some stuff
end

Instance method
def instance_method
  # do some stuff 
en

Call class method using

ModelName.class_method

Call instance method using

@instance_variable.instance_method

In your code change your method to instance method

def trans_equip_and_save
 EquipSwap.transaction do
  Tool.transfer_equipment(self.to_vehicle, self.items_moved)
  self.save
 end
end

And now call this method using instance variable @equip_swap.trans_equip_and_save

Edit:

If you are calling transfer_equipment using model name then add self before method name, I mean make it class method like following

def self.transfer_equipment(location,ids)
  ids.each do |id|
    Tool.find(id).update(location: location)
  end
end

Upvotes: 8

Sravan
Sravan

Reputation: 18647

You have two things to notice here,

First of all there are two different methods, class methods and instance methods.

Class methods: Class methods are defined directly on a class and they are defined using def self.method.

Usage: Class.method

Instance methods: Instance methods are defined on an object of a class and they are defined without self.

Usage: object = Class.new(), def method ==> object.method

So, in your case, there will be two changes,

1) you called, @equip_swap.trans_equip_and_save.

Since, @equip_swap is an object, according to second point you shold have an Since, @equip_swap is an object, according to second point you shold have an instance method without self..

def trans_equip_and_save
  EquipSwap.transaction do
    Tool.transfer_equipment(self.to_vehicle, self.items_moved)
    self.save
  end
end

2) Tool.transfer_equipment, this is called with class name. So, according to first point it should be called with self.

def self.transfer_equipment(location,ids)
  ids.each do |id|
    Tool.find(id).update(location: location)
  end
end

Upvotes: 2

Related Questions