1

In my view, I use a <%= f.text_field :latlon %> to edit the latlon attribute (not an ActiveRecord column). When saving, I want to parse latlong and split it into lat and lon in a before_save callback.

I don't know how to access to the params of the latlon variable inside the callback. I have tried self.latlong but that calls the same attr_reader as the lat and lon attributes.

I know I can do this in the controller but, this is model logic, no?

#app/models/bla.rb
class Bla < ActiveRecord::Base
  attr_accessible :name, :lat, :lon, :latlon #but latlon is not an ActiveRecord Attribute

  before_save :foo

  def latlon
    "#{lat}, #{lon}"
  end

  attr_writer latlon

  private

  def foo
    self.lat = # regex that parse latlon
    self.lon = # regex that pase coors
  end

end
Tom Harrison
  • 13,533
  • 3
  • 49
  • 77
eveevans
  • 4,392
  • 2
  • 31
  • 38
  • Could you post the error you're getting? – Tom Harrison Nov 30 '12 at 21:28
  • Yes, this is model logic, but you'll need to pass the right value from the controller. – Tom Harrison Nov 30 '12 at 21:34
  • Its not exactly an error, the problem is that when I call the latlon method (attr_reader) it will return me "#{lat}, #{lon}" , instead of its real value – eveevans Nov 30 '12 at 21:37
  • can you use @latlon in foo per the answer below? – John Naegle Nov 30 '12 at 21:38
  • @TomHarrisonJr , yes, I pass the right value via form from the view. I mean, If I call latlong without define the latlon method, I will return the right value, but when I enter to the view I will not see the latlon value, – eveevans Nov 30 '12 at 21:41
  • If the view references an instance of the Bla model, @bla.latlon should contain the current values of `lat` and `lon` formatted correctly. You might have to handle nil cases or something but that should work fine. And going the other direction, the form should have `params => {:bla => {:latlon => "12.3456, 78.9012", ...}}` which you should be able to save (see Xathras's and my answer). – Tom Harrison Nov 30 '12 at 21:46

3 Answers3

3

You can override the assignment method to do what you're describing. This has the bonus of being faster/easier to unit test.

def latlon=(new_value)
  # do work to split and assign
end
Andrew Kothmann
  • 607
  • 3
  • 4
1

I would think that you might replace attr_writer latlon with

def latlon=(latlon)
  self.lat = # regex that parses lat from latlon
  self.lon = # regex that parses lon from latlon
end

And maybe don't make :lat and :lon part of attr_accessible since they will never be mass-assigned, i.e. from the params array. params passed from the controller will contain the latlon value (formatted correctly).

I don't think you need a before_save in this case.

Tom Harrison
  • 13,533
  • 3
  • 49
  • 77
0

The model should have access to the instance variable @latlon that you can use, right?

Jakob W
  • 3,347
  • 19
  • 27
  • yes, but It will call to my latlon method (attr_reader) that will be "#{lat}, #{lon}" , instead of its real value – eveevans Nov 30 '12 at 21:35
  • 1
    Take a look at http://stackoverflow.com/questions/5046831/why-use-rubys-attr-accessor-attr-reader-and-attr-writer – John Naegle Nov 30 '12 at 21:38