Mike Kogan
2006-Jul-07 00:29 UTC
[Rails] Sequencing control with edit method in CRUD examples
I have been playing with the cookbook type of tutorials building a fish tournament scoring piece and am having a bit of a problem with a DB field called "points" in my "catch" table that is not input by the user but is calulated based on a "size" field that is input by the user. I have the following in my catch_controller.db def new @catch = Catch.new @fish = Fish.find_all @bait = Bait.find_all end def create @catch = Catch.new(@params[''catch'']) @catch.datetime = DateTime.now @catch.points = @catch.size if @catch.bait_id == 2 @catch.points = @catch.size + (@catch.size/10) end if @catch.bait_id == 3 @catch.points = @catch.size + (@catch.size/5) end if @catch.save redirect_to :action => ''list'' else render_action ''new'' end end Granted it''s not particularly elegant but when a new catch is entered the "points" are correctly set in the create method. The problem I am having is in "Edit". def edit @catch = Catch.find(@params["id"]) @fish = Fish.find_all @bait = Bait.find_all @catch.points = @catch.size if @catch.bait_id == 2 @catch.points = @catch.size + (@catch.size/10) end if @catch.bait_id == 3 @catch.points = @catch.size + (@catch.size/5) end if @catch.save redirect_to :action => ''list'' else render_action ''new'' end end Where or in what method would I put similar code so that when someone edits the "size" field of a record the "points" are properly tabulated? The code above does not correctly work as it does for the new/create function. Should this code be in an update method? What runs after the edit view? With default edit/update scaffolding I am seeing the "size" properly updated but no effect on "points". But if I then go back into the record with the edit view and "submit" with no further changes the "points" are magically updated. WTF is going on and how do I get my code to set the points in the proper place? Clearly it does not belong in the edit view ... -- Posted via http://www.ruby-forum.com/.
Mike Kogan
2006-Jul-07 01:40 UTC
[Rails] Re: Sequencing control with edit method in CRUD examples
Nevermind, solved. But a real POS solution. Clearly I am missing something here. def update @catch = Catch.find(params[:id]) if @catch.update_attributes(params[:catch]) @catch.points = @catch.size if @catch.bait_id == 2 @catch.points = @catch.size + (@catch.size/10) end if @catch.bait_id == 3 @catch.points = @catch.size + (@catch.size/5) end @catch.update_attributes(params[:catch]) redirect_to :action => ''show'', :id => @catch else render :action => ''edit'' end end By doing my points mod after the initial catch.update, then doing another catch.update it works OK. Not sure why I couldn''t just do my points processing before the first catch.update though -- that''s how it should work. This method is invoked after the edit view (form) is submitted and the new score is input. I''m thinking that perhaps the new score was input by the form, but the @catch instance is getting the old score value to assign to points (from the db model) not the new one that was freshly input inside the params. I bet there''s a way to extract it from the params and insert the updated score into the params[:catch] so that a single update can be done. Any ideas? -- Posted via http://www.ruby-forum.com/.
Chris Carter
2006-Jul-07 03:55 UTC
[Rails] Re: Sequencing control with edit method in CRUD examples
Hey, I see you solved your problem, but you really should put that calculation in the model, not in the controller, then call it from the controller. This will keep your code clean and DRY, and makes it more MVCish/Railsish. You may want to just put it in a before_save filter in your model, would be simple, assuming on all saves you want to calculate points. Look up callbacks in the api. Good Luck! Chris Carter concentrationstudios.com Mike Kogan wrote:> I have been playing with the cookbook type of tutorials building a fish > tournament scoring piece and am having a bit of a problem with a DB > field called "points" in my "catch" table that is not input by the user > but is calulated based on a "size" field that is input by the user. > > I have the following in my catch_controller.db > ... > > Where or in what method would I put similar code so that when someone > edits the "size" field of a record the "points" are properly tabulated? > The code above does not correctly work as it does for the new/create > function. Should this code be in an update method? What runs after the > edit view? > > With default edit/update scaffolding I am seeing the "size" properly > updated but no effect on "points". But if I then go back into the record > with the edit view and "submit" with no further changes the "points" are > magically updated. WTF is going on and how do I get my code to set the > points in the proper place? Clearly it does not belong in the edit view > ...-- Posted via http://www.ruby-forum.com/.
Mike Kogan
2006-Jul-07 12:25 UTC
[Rails] Re: Sequencing control with edit method in CRUD examples
Thanks Chris -- so move the points tabulation code (which I do want on all catch saves whether a new catch is entered or an existing one is edited/updated) to the model but still invokve it from the controller? I was under the impression actions not related to displaying data should be in the controller MVC-wise etc. Will a before-save filter be invoked on both new and edit operations automatically or do I need to enable this? I''ll research the callbacks and before_save later. Also I am wondering about my "solution" -- there really should not have to be 2 calls to update_attributes should there? Does the before_save get invoked through a callback when the update_attributes or save methods are invoked? That would be a lot cleaner. Thanks again, Mike Chris Carter wrote:> Hey, > I see you solved your problem, but you really should put that > calculation in the model, not in the controller, then call it from the > controller. This will keep your code clean and DRY, and makes it more > MVCish/Railsish. You may want to just put it in a before_save filter in > your model, would be simple, assuming on all saves you want to calculate > points. Look up callbacks in the api. Good Luck! > > Chris Carter > concentrationstudios.com >-- Posted via http://www.ruby-forum.com/.
Justin Forder
2006-Jul-07 14:17 UTC
[Rails] Re: Sequencing control with edit method in CRUD examples
Mike Kogan wrote:> Thanks Chris -- so move the points tabulation code (which I do want on > all catch saves whether a new catch is entered or an existing one is > edited/updated) to the model but still invokve it from the controller? I > was under the impression actions not related to displaying data should > be in the controller MVC-wise etc. > > Will a before-save filter be invoked on both new and edit operations > automatically or do I need to enable this? I''ll research the callbacks > and before_save later. > > Also I am wondering about my "solution" -- there really should not have > to be 2 calls to update_attributes should there? Does the before_save > get invoked through a callback when the update_attributes or save > methods are invoked? That would be a lot cleaner. > > Thanks again, > Mike > > > Chris Carter wrote: >> Hey, >> I see you solved your problem, but you really should put that >> calculation in the model, not in the controller, then call it from the >> controller. This will keep your code clean and DRY, and makes it more >> MVCish/Railsish. You may want to just put it in a before_save filter in >> your model, would be simple, assuming on all saves you want to calculate >> points. Look up callbacks in the api. Good Luck!If the scoring rules are fixed, you can just compute the points on demand, rather than saving them in the database. E.g. (in Catch) BAIT_SCALE_FACTORS = [1.0, 1.0, 1.1, 1.2] def points size * BAIT_SCALE_FACTORS[bait_id] end (untested!) You might need to add some protection against size or bait_id being undefined (but the same would be true of your original code) Justin
Mike Kogan
2006-Jul-07 15:35 UTC
[Rails] Re: Re: Sequencing control with edit method in CRUD examples
Justin thanks for that idea. However I think I am going to store them because there will be multiple fish per angler and ultimately I will be computing the angler''s total points from all catches etc. So for simplicity I really want to store the points although I like your approach better -- being a 25+ year C programmer I don''t have my teeth around the Ruby syntax yet to do the obvious as you did with the points method and array. I think I''ll be doing that anyway to better isolate the common points logic. Thanks! -- Posted via http://www.ruby-forum.com/.
Mike Kogan
2006-Jul-07 17:20 UTC
[Rails] Re: Sequencing control with edit method in CRUD examples
Totally cool guys, I really appreciate all the pointers. The before-save callback works like a charm once the moronic programmer realizes the method goes in the model not the controller ;) Justin I took your advice a step further, and put the bait scale factors into the bait table so it wouldn''t be hard-coded anywhere and would always be data-driven for other tournaments, bait types, and potential point scaling factors related to bait type. The only thing that bites is my lack of understanding why the original piece of code in the 2nd post was required to have 2 updates. When I figure that out I''ll be much further down the road to understanding more about data passing and flow control in RoR. Thanks Again, even an old OS programmer can find a little joy in this MVC stuff! -- Posted via http://www.ruby-forum.com/.
Chris Carter
2006-Jul-07 18:50 UTC
[Rails] Re: Sequencing control with edit method in CRUD examples
Mike Kogan wrote:> Totally cool guys, I really appreciate all the pointers. The before-save > callback works like a charm once the moronic programmer realizes the > method goes in the model not the controller ;) Justin I took your advice > a step further, and put the bait scale factors into the bait table so it > wouldn''t be hard-coded anywhere and would always be data-driven for > other tournaments, bait types, and potential point scaling factors > related to bait type. > > The only thing that bites is my lack of understanding why the original > piece of code in the 2nd post was required to have 2 updates. When I > figure that out I''ll be much further down the road to understanding more > about data passing and flow control in RoR. > > Thanks Again, even an old OS programmer can find a little joy in this > MVC stuff!Hi Mike! Glad to see it all worked out. It needed two updates because you updated them from the edit, then made the points, then updated again. If you did the points logic outside of that if statement you would have only needed the one. -- Chris -- Posted via http://www.ruby-forum.com/.