Rails / ActiveRecord: нормализация полей - PullRequest
3 голосов
/ 19 мая 2009

Я пытаюсь удалить запятые из поля в модели. Я хочу, чтобы пользователь набрал число, то есть 10 000, и это число должно быть сохранено в базе данных как 10000. Я надеялся, что смогу выполнить некоторую нормализацию на стороне модели, чтобы удалить запятую. Я не хочу зависеть от представления или контроллера, чтобы правильно отформатировать мои данные.

Я пытался:

before_validation :normalize

def normalize 
 self['thenumber'] = self['thenumber'].to_s.gsub(',','')
end

без работы.

Ответы [ 5 ]

8 голосов
/ 18 августа 2010

http://github.com/mdeering/attribute_normalizer выглядит многообещающим решением этой распространенной проблемы. Вот несколько примеров с домашней страницы:

  # By default it will strip leading and trailing whitespace
  # and set to nil if blank.
  normalize_attributes :author, :publisher

  # Using one of our predefined normalizers.
  normalize_attribute  :price, :with => :currency

  # You can also define your normalization block inline.
  normalize_attribute :title do |value|
    value.is_a?(String) ? value.titleize.strip : value
  end

Так что в вашем случае вы можете сделать что-то вроде этого:

  normalize_attribute :title do |value|
    value.to_s.gsub(',', '')
  end
5 голосов
/ 19 мая 2009

Я думаю, вы делаете все правильно. Этот тест проходит:

test "should remove commas from thenumber" do
  f = Foo.new(:thenumber => "10,000")
  f.save
  f = Foo.find(f.id)
  assert f.thenumber == "10000"    
end

И я использовал твой код.

 class Foo < ActiveRecord::Base
  before_validation :normalize

  def normalize 
    self['thenumber'] = self['thenumber'].to_s.gsub(',','')
  end

 end

Теперь моя схема настроена так, чтобы тогда число было строкой, а не целым числом.

Started
.
Finished in 0.049666 seconds.

1 tests, 1 assertions, 0 failures, 0 errors

Если вы хотите сохранить это в БД как целое число, то вам определенно нужно переопределить установщик:

 def thenumber=(value)
   self['thenumber'] = value.to_s.gsub(',','').to_i
 end

Если вы делаете это по-своему, с целочисленным столбцом, оно усекается AR ....

>> f.thenumber = "10,000"
=> "10,000"
>> f.thenumber
=> 10

Это малоизвестная вещь с Ruby и целыми числами ... она автоматически преобразуется путем усечения всего, что больше не является целым числом.

irb(main):004:0> i = "155-brian-hogan".to_i
=> 155

Может быть круто для таких вещей, как

/users/155-brian-hogan

@user = User.find_by_id(params[:id])

Но не очень круто для того, что ты делаешь.

Так что либо измените col на строку и используйте фильтр, либо измените setter:)

Удачи!

1 голос
/ 19 мая 2009

Проблема с этим заключается в том, что какое-то время ненормализованный материал будет существовать в объекте; если у вас есть код, который работает с атрибутами до нормализации содержимого, это будет проблемой.

Вы можете определить сеттер:

def thenumber=(value)
  # normalise stuff here, call write_attribute
end

К сожалению, я думаю, что многие из форм Rails пишут атрибуты напрямую, что является одной из причин, по которой я не склонен их использовать.

Или вы можете нормализовать параметры в контроллере, прежде чем пропустить их.

0 голосов
/ 12 мая 2010

Вы должны вернуть true из вашего метода before_validation, в противном случае, если выражение, присваиваемое self ['thenumber'], в конечном итоге станет nil или false, данные не будут сохранены, согласно документации Rails:

Если обратный вызов before_ * возвращает false, все последующие обратные вызовы и тому связанные действия отменяются.

Якобы, вы пытаетесь нормализовать здесь, а затем проверить результат нормализации с вашими валидациями Rails, который решит, в порядке ли nil / false / blank или нет.

before_validation :normalize

def normalize 
  self['thenumber'] = self['thenumber'].to_s.gsub(',','')
  return true
end
0 голосов
/ 19 мая 2009

Позволяет ли ruby ​​вам обмениваться между собой. а также [''] ? Я не знаю, я попробую позже, но я думаю, что вы должны использовать.

self.thenumber = self.thenumber.to_s.gsub(',','')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...