Gavin Yap
Gavin Yap

Reputation: 762

Rails: Use reload! in controller

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.

Upvotes: 2

Views: 1861

Answers (1)

Edgars Jekabsons
Edgars Jekabsons

Reputation: 2853

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.

Upvotes: 2

Related Questions