ruby-on-rails 如何有条件地用另一个示例变量替换一个示例变量?

fkvaft9z  于 2023-03-31  发布在  Ruby
关注(0)|答案(2)|浏览(178)

我正在给一个类的示例变量赋值。场景是我需要调用一个函数至少三次,每次调用都需要一个答案存储在另一个示例变量中。
请记住,'RuboCop'可能会抛出错误。
名为Major的类如下所示。

class Major

  attr_accessor :max_temp, :min_temp, :max_humid, :max_t_day, 
  :min_temp_day, :max_humid_day

  def initialize
    @max_temp = -440
    @min_temp = 1000
    @max_humid = -500
    @max_t_day = 'fahad'
    @min_temp_day = 'fahad'
    @max_humid_day = 'fahad'
  end

  def day_wise_results
    _arg, year, path, _month = ARGV
    arr = Dir.entries(path).select { |x| x.include?(year) }
    # max_temp_day, min_temp_day, max_humid_day = ''

    arr.each do |yc|
      collection = file_collection("#{ path }/#{ yc }")
      collection.shift

      temperature_with_day(collection, 1, true, '>')
      temperature_with_day_min(collection, 3, false, '<')
      temperature_with_day_humid(collection, 7, true, '>')
end

这些函数具有几乎相同的代码;但是,示例变量是不同的。另外,我不希望有重复的代码。

函数

def temperature_with_day(collection, col, is_max, operator)
  if separate_collections(collection, col, is_max).public_send(
    operator, @max_temp
  )
    @max_temp = separate_collections(collection, col,
    is_max)
  end
  collection.each do |row|
    @max_t_day = row[0] if row[col].to_i.eql?(@max_temp)
  end
end

def temperature_with_day_min(collection, col, is_max, operator)
  if separate_collections(collection, col, is_max).public_send(
    operator, @min_temp
  )
    @min_temp = separate_collections(collection, col,
    is_max)
  end
  collection.each do |row|
    @min_temp_day = row[0] if row[col].to_i.eql?(@min_temp)
  end
end

def temperature_with_day_humid(collection, col, is_max, 
operator)
  if separate_collections(collection, col, is_max).public_send(
    operator, @max_humid
  )
    @max_humid = separate_collections(collection, col,
    is_max)
  end
  collection.each do |row|
    @max_humid_day = row[0] if row[col].to_i.eql?(@max_humid)
  end
end

显然,这三个函数中的代码块是相同的,如上所述。

有没有办法重构代码,避免重复,使用单个示例变量?

我还想使用最佳实践重构这些函数,避免“RuboCop”抛出错误。
最终,这三个示例变量中的每一个都应该返回一些值。

snz8szmq

snz8szmq1#

你能不能使用一个散列来代替,传递一个符号来指示你想要使用哪个值?类似这样,它将额外的值作为方法的第一个参数添加进来,这里称为type

def initialize
    @temp = { max: -440, min: 1000, humid: -500 }
    @temp_day = { max: 'fahad', min: 'fahad', humid: 'fahad' }
  end

...

  def temperature_with_day(type, collection, col, is_max, operator)
    if separete_collections(collection, col, is_max).public_send(
      operator, @temp[type]
    )
      @temp[type] = separete_collections(collection, col, is_max)
    end
    collection.each do |row|
      @temp_day = row[0] if row[col].to_i.eql?(@temp[type])
    end
  end

如果你仍然需要单独的方法来设置和返回这三个值,你可以显式地添加这些方法,而不是依赖于自动访问器,类似于这样:

def max_temp=(value)
  @temp[:max] = value
end

def max_t_day
  return @temp_day[:max]
end

等等。
(PS我认为,您的方法separete_collections应该被称为separate_collections--只是“separate”中的一个拼写错误!)

fcwjkofz

fcwjkofz2#

你可以用一些常量

SETTINGS = {
  max_temp: {
    col: 1,
    is_max: true,
    operator: :>
  },
  # ...
}

然后迭代它的

SETTINGS.each do |temp, opts|
  separete_collections = separete_collections(collection, opts[:col], opts[:is_max])

  if separete_collections.public_send(opts[:operator], public_send(temp))
    public_send("#{temp}=", separete_collections)
  end
end

if (row = collection.find { |row| row[col].to_i == @max_humid })
  public_send("#{temp}=", row[0])
end

相关问题