I'm learning with the Agile Web Development 4th edition book. I've built a method in my controller to test that it works, and now I want to move it to the model.
I’m learning with the Agile Web Development 4th edition book. I’ve
built a method in my controller to test that it works, and now I want to
move it to the model.
*** line_item controller ***
def create
@cart = current_cart event = Event.find(params[:event_id]) @line_item = @cart.add_event(event) new_capacity = event.capacity respond_to do |format| if @line_item.save new_capacity = new_capacity - @line_item.quantity event.capacity = new_capacity event.save format.html { redirect_to(@line_item.cart, :notice => 'Line item
was successfully created.') }
format.xml { render :xml => @line_item, :status => :created,
:location => @line_item }
else format.html { render :action => "new" } format.xml { render :xml => @line_item.errors, :status =>
:unprocessable_entity }
end end
end
so I started by doing this
line_item.rb***********
def decrease_seat_capacity_on_create
new_capacity = new_capacity - @line_item.quantity event.capacity = new_capacity event.save
end
In this method @line_item does not exist because you have not created it. So you may need to pass to this method the line_item object or look it up.
Also, you should look at the after_save callback in ActiveRecord, that way you might be able to tell your LineItem model to automatically perform this action after a successful save (if you google for activerecord callbacks you will find a number of them, they are very useful).
See inserted comments below.
Quoting linda Keating <lists@ruby-forum.com>:
I'm learning with the Agile Web Development 4th edition book. I've built a method in my controller to test that it works, and now I want to move it to the model. ******************************** *** line_item controller *** ******************************** def create @cart = current_cart event = Event.find(params[:event_id]) @line_item = @cart.add_event(event) new_capacity = event.capacity
respond_to do |format| if @line_item.save new_capacity = new_capacity - @line_item.quantity event.capacity = new_capacity event.save
format.html { redirect_to(@line_item.cart, :notice => 'Line item was successfully created.') } format.xml { render :xml => @line_item, :status => :created, :location => @line_item } else format.html { render :action => "new" } format.xml { render :xml => @line_item.errors, :status => :unprocessable_entity } end end end
so I started by doing this
*********************************** *****line_item.rb**************** ********************************
def decrease_seat_capacity_on_create
new_capacity = new_capacity - @line_item.quantity event.capacity = new_capacity event.save end
new_capacity and event are local variables in the controller method. They are not accessible in the called model method. @line_item is an instance variable of the controller instance. It is also not accessible in the model method. However it references the same object as self in the model method. Presumably, event is another model. Note: it is possible that a LineItem has an event method because there is an association between Events and LineItems.
I don't see any good reason to push this functionality into a model method. The only property of the model that is clearly being used is the quantity attribute/method. Unless the LineItem model includes a reference to an Event (i.e. LineItem belongs to an Event or hasMany Events). It still looks like poor design unless there are several factors not mentioned here.
Jeffrey
and made a changed the line_item controller like this
respond_to do |format| if @line_item.save @line_item.decrease_seat_capacity_on_create
But I get the error
undefined method `quantity' for nil:NilClass Rails.root: c:/webtech/ServerSide/tickets_online
Application Trace | Framework Trace | Full Trace app/models/line_item.rb:12:in `decrease_seat_capacity_on_create' app/controllers/line_items_controller.rb:51:in `block in create' app/controllers/line_items_controller.rb:49:in `create'
So I'm a bit confused about 'quantity'. I've used it in another method in the line_item.rb and it worked (much to my surprise) but it doesn't work in this new method I'm writing.
It isn't quantity that isn't working, it is that @line_item is nil (i.e., @line_item of the LineItem instance has not been assigned a value). @line_item is an instance variable in the controller, not in the model.
I really am an absolute beginner so I'm really just guessing most of the time. Any suggestions or hints would be most appreciated.
HTH, Jeffrey
Jeffrey L. Taylor wrote in post #997405:
See inserted comments below.
Quoting linda Keating <lists@ruby-forum.com>:
new_capacity = event.capacity format.xml { render :xml => @line_item, :status => :created,
new_capacity and event are local variables in the controller method. They are not accessible in the called model method. @line_item is an instance variable of the controller instance. It is also not accessible in the model method. However it references the same object as self in the model method. Presumably, event is another model. Note: it is possible that a LineItem has an event method because there is an association between Events and LineItems.
I don't see any good reason to push this functionality into a model method. The only property of the model that is clearly being used is the quantity attribute/method. Unless the LineItem model includes a reference to an Event (i.e. LineItem belongs to an Event or hasMany Events). It still looks like poor design unless there are several factors not mentioned here.
Hi Jeffrey, I was moving it into the model soley because I've read that fat models and skinny controllers are the best design practice. I was just trying to get the function to work first, and now that it's working I was hoping to tidy up the design. But maybe I should just leave it as is. I have though similar functionality in the update controller that looks like this ...
def update @line_item = LineItem.find(params[:id]) event = @line_item.event new_quantity = params[:line_item_quantity].to_i change_in_capacity = @line_item.quantity - new_quantity
respond_to do |format| if @line_item.update_attributes(params[:line_item]) if (@line_item.quantity >0) event.capacity = change_in_capacity event.save
and I'll be writing something similar again reversing the action in the destroy method of line_item.
But maybe I should just leave it as is for the moment until I've learned a bit more about Ruby and Rails.
Many thanks for your help and feedback. Really appreciate your patience.
Linda