Reputation: 6411
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
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
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