Rails替换数组中的属性

时间:2009-12-08 06:57:08

标签: ruby-on-rails

我在菲律宾有一个错误的城市名称列表:

>> a = City.find_all_by_country_id(4)

=> [#<City id: 91, name: "Alaminos", country_id: 4, created_at: "2009-11-12 04:06:14", updated_at: "2009-11-12 04:06:14">, #<City id: 92, name: "Angeles", country_id: 4, created_at: "2009-11-12 04:06:14", ...

我想用正确的名字替换所有名字:

=> b = ["Abra", "Agusan del Norte", "Agusan del Sur", ...

我想使用replace方法,因为我想更新现有的城市ID,只在必要时插入/截断它们。

但我仍然无法弄清楚这一点,因为a是一个数组数组(如果我错了,请纠正我),而b只是一个简单的,脚踏实地的数组

3 个答案:

答案 0 :(得分:0)

a应该是一系列City模型。例如,如果您想要将城市ID 91(第一条记录)的城市名称更改为“Abra”(数组中的第一个元素),您只需a[0].name = b[0]。我有点不清楚你究竟想要做什么,但希望这会让你了解问题的语法部分。

答案 1 :(得分:0)

请查看Array#zipActiveRecord::Base#update_attribute。正如Andy Gaskell所指出的,a是一系列City对象。因此可以在a上调用zip,并且可以在。

的任何元素上调用update_attribute

做你想做的事的简单方法就是:

a.zip(b){|array| array[0].update_attribute(:name, array[1])}

Zip会将多个数组转换为数组数组。其中新数组的每个索引都是由同一索引的源数组中的元素组成的数组。

a.zip(b) = c #=> ∀i: c[i] = [a[i],b[i]]

如果将块传递给zip,Ruby会将c中的每个数组放到块中。这是a.zip(b).collect(&block)的便捷捷径。

在上面的代码array[0] = a[i]array[1] = b[i]中,每次迭代都会提供不同的i值。 update_attributes将绕过验证和回调更新数据库中的记录。

警告:

  • 如果b有更多元素,那么你将得到No Method Errors。
  • 如果a的元素多于b,则额外元素的名称将设置为“”。
  • 同样,Update_attributes会绕过验证并自动保存更新的记录。如果你不喜欢这样,你可以用以下内容替换块的内部:

    array[0].name = array[1]; array[0].save
    

答案 2 :(得分:0)

我决定使用迁移文件,因此这是代码:

class AddProvinces < ActiveRecord::Migration
  def self.up
    philippines = Country.find_by_name('Philippines')
    old_cities = philippines.cities
    new_cities = (['Abra', 'Agusan del Norte', 'And all the cities...'])

    old_cities.each do |c|
      unless new_cities.blank?
        City.update(c.id, :name => new_cities.first)
        new_cities.delete(new_cities.first)
      else
        City.delete(c.id)
      end
    end

    unless new_cities.blank?
      new_cities.each do |c|
        City.create(:name => c, :country_id => 'philippines.id')
      end
    end
  end

  def self.down
  end
end