Ryan Clarke
Ryan Clarke

Reputation: 3

Rails create a method accessible via both the model and controller

Is there anyway to create a function I can call both in the model and controller? I have a function that grabs an array of files and strips the extension off and want to validate against the list. However I also want access to this list in the controller so I can output a select box for the options. I currently have this, however the VALID_MODULES doesnt get populated all the time.

class Job < ActiveRecord::Base

  after_initialize :init
  VALID_MODULES =[];

  validates :name, presence: true
  validates :desc, presence: true
  validates :api, presence: true, :inclusion => { :in => VALID_MODULES}
  validates :filters, presence: true
  validates :toe, presence: true

  def init
    Dir.foreach('lib/resources') do |item|
         next if item == '.' or item == '..' or item == 'resource.rb'
            #Wont be called very often so O(n) complexity is fine (small #elements)
            VALID_MODULES.push(item[0..-4]) unless VALID_MODULES.include?(item[0..-4])
    end
  end

end

Upvotes: 0

Views: 509

Answers (2)

Peter P.
Peter P.

Reputation: 3507

# in config/initializers/api_modules.rb
module ApiModules
  def self.modules
    # the Dir[""] glob syntax here I believe exclude dot directories
    # but I still like the Array#include? syntax here for your exclusions list
    # you may need to massage the strings of your file list to be more appropriate to your case
    @modules ||= Dir["lib/*"].select{|f| !["resource.rb"].include?(f) } 
  end
end

#app/models/job.rb
validates :api, presence: true, :inclusion => { :in => ApiModules.modules}

Upvotes: 0

johnnycakes
johnnycakes

Reputation: 2450

Instead of using a constant (VALID_MODULES), try making it an attribute of your job.

class Job < ActiveRecord::Base

  attr_accessor :valid_modules
  after_initialize :init


  validates :name, presence: true
  validates :desc, presence: true
  validates :api, presence: true, :inclusion => { :in => VALID_MODULES}
  validates :filters, presence: true
  validates :toe, presence: true

  def init
    @valid_modules ||= []
    Dir.foreach('lib/resources') do |item|
         next if ['.', '..', 'resource.rb'].include?(item)
         #Wont be called very often so O(n) complexity is fine (small #elements)
         @valid_modules << item[0..-4] unless @valid_modules.include?(item[0..-4])
    end
  end

end

Now in your controller you can just call valid_modules on your Job object to return the array. Example:

job = Job.new
job.valid_modules

Upvotes: 1

Related Questions