I''m an amateur coder. Know enough to get into trouble, not enough to get out of it. I''m trying to make an office app for the photo studio I work for. Part of this app is a scheduler. Our assignments typically do not span more than a day. I have defined starts_at and ends_at attributes in my model, both datetime objects. I have a datetime_select helper in the form to establish starts_at. Because year, month and day will be the same for ends_at, I would prefer the user not have to enter that redundant information. Ideally I would like the user to only need to specify hour and minute for ends_at, and have the rest picked up from starts_at. For that reason, I added two textfield_tag helpers to the form to capture how many hours and how many minutes we anticipated the event to last. I understand that a before_save callback in the model is a smart way to go. I can''t figure out how to do it. Using raise params, I learned that the datetime_select helper does not create a full blown datetime object but rather adds 5 items to the params hash: starts_at(1i) - starts_at(5i) I tried this (and multiple variations of this) to the before_save method: class Event < ActiveRecord::Base before_save :create_end def create_end self.ends_at.year = params[:starts_at[:1i]] self.ends_at.month = params[:starts_at[:2i]] self.ends_at.day = params[:starts_at[:3i]] self.ends_at.hour = params[:starts_at[:4i]] + params [:duration_hours] self.ends_at.min = params[:starts_at[:5i]] + params [:duration_minutes] end end That was a mess, so, following a helpful tip, I tried def create_end ends_at = ends_at.change(:year => starts_at.year, :month => starts_at.month, :day => starts_at.day, :hour => (starts_at.hour + params [:duration_hours]), :min => (starts_at.min + params[:duration_minutes])) end I''m clearly botching the syntax for the callback because nothing I have tried has worked. Help? Thanks. Steve
On Oct 1, 7:19 pm, SNelson <stv.n...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: Well there is some funkiness todo with how time parameters are passed around, but that is not the problem here. Equally the components of a date or time object are readonly properties. What I think the core misconception here is that params is a controller method therefore you cannot call it from a model instance method. Usually you don''t need to: why fiddle with params[:starts_at] when you already have self.starts_at ? I''m not sure a callback is right for you here, are you always going to want to update ends_at even on subsequent saves ? You could instead have a method that takes a number of hours and minutes and sets tends at correspondlingly, call that from your controller. Lastly be careful about your calculations - not sureyour examples wouldn''t work if starts_at hour was 23 and duration_hours was 3 for example) Fred> > class Event < ActiveRecord::Base > before_save :create_end > def create_end > self.ends_at.year = params[:starts_at[:1i]] > self.ends_at.month = params[:starts_at[:2i]] > self.ends_at.day = params[:starts_at[:3i]] > self.ends_at.hour = params[:starts_at[:4i]] + params > [:duration_hours] > self.ends_at.min = params[:starts_at[:5i]] + params > [:duration_minutes] > end > end > > That was a mess, so, following a helpful tip, I tried > > def create_end > ends_at = ends_at.change(:year => starts_at.year, :month => > starts_at.month, > :day => starts_at.day, :hour => (starts_at.hour + params > [:duration_hours]), > :min => (starts_at.min + params[:duration_minutes])) > end > > I''m clearly botching the syntax for the callback because nothing I > have tried has worked. > > Help? > Thanks. > > Steve
Thanks so much for taking the time to consider this Fred. I got it working, thanks to some patient help from several complete strangers. The generosity inside online communities is a wonderful thing. I had to add both duration_minutes and duration_hours to the model so the callback could access them. I had initially been thinking of them as just "disposable" items, not worth saving. Now I''m glad I did because, to answer your question, yes we are just as likely to change the duration of an assignment as we are to change its start time. Lots of little last minute changes in our shop. :( Once those attributes became available to the model, I could write a before_save callback like this: def create_end self.ends_at = starts_at.advance(:hours => duration_hours, :minutes => duration_minutes) end So thanks again for your help. I learned some interesting things. Not having worked with model callback methods before, I had not grasped that the params method was not available to models. Thanks for that insight. Steve