开发者

Convert data when putting them into a database using active record

What's the cleanest way to convert data (field values) when storing/loading into/from a database.

I usually convert the values the user has entered in the model class:

  def date_str
    format_date(开发者_运维知识库self.date)
  end

  def date_str=(str)
    self.date = DateParser.parse(str)
  end

(Note: The internal date parser is not sufficient, it doesn't cover many of our locale date notation styles, anyway).

This works already pretty fine, but I doesn't let me check for validity the usual RoR way because we don't store the string the user has entered. I usually let the parser function return nil if anything was wrong with the date, but this isnt very user-friendly – I cant really tell if the user hasn't entered anything or just a invalid value.

I'm looking for some way to integrate the conversion better into the A::R world where I can produce some useful error message if the conversion fails. Best would be if I could use the same facilities as the A::R::Adapter uses internally.

Has anybody some good ideas? What are other approaches?


The way you've suggested is fine, another alternative would be to do something like

attr_accessor :when

before_validation :update_date

def update_date
  self.date = parse_date(self.when) if self.when
end

def parse_date(date_as_string)
  # do something with the date
end

However, you're going to have write the validation yourself. It's not ideal, but it shouldn't be that much code.

If you're planning on using this all over your app, you should maybe look at writing a custom validator too, you can get more info about that here:

http://marklunds.com/articles/one/312


You can do this in a before validation callback that way you can use the normal AR validations on date.

before_validation :convert_date

def convert_date
   self.date = DateParser.parse(self[:date])
end


The attribute_normalizer provides a nice dsl for doing this kind of thing like this:

class Klass < ActiveRecord::Base

  normalize_attributes :date do |value|
    value.is_a?(String) ? DateParser.parse(value) : nil
  end

end
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜