seven1m / onebody

OneBody is free, open-source, web-based social networking and online directory software for churches.

This URL has Read+Write access

onebody / test / forgeries.rb
100644 180 lines (154 sloc) 4.902 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
require 'faker'
 
module Forgeable
  def forge(association, attributes={}, foreign_key=nil)
    foreign_key ||= self.class.name.downcase + '_id'
    attributes.merge!(foreign_key => self.id)
    eval(association.to_s.classify).forge(attributes)
  end
  
  def forge_photo(photo=true)
    if photo.is_a?(String)
      self.photo = File.open(photo)
    else
      self.photo = File.open(RAILS_ROOT + '/test/fixtures/files/image.jpg')
    end
  end
  
  def forge_file(file=true)
    if file.is_a?(String)
      self.file = File.open(file)
    else
      self.file = ActionController::TestUploadedFile.new(File.dirname(__FILE__) + '/fixtures/files/attachment.pdf', nil, false)
    end
  end
  
  def self.included(mod)
    mod.extend(ClassMethods)
    mod.class_eval <<-END
@@forgery_defaults = {}
def self.forgery_defaults=(defaults)
class_eval do
@@forgery_defaults = defaults
end
end
 
def self.forgery_defaults
defaults = {}
@@forgery_defaults.each do |key, val|
if val.respond_to? :call
defaults[key] = val.call
elsif val.is_a? Symbol
defaults[key] = self.fake(val)
else
defaults[key] = val
end
end
defaults
end
END
  end
  
  module ClassMethods
    
    def forge(attributes={})
      attributes.symbolize_keys!
      attributes = forgery_defaults.merge(attributes)
      photo = attributes.delete(:photo)
      file = attributes.delete(:file)
      begin
        returning create!(attributes) do |obj|
          obj.forge_photo(photo) if photo
          obj.forge_file(file) if file
        end
      rescue ActiveRecord::RecordInvalid => e
        if e.message =~ /^Validation failed: (.+) has already been taken/
          attributes[$1.downcase.to_sym] << 'a'
          retry
        else
          puts e.message
        end
      end
    end
    
    def fake(symbol)
      case symbol
      when :word
        Faker::Lorem.words(1).join
      when :sentence, :paragraph
        Faker::Lorem.send(symbol)
      when :email
        Faker::Internet.send(symbol)
      when :name
        "#{fake :first_name} #{fake :last_name}"
      when :first_name, :last_name
        Faker::Name.send(symbol)
      when :link
        "http://#{Faker::Internet.domain_name}"
      else
        raise 'Unrecognized faker symbol.'
      end
    end
    
  end
end
 
%w(Family Person Recipe Note Picture Verse Group Album Publication Tag NewsItem Comment PrayerRequest).each do |model|
  eval model
  eval "class #{model}; include Forgeable; end"
end
 
class Person
  def self.forge(attributes={})
    attributes.symbolize_keys!
    first_name = Faker::Name.first_name
    last_name = Faker::Name.last_name
    photo = attributes.delete(:photo)
    attributes[:family] ||= Family.forge(:name => "#{first_name} #{last_name}", :last_name => last_name)
    defaults = {:first_name => first_name, :last_name => last_name, :gender => 'Male', :visible_to_everyone => true, :visible => true, :can_sign_in => true, :full_access => true, :email => Faker::Internet.email, :encrypted_password => '5ebe2294ecd0e0f08eab7690d2a6ee69', :child => false}
    person = create!(defaults.merge(attributes))
    person.forge_photo if photo
    person
  end
  
  def forge_blog
    # must be set for the logger to correctly mark these entries
    Person.logged_in = self
    # 26 total - blog only shows 25
    1.times { self.forge(:pictures) }
    10.times { self.forge(:notes) }
    10.times { self.forge(:recipes) }
    5.times { self.verses << Verse.forge; self.save }
  end
end
 
class Group
  self.forgery_defaults = {:name => :word, :category => :word, :approved => true}
end
 
class Family
  self.forgery_defaults = {:name => :name, :last_name => :last_name}
end
 
class Recipe
  self.forgery_defaults = {:title => :word, :ingredients => :paragraph, :directions => :paragraph}
end
 
class Note
  self.forgery_defaults = {:title => :word, :body => :paragraph}
end
 
class Picture
  self.forgery_defaults = {:photo => true, :album_id => Proc.new { Album.forge.id }}
end
 
class Album
  self.forgery_defaults = {:name => :word}
end
 
class Publication
  self.forgery_defaults = {:name => :word, :description => :paragraph, :file => true}
end
 
class NewsItem
  self.forgery_defaults = {:title => :sentence, :link => :link}
end
 
class Verse
  def self.forge(attributes={})
    returning Verse.find("#{Verse::BOOKS.rand} #{rand(25)+1}:#{rand(50)+1}") do |verse|
      attributes.each do |attr, val|
        verse.send("#{attr}=", val) # will allow tag_list= to work
      end
      verse.save!
    end
  end
end
 
class Tag
  self.forgery_defaults = {:name => :word}
end
 
class Comment
  self.forgery_defaults = {:text => :sentence}
end
 
class PrayerRequest
  self.forgery_defaults = {:request => :sentence, :answer => :sentence, :answered_at => Time.now}
end