2015-11-18 2 views
0

Я пытаюсь оптимизировать следующие модели бухгалтерского учета класса и два вопроса:Rails4 рефакторинг модель делает DRY

1) Как я могу заменить несколько сеттеров атрибутов с более изящным способом?

2) Есть ли лучший способ, чем если условно в методе replace_comma_with_dot

class Accounting < ActiveRecord::Base 

    validates :share_ksk, :central_office, :limit_value, :fix_disagio, 
      presence: true, numericality: { less_than: 999.99, greater_than_or_equal_to: 0.00 }, 
      format: { with: /\d*\.\d{0,2}$/, multiline: true, message: I18n.t('accounting.two_digits_after_decimal_point')} 

    def share_ksk=(number) 
    replace_comma_with_dot(number) 
    super 
    end 

    def central_office=(number) 
    replace_comma_with_dot(number) 
    super 
    end 

    def limit_value=(number) 
    replace_comma_with_dot(number) 
    super 
    end 

    def fix_disagio=(number) 
    replace_comma_with_dot(number) 
    super 
    end 

    def replace_comma_with_dot(number) 
    if number.is_a? String 
     number.sub!(",", ".") 
    elsif number.is_a? Float 
     number 
    else 
     "" 
    end 
    end 

end 

Как предложил пользователь Пардип я пытаюсь заменить мои добытчик с define_method:

[:share_ksk=, :central_office=, :limit_value=, :fix_disagio=].each do |method_name| 
    self.class.send :define_method, method_name do |number| 
     replace_comma_with_dot(number) 
     super 
    end 
    end 

Что я я скучаю?

+1

Обновление очень плохая практика –

+0

Должен ли я придерживаться затем к четырем сеттеры? – StandardNerd

+0

Возможно, я уже написал половину ответа - посмотрим, есть ли лучший способ. –

ответ

1

Вместо того, чтобы иметь метод в модель, я извлечу функциональность и добавлю ее к классам String или Integer:

#lib/ext/string.rb 
class String 
    def replace_comma_with_dot 
    number.sub!(",",".") #Ruby automatically returns so no need to use return 
    end 
end 

Это - если ваш number это string позволит вам сделать следующее:

number = "67,90" 
number.replace_comma_with_dot 

Чтобы использовать эту функцию в приложении, сеттеры в порядке. Вы можете достичь своей функциональности следующим образом:

def fix_disagio=(number) 
    self[:fix_disagio] = number.replace_comma_with_dot 
end 

Вашего обновление в порядке, за исключением того, я бы уклоняться от него себя, как это создает навороты, которые не должны быть там.

Я искал способ установить атрибуты, когда вы вытаскиваете из db, но потом я понял, что если вам нужно установить это каждый раз, когда вы вызываете модель, то что-то будет не так.

Я бы лично посмотреть на изменение этого на db уровне, в противном случае, вы, вероятно, будете иметь возможность использовать какие-то localization, чтобы определить, нужно ли вам в dot или comma.

Существует хороший ответ здесь, который выступает adding to the ActiveRecord::Base class:

class ActiveRecord::Base 
    def self.attr_localized(*fields) 
    fields.each do |field| 
     define_method("#{field}=") do |value| 
     self[field] = value.is_a?(String) ? value.to_delocalized_decimal : value 
     end 
    end 
    end 
end 

class Accounting < ActiveRecord::Base 
    attr_localized :share_ksk 
end 
+0

Спасибо @richpeck, я ценю ваше понимание и обратную связь! – StandardNerd

3

Вы можете определить методы динамически с помощью define_method, вы можете оштрафовать более подробную информацию here

и вы можете обновить ваш replace_comma_with_dot с этим

def replace_comma_with_dot(number) 
    return number.sub!(",", ".") if number.is_a? String 
    return number if number.is_a? Float 
    "" 
end 

конца

+0

Спасибо, Пардиум! У меня есть некоторые проблемы, чтобы заменить сеттеры с помощью define_method. Можете ли вы уточнить? – StandardNerd