0

I'm trying to provide an interface to "pre-load" a table from a spreadsheet file. Sounds simple, but I'm making heavy weather of it, being a complete novice. I have used the action_view helper asset_path to locate the file after it is precompiled in assets, but it seems that I am not including the helpers properly, because I keep getting "NoMethodError: undefined method `asset_path' for #". Here is my model code:

require 'rubygems'
require 'roo' 
require 'action_view'

class Item < ActiveRecord::Base
  include ActionView::Helpers
  validates :description, presence: true, length: { maximum: 240 }
  validates :category, presence: true
  has_many :interests
  has_many :members, through: :interests
end

def populate_items_table
  from_file = asset_path("item_listing.ods")
  original_list = Openoffice.new(from_file)
  original_list.default_sheet = original_list.sheets.first
  headers = original_list.row(1)
  ...
end

I would be most grateful if anyone can point out where I am going wrong here. Also, am I going about this in the "Rails way"? Should this sort of code be in the model or somewhere else? I am guessing somewhere else, otherwise the appropriate helpers would probably already be defined?

There are similar questions on the stack here, e.g. 1 , but the answers don't seem to be any different to what I am doing.

@shishir: here is the stack trace when including the specific module as suggested:

ERROR["test_should_reload_items_table", ItemsControllerTest, 2016-03-22 08:43:53 +0000] test_should_reload_items_table#ItemsControllerTest (1458636233.20s) NoMethodError: NoMethodError: undefined method asset_path' for #<ItemsController:0x000000097cb308> app/models/item.rb:14:inpopulate_items_table' app/controllers/items_controller.rb:67:in reload' test/controllers/items_controller_test.rb:53:inblock in ' app/models/item.rb:14:in populate_items_table' app/controllers/items_controller.rb:67:inreload' test/controllers/items_controller_test.rb:53:in `block in '

Community
  • 1
  • 1
FBtLL
  • 1
  • 1
  • 2

2 Answers2

0

asset_path is defined in ActionView::Helpers::AssetUrlHelper which is a module. use

 include ActionView::Helpers::AssetUrlHelper

instead of

 include ActionView::Helpers
Shishir
  • 780
  • 4
  • 9
  • I tried this before, and get "ActionView::Template::Error: undefined method `errors' for nil:NilClass". I figured that by including all helpers I was more likely to include everything that the more specific module depended on? – FBtLL Mar 31 '16 at 00:58
  • Can paste the stack trace for errors for nil class? – Shishir Mar 31 '16 at 01:12
  • My apologies, I rushed into that response. The ActionView::Template::Error was not related, I had tried to progress in other areas, and this error relates to stuff that isn't built yet... I have now posted the corrrect trace from the test of the model code, and it is still reporting undefined_method. – FBtLL Mar 31 '16 at 01:53
  • Include ActionView::Helpers::AssetUrlHelper in the ItemsController where populate_items_table. Its not mixed in by default in controllers. – Shishir Mar 31 '16 at 02:25
  • That's why I put populate_items_table in the model, not the controller. Fat models, thin controllers. The controller only calls the class method. – FBtLL Mar 31 '16 at 10:53
  • undefined method asset_path' for #. This made me believe that asset_path was called from within controller. If you have mixed in ActionView::Helpers::AssetUrlHelper in item.rb. Can you open console and try to call Item populate_items_table on item. It should not give asset_path error there. It might fail saying "file not found" or something. – Shishir Apr 01 '16 at 04:47
0
class Item < ActiveRecord::Base
    include ActionView::Helpers
    validates :description, presence: true, length: { maximum: 240 }
    validates :category, presence: true
    has_many :interests
    has_many :members, through: :interests

    def populate_items_table
      from_file = asset_path("item_listing.ods")
      original_list = Openoffice.new(from_file)
      original_list.default_sheet = original_list.sheets.first
      headers = original_list.row(1)
      ...
    end

end

If I understand correctly, your function won't work if it isn't inside the class.

Irrespective, you need to include ActionView::Helpers in such a way that it reaches the asset_path call, which it currently doesn't (as it is segregated in the Class, which is in a different scope currently to the function you've declared.)

  • Now I'm very confused. What do you mean, my function won't work if it isn't inside the class? It is inside the Item class, isn't it? And that's where I've included the helpers. How should I include the helpers? I'm only following examples submitted by others for similar questions. – FBtLL Mar 31 '16 at 05:51