I wanted to be able to auto-generate FactoryGirl factories from my database, so this task will do that, using Faker to give you fake data.
require 'erb'
task :factory_girl_translate, [:model] => [:environment] do |t, args|
puts FactoryTemplate.new(model: args[:model]).render
end
class FactoryTemplate
def initialize(model:)
@klass = model.classify.constantize
@model = model
@attributes = @klass.attribute_names
end
def render
ERB.new(template, nil, '-').result binding
end
private
def template
<<-EOF
FactoryGirl.define do
factory :<%= @model %>, class: <%= @klass.to_s -%> do
<%- @attributes.each do |attr| -%>
<%= attr -%> { <%= example_for attr -%> }
<%- end -%>
end
end
EOF
end
def example_for(attr)
case type_for attr
when :integer then 'Faker::Number.number'
when :string then 'Faker::Lorem.word'
when :text then 'Faker::Lorem.sentence'
when :datetime then 'Faker::Date.backward(365)'
when :json then "{ test: 'json' }.to_json"
else attr
end
end
def type_for(attr)
@klass.columns_hash[attr].type.to_sym
end
end
Then, $ rake factory_girl_translate[user]
will generate a factory like this:
FactoryGirl.define do
factory :user, class: User do
id { Faker::Number.number }
team_id { Faker::Number.number }
email { Faker::Lorem.word }
first_name { Faker::Lorem.word }
last_name { Faker::Lorem.word }
facebook_token { Faker::Lorem.word }
facebook_uid { Faker::Lorem.word }
password_digest { Faker::Lorem.word }
access_token { Faker::Lorem.word }
created_at { Faker::Date.backward(365) }
updated_at { Faker::Date.backward(365) }
metadata { { test: 'json' }.to_json }
google_token { Faker::Lorem.word }
google_refresh_token { Faker::Lorem.word }
google_customer_id { Faker::Lorem.word }
zip_code { Faker::Lorem.word }
end
end