Where to put helper functions for rake tasks and test files in Ruby on Rails?
Asked Answered
C

3

12

In my Rails application I have a file sample_data.rb inside /lib/tasks as well as a bunch of test files inside my /spec directory.

All these files often share common functionality such as:

def random_address
  [Faker::Address.street_address, Faker::Address.city].join("\n")
end

Where should I put those helper functions? Is there some sort of convention on this?

Thanks for any help!

Conceptacle answered 1/3, 2013 at 17:43 Comment(1)
What does this have to do with rake? All I see are .rb files. This is a misleading title.Cladoceran
K
10

You could create a static class, with static functions. That would look something like this:

class HelperFunctions

     def self.random_address
          [Faker::Address.street_address, Faker::Address.city].join("\n")
     end

     def self.otherFunction
     end
end

Then, all you would need to do is:

  1. include your helper class in the file you want to use
  2. execute it like:

    HelperFunctions::random_address(anyParametersYouMightHave)
    

When doing this, make sure you include any dependencies in your HelperFunctions class.

Kusin answered 1/3, 2013 at 21:43 Comment(3)
Thanks for your help! In what directory would you put that class?Conceptacle
It's up to you. I'd probably put it in the controller directory.Kusin
Nooooo not the controller directory. This is exactly why there is a lib folder. The app/controllers folder should only contain controllers.Ascanius
B
7

If you're sure it's rake only specific, you also can add in directly in RAILS_ROOT/Rakefile (that's probably not the case for the example you use).

I use this to simplify rake's invoke syntax :

#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path('../config/application', __FILE__)

def invoke( task_name )
  Rake::Task[ task_name ].invoke
end

MyApp::Application.load_tasks

That way, I can use invoke "my_namespace:my_task" in rake tasks instead of Rake::Task[ "my_namespace:my_task" ].invoke.

Buyse answered 28/5, 2013 at 14:23 Comment(1)
Exactly why I ended up here! Wanted to know where to put a wrapper for Rake::Task['namespace:task'].reenable; Rake::Task['namespace:task'].invoke.Varrian
A
1

You share methods in a module, and you place such a module inside the lib folder.

Something like lib/fake_data.rb containing

module FakeData
  def random_address
    [Faker::Address.street_address, Faker::Address.city].join("\n")
  end

  module_function 
end

and inside your rake task just require the module, and call FakeData.random_address.

But, if it is like a seed you need to do every time you run your tests, you should consider adding this to your general before all.

E.g. my spec_helper looks like this:

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }

RSpec.configure do |config|
  config.use_transactional_fixtures = true
  config.infer_base_class_for_anonymous_controllers = false
  config.order = "random"

  include SetupSupport

  config.before(:all) do
    load_db_seed
  end
end

and the module SetupSupport is defined in spec/support/setup_support.rb and looks as follows:

module SetupSupport

  def load_db_seed
    load(File.join(Rails.root, 'db', 'seeds.rb'))
  end

end

Not sure if you need to load the seeds, or are already doing this, but this is the ideal spot to also generate needed fake data.

Note that my setup support class is defined in spec/support because the code is only relevant to my specs, I have no rake task also needing the same code.

Ascanius answered 25/11, 2013 at 10:13 Comment(1)
in order to make your FakeData module example code work, it would appear the module_function statement should be inserted before defining the random_address function, rather than after.Jenkins

© 2022 - 2024 — McMap. All rights reserved.