2

I'm creating a rails code that could add/remove field of a model.

I've a model Inventory, where I could add a list of fields as below:

def update_new_fields
  @fieldnames = params["fieldnames"]

  @fieldnames.each do |fieldname|
    ActiveRecord::Migration.add_column(Inventory, fieldname, :string)
  end    
end

To view list of updated fields

def index
  reload!
  @fields=Inventory.attribute_names
  respond_to do |format|
    format.html 
  end
end

However, I've got the following error:

undefined method `reload!' for #<InventoriesController:0x007fccf70b7720>

If I did a reload! in console:

2.0.0 :163 >   ActiveRecord::Migration.remove_column(Inventory, "f", :string)
-- remove_column(Inventory(id: integer, name: string, description: string, quatity: integer, created_at: datetime, updated_at: datetime, a: string, b: string, c: string, e: string, f: string), "f", :string)
   (122.9ms)  ALTER TABLE `inventories` DROP `f`
   -> 0.1232s
 => nil
2.0.0 :164 > Inventory.reset_column_information
 => nil
2.0.0 :165 > Inventory.attribute_names
 => ["id", "name", "description", "quatity", "created_at", "updated_at", "a", "b", "c", "e", "f"]
2.0.0 :166 > reload!
Reloading...
 => true
2.0.0 :167 > Inventory.attribute_names
 => ["id", "name", "description", "quatity", "created_at", "updated_at", "a", "b", "c", "e"]

It works.

UPD

What I've find out is, after foing a "Inventory.reset_column_information", the attribute_names were not updated but the Class information is:

2.0.0 :090 > Inventory.reset_column_information
 => nil
2.0.0 :091 > Inventory.attribute_names
 => ["id", "name", "description", "quatity", "created_at", "updated_at", "hello", "next"]
2.0.0 :092 > Inventory
 => Inventory(id: integer, name: string, description: string, quatity: integer, created_at: datetime, updated_at: datetime, a: string, b: string, c: string, d: string)

So, the work around I did was:

def index
  Inventory.reset_column_information
  tmp = Inventory.new
  @fields=tmp.attribute_names
  respond_to do |format|
    format.html 
  end
end

And finally my field in Inventory is updated.

Gavin Yap
  • 642
  • 12
  • 26
  • Some how when I did this, it works. ` def index Inventory.reset_column_information tmp = Inventory.new @fields=tmp.attribute_names respond_to do |format| format.html end end` – Gavin Yap Oct 13 '13 at 11:03

1 Answers1

2

Though I wonder why You need this, looks very odd. But what actually You are looking is to refresh model column information. It can be done like this:

Inventory.reset_column_information

UPD

Probably it's because the class is cached. You can reload a single class by using load

load "#{Rails.root}/app/models/inventory.rb"

Though it will spit out some warning about redefining. You could use remove_const method before actually loading again to avoid warnings.

remove_const "Inventory"
load "#{Rails.root}/app/models/inventory.rb"

But beware that doing this may cause errors in production environment. If You use several rails instances, that code would reload the class only on one! So think twice, maybe there are alternatives how to achieve what You are actually doing. I strongly not recommend going this path.

Edgars Jekabsons
  • 2,833
  • 15
  • 20
  • If you look at the bottom of my message, that's exactly what I've did. But I'd still have a "f" field with Inventory.reset_column_information. – Gavin Yap Oct 13 '13 at 10:42