sugoi-mail 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) hide show
  1. data/README +35 -0
  2. data/Rakefile +10 -0
  3. data/app/apis/mailservice_api.rb +178 -0
  4. data/app/controllers/.sugoi_admin_controller.rb.swp +0 -0
  5. data/app/controllers/account_controller.rb +39 -0
  6. data/app/controllers/address_controller.rb +49 -0
  7. data/app/controllers/application.rb +4 -0
  8. data/app/controllers/commandline_controller.rb +15 -0
  9. data/app/controllers/domain_controller.rb +37 -0
  10. data/app/controllers/mailinglist_controller.rb +51 -0
  11. data/app/controllers/mailservice_controller.rb +497 -0
  12. data/app/controllers/sugoi_admin_controller.rb +93 -0
  13. data/app/helpers/account_helper.rb +2 -0
  14. data/app/helpers/address_helper.rb +2 -0
  15. data/app/helpers/application_helper.rb +3 -0
  16. data/app/helpers/domain_helper.rb +2 -0
  17. data/app/helpers/mailservice_helper.rb +2 -0
  18. data/app/helpers/sugoi_admin_helper.rb +2 -0
  19. data/app/models/address.rb +110 -0
  20. data/app/models/admin_message.rb +45 -0
  21. data/app/models/confirmationcode.rb +59 -0
  22. data/app/models/domain.rb +76 -0
  23. data/app/models/mailinglist.rb +336 -0
  24. data/app/models/mailinglist_class.rb +39 -0
  25. data/app/models/message.rb +293 -0
  26. data/app/models/proxy_link.rb +25 -0
  27. data/app/models/user.rb +150 -0
  28. data/app/views/account/login.rhtml +22 -0
  29. data/app/views/account/logout.rhtml +10 -0
  30. data/app/views/account/signup.rhtml +17 -0
  31. data/app/views/account/welcome.rhtml +13 -0
  32. data/app/views/address/_form.rhtml +7 -0
  33. data/app/views/address/edit.rhtml +10 -0
  34. data/app/views/address/list.rhtml +27 -0
  35. data/app/views/address/new.rhtml +8 -0
  36. data/app/views/address/show.rhtml +8 -0
  37. data/app/views/domain/login.rhtml +22 -0
  38. data/app/views/domain/logout.rhtml +10 -0
  39. data/app/views/domain/signup.rhtml +17 -0
  40. data/app/views/domain/welcome.rhtml +13 -0
  41. data/app/views/layouts/address.rhtml +13 -0
  42. data/app/views/layouts/scaffold.rhtml +13 -0
  43. data/app/views/mailinglist/_form.rhtml +28 -0
  44. data/app/views/mailinglist/edit.rhtml +10 -0
  45. data/app/views/mailinglist/list.rhtml +27 -0
  46. data/app/views/mailinglist/new.rhtml +8 -0
  47. data/app/views/mailinglist/show.rhtml +16 -0
  48. data/app/views/sugoi_admin/create_domain.rhtml +1 -0
  49. data/app/views/sugoi_admin/list_addresses.rhtml +1 -0
  50. data/app/views/sugoi_admin/list_domains.rhtml +2 -0
  51. data/app/views/sugoi_admin/list_mailinglists.rhtml +1 -0
  52. data/bin/mailc +32 -0
  53. data/bin/maild +133 -0
  54. data/bin/sugoi-admin +21 -0
  55. data/bin/sugoi-mail +20 -0
  56. data/config/boot.rb +44 -0
  57. data/config/environment.rb +54 -0
  58. data/config/environments/bench.rb +21 -0
  59. data/config/environments/coverage.rb +21 -0
  60. data/config/environments/development.rb +21 -0
  61. data/config/environments/production.rb +18 -0
  62. data/config/environments/test.rb +19 -0
  63. data/config/lighttpd.conf +46 -0
  64. data/config/routes.rb +29 -0
  65. data/db/migrate/001_mailproxy.rb +7 -0
  66. data/db/migrate/002_create_users.rb +13 -0
  67. data/db/migrate/003_create_mailinglists.rb +13 -0
  68. data/db/migrate/004_create_addresses.rb +12 -0
  69. data/db/migrate/005_create_addresses_mailinglists.rb +13 -0
  70. data/db/migrate/006_alter_mailinglists.rb +9 -0
  71. data/db/migrate/007_create_messages.rb +25 -0
  72. data/db/migrate/008_add_mailinglistid_to_users.rb +14 -0
  73. data/db/migrate/009_add_domainadmin_to_users.rb +9 -0
  74. data/db/migrate/010_add_domain_to_users.rb +16 -0
  75. data/db/migrate/011_add_active_to_addresses.rb +14 -0
  76. data/db/migrate/012_create_confirmationcodes.rb +14 -0
  77. data/db/migrate/013_add_description_to_mailinglists.rb +9 -0
  78. data/db/migrate/014_create_admin_messages.rb +69 -0
  79. data/db/migrate/015_add_messages_to_mailinglists.rb +26 -0
  80. data/db/migrate/016_add_mailinglist_admin_to_users.rb +9 -0
  81. data/db/migrate/017_add_mailinglist_types.rb +94 -0
  82. data/db/migrate/018_add_bounciness_to_addresses.rb +20 -0
  83. data/db/migrate/019_add_archived_to_mailinglist_classes.rb +25 -0
  84. data/db/migrate/020_add_envelope_data_to_messages.rb +11 -0
  85. data/db/migrate/021_add_addresses_users.rb +14 -0
  86. data/db/migrate/022_add_virtual_to_users.rb +14 -0
  87. data/db/migrate/023_drop_openposting_from_mailinglists.rb +9 -0
  88. data/db/migrate/024_add_proxy_links.rb +21 -0
  89. data/db/migrate/025_add_proxify_to_mailinglist_classes.rb +25 -0
  90. data/db/schema.mysql.sql +104 -0
  91. data/db/schema.postgresql.sql +104 -0
  92. data/db/schema.rb +85 -0
  93. data/db/schema.sqlite.sql +104 -0
  94. data/db/schema.sqlserver.sql +113 -0
  95. data/db/schema_version +1 -0
  96. data/doc/README_FOR_APP +179 -0
  97. data/doc/mailinglist_classes description.txt +28 -0
  98. data/installer/rails_installer_defaults.yml +5 -0
  99. data/lib/daemonize.rb +56 -0
  100. data/lib/domain_system.rb +87 -0
  101. data/lib/gurgitate-rules.rb +69 -0
  102. data/lib/limitedfork.rb +66 -0
  103. data/lib/login_system.rb +87 -0
  104. data/public/.htaccess +40 -0
  105. data/public/404.html +8 -0
  106. data/public/500.html +8 -0
  107. data/public/dispatch.cgi +10 -0
  108. data/public/dispatch.fcgi +24 -0
  109. data/public/dispatch.rb +10 -0
  110. data/public/favicon.ico +0 -0
  111. data/public/images/rails.png +0 -0
  112. data/public/javascripts/application.js +2 -0
  113. data/public/javascripts/controls.js +815 -0
  114. data/public/javascripts/dragdrop.js +913 -0
  115. data/public/javascripts/effects.js +958 -0
  116. data/public/javascripts/prototype.js +2006 -0
  117. data/public/robots.txt +1 -0
  118. data/public/stylesheets/scaffold.css +74 -0
  119. data/public/stylesheets/trestle.css +74 -0
  120. data/script/about +3 -0
  121. data/script/breakpointer +3 -0
  122. data/script/console +3 -0
  123. data/script/destroy +3 -0
  124. data/script/fakedeliver +19 -0
  125. data/script/generate +3 -0
  126. data/script/performance/benchmarker +3 -0
  127. data/script/performance/profiler +3 -0
  128. data/script/plugin +3 -0
  129. data/script/process/reaper +3 -0
  130. data/script/process/spawner +3 -0
  131. data/script/runner +3 -0
  132. data/script/server +3 -0
  133. data/sugoi-mail.gemspec +36 -0
  134. data/test/fixtures/addresses.yml +70 -0
  135. data/test/fixtures/addresses_mailinglists.yml +20 -0
  136. data/test/fixtures/admin_messages.yml +65 -0
  137. data/test/fixtures/confirmationcodes.yml +13 -0
  138. data/test/fixtures/domains.yml +9 -0
  139. data/test/fixtures/mailinglist_classes.yml +45 -0
  140. data/test/fixtures/mailinglists.yml +80 -0
  141. data/test/fixtures/messages.yml +154 -0
  142. data/test/fixtures/proxy_links.yml +5 -0
  143. data/test/fixtures/users.yml +50 -0
  144. data/test/functional/domain_controller_test.rb +74 -0
  145. data/test/functional/mailservice_controller_test.rb +546 -0
  146. data/test/integration/test_soap.rb +413 -0
  147. data/test/integration/test_xmlrpc.rb +198 -0
  148. data/test/mocks/test/net-smtp-stub.rb +24 -0
  149. data/test/test_helper.rb +28 -0
  150. data/test/unit/address_test.rb +44 -0
  151. data/test/unit/admin_message_test.rb +41 -0
  152. data/test/unit/confirmationcode_test.rb +64 -0
  153. data/test/unit/domain_test.rb +128 -0
  154. data/test/unit/mailinglist_class_test.rb +82 -0
  155. data/test/unit/mailinglist_test.rb +145 -0
  156. data/test/unit/message_test.rb +151 -0
  157. data/test/unit/user_test.rb +126 -0
  158. data/test/units.rb +4 -0
  159. data/vendor/plugins/active_command/init.rb +1 -0
  160. data/vendor/plugins/active_command/lib/active_command/request.rb +137 -0
  161. data/vendor/plugins/active_command/lib/active_command/response.rb +132 -0
  162. data/vendor/plugins/active_command/lib/active_command.rb +2 -0
  163. data/vendor/plugins/ar_fixtures/CHANGELOG +10 -0
  164. data/vendor/plugins/ar_fixtures/MIT-LICENSE +20 -0
  165. data/vendor/plugins/ar_fixtures/README +19 -0
  166. data/vendor/plugins/ar_fixtures/Rakefile +54 -0
  167. data/vendor/plugins/ar_fixtures/about.yml +7 -0
  168. data/vendor/plugins/ar_fixtures/init.rb +1 -0
  169. data/vendor/plugins/ar_fixtures/lib/ar_fixtures.rb +102 -0
  170. data/vendor/plugins/ar_fixtures/tasks/ar_fixtures.rake +39 -0
  171. data/vendor/plugins/ar_fixtures/test/ar_fixtures_test.rb +53 -0
  172. data/vendor/plugins/ar_fixtures/test/database.yml +18 -0
  173. data/vendor/plugins/ar_fixtures/test/fixtures/beer.rb +5 -0
  174. data/vendor/plugins/ar_fixtures/test/fixtures/beers.yml +9 -0
  175. data/vendor/plugins/ar_fixtures/test/fixtures/beers_drunkards.yml +8 -0
  176. data/vendor/plugins/ar_fixtures/test/fixtures/drunkard.rb +6 -0
  177. data/vendor/plugins/ar_fixtures/test/fixtures/drunkards.yml +8 -0
  178. data/vendor/plugins/ar_fixtures/test/fixtures/glass.rb +2 -0
  179. data/vendor/plugins/ar_fixtures/test/fixtures/glasses.yml +9 -0
  180. data/vendor/plugins/ar_fixtures/test/schema.rb +21 -0
  181. data/vendor/plugins/ar_fixtures/test/test_helper.rb +37 -0
  182. metadata +320 -0
@@ -0,0 +1,126 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ # Set salt to 'change-me' because thats what the fixtures assume.
4
+ # User.salt = 'change-me'
5
+
6
+ class UserTest < Test::Unit::TestCase
7
+ fixtures :users, :domains
8
+
9
+ def setup
10
+ @testuser = User.find 1
11
+ @users=@loaded_fixtures["users"]
12
+ @user_testuser=@users["testuser"]
13
+ end
14
+
15
+ def test_aa_break_everything
16
+ @testuser.destroy
17
+ assert_raise ActiveRecord::RecordNotFound do
18
+ User.find @testuser.id
19
+ end
20
+ end
21
+
22
+ def test_find
23
+ user_1 = User.find 1
24
+ assert user_1
25
+
26
+ assert_equal @user_testuser["login"], user_1.login
27
+ assert_equal @user_testuser["password"], user_1.password
28
+ assert_equal @user_testuser["id"], user_1.mailinglist_id
29
+ end
30
+
31
+ def test_auth_notfound
32
+ assert_nil User.authenticate("nontestuser", "foobar")
33
+ end
34
+
35
+ def test_auth
36
+
37
+ user_1 = User.find 1
38
+ assert user_1
39
+
40
+ user_testuser = User.authenticate "testuser", "foobar"
41
+ assert user_testuser
42
+
43
+ assert_equal user_1, user_testuser
44
+ end
45
+
46
+ def test_disallowed_passwords
47
+
48
+ u = User.new
49
+ u.login = "nonbob"
50
+ u.domain_id=1
51
+
52
+ u.password = u.password_confirmation = "tiny"
53
+ assert !u.save
54
+ assert u.errors.invalid?('password')
55
+
56
+ u.password = u.password_confirmation = "hugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehugehuge"
57
+ assert !u.save
58
+ assert u.errors.invalid?('password')
59
+
60
+ u.password = u.password_confirmation = ""
61
+ assert !u.save
62
+ assert u.errors.invalid?('password')
63
+
64
+ u.password = u.password_confirmation = "bobs_secure_password"
65
+ assert u.save
66
+ # assert u.errors.empty?
67
+
68
+ end
69
+
70
+ def test_bad_logins
71
+
72
+ u = User.new
73
+ u.domain_id=1
74
+ u.password = u.password_confirmation = "bobs_secure_password"
75
+
76
+ u.login = "x"
77
+ assert !u.save
78
+ assert u.errors.invalid?('login')
79
+
80
+ u.login = "hugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhugebobhug"
81
+ assert !u.save
82
+ assert u.errors.invalid?('login')
83
+
84
+ u.login = ""
85
+ assert !u.save
86
+ assert u.errors.invalid?('login')
87
+
88
+ u.login = "okbob"
89
+ assert u.save
90
+ # assert u.errors.empty?
91
+
92
+ end
93
+
94
+
95
+ def test_collision
96
+ u = User.new
97
+ u.login = "testuser"
98
+ u.domain_id = 1
99
+ u.password = u.password_confirmation = "bobs_secure_password"
100
+ assert !u.save
101
+ end
102
+
103
+
104
+ def test_create
105
+ u = User.new
106
+ u.login = "nonexistingbob"
107
+ u.domain_id = 1
108
+ u.password = u.password_confirmation = "bobs_secure_password"
109
+
110
+ assert u.save
111
+
112
+ assert u.mailinglist_id
113
+ end
114
+
115
+ def test_sha1
116
+ u = User.new
117
+ u.login = "nonexistingbob"
118
+ u.domain_id=1
119
+ u.password = u.password_confirmation = "bobs_secure_password"
120
+ assert u.save
121
+
122
+ assert_equal '826005bc4b82d02a3e6097556a45083375fe556c', u.password
123
+ end
124
+
125
+
126
+ end
data/test/units.rb ADDED
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+ Dir["unit/*.rb"].each do |file|
3
+ require file.sub(/.rb$/,'')
4
+ end
@@ -0,0 +1 @@
1
+ require "active_command"
@@ -0,0 +1,137 @@
1
+ module ActionController
2
+ class CommandlineSession #:nodoc:
3
+ def initialize(attributes = {})
4
+ @attributes = attributes
5
+ end
6
+
7
+ def [](key)
8
+ @attributes[key]
9
+ end
10
+
11
+ def []=(key, value)
12
+ @attributes[key] = value
13
+ end
14
+
15
+ def session_id
16
+ ""
17
+ end
18
+
19
+ def update() end
20
+ def close() end
21
+ def delete() @attributes = {} end
22
+ end
23
+
24
+ class CommandlineRequest < AbstractRequest
25
+ attr_accessor :cookies, :session_options
26
+ attr_accessor :query_parameters, :request_parameters, :path, :session, :env
27
+ attr_accessor :host
28
+
29
+ def initialize(action, *args)
30
+ @parameters = { "action" => action,
31
+ "args" => args.flatten }
32
+
33
+ @session = session || CommandlineSession.new
34
+
35
+ initialize_containers
36
+ initialize_default_values
37
+
38
+ super()
39
+ end
40
+
41
+ def reset_session
42
+ @session = {}
43
+ end
44
+
45
+ def raw_post
46
+ if raw_post = env['RAW_POST_DATA']
47
+ raw_post
48
+ else
49
+ params = self.request_parameters.dup
50
+ %w(controller action only_path).each do |k|
51
+ params.delete(k)
52
+ params.delete(k.to_sym)
53
+ end
54
+
55
+ params.map { |k,v| [ CGI.escape(k.to_s), CGI.escape(v.to_s) ].join('=') }.sort.join('&')
56
+ end
57
+ end
58
+
59
+ def port=(number)
60
+ @env["SERVER_PORT"] = number.to_i
61
+ @port_as_int = nil
62
+ end
63
+
64
+ def action=(action_name)
65
+ @query_parameters.update({ "action" => action_name })
66
+ @parameters = nil
67
+ end
68
+
69
+ # Used to check AbstractRequest's request_uri functionality.
70
+ # Disables the use of @path and @request_uri so superclass can handle those.
71
+ def set_REQUEST_URI(value)
72
+ @env["REQUEST_URI"] = value
73
+ @request_uri = nil
74
+ @path = nil
75
+ end
76
+
77
+ def request_uri=(uri)
78
+ @request_uri = uri
79
+ @path = uri.split("?").first
80
+ end
81
+
82
+ def remote_addr=(addr)
83
+ @env['REMOTE_ADDR'] = addr
84
+ end
85
+
86
+ def remote_addr
87
+ @env['REMOTE_ADDR']
88
+ end
89
+
90
+ def request_uri
91
+ @request_uri || super()
92
+ end
93
+
94
+ def path
95
+ @path || super()
96
+ end
97
+
98
+ def assign_parameters(controller_path, action, parameters)
99
+ parameters = parameters.symbolize_keys.merge(:controller => controller_path, :action => action)
100
+ extra_keys = ActionController::Routing::Routes.extra_keys(parameters)
101
+ non_path_parameters = get? ? query_parameters : request_parameters
102
+ parameters.each do |key, value|
103
+ if value.is_a? Fixnum
104
+ value = value.to_s
105
+ elsif value.is_a? Array
106
+ value = ActionController::Routing::PathComponent::Result.new(value)
107
+ end
108
+
109
+ if extra_keys.include?(key.to_sym)
110
+ non_path_parameters[key] = value
111
+ else
112
+ path_parameters[key.to_s] = value
113
+ end
114
+ end
115
+ end
116
+
117
+ def recycle!
118
+ self.request_parameters = {}
119
+ self.query_parameters = {}
120
+ self.path_parameters = {}
121
+ @request_method, @accepts, @content_type = nil, nil, nil
122
+ end
123
+
124
+ private
125
+ def initialize_containers
126
+ @env, @cookies = {}, {}
127
+ end
128
+
129
+ def initialize_default_values
130
+ @host = "test.host"
131
+ @request_uri = "/"
132
+ self.remote_addr = "0.0.0.0"
133
+ @env["SERVER_PORT"] = 80
134
+ @env['REQUEST_METHOD'] = "GET"
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,132 @@
1
+ module ActionController
2
+ class CommandlineResponse < AbstractResponse
3
+
4
+ # the response code of the request
5
+ def response_code
6
+ headers['Status'][0,3].to_i rescue 0
7
+ end
8
+
9
+ # returns a String to ensure compatibility with Net::HTTPResponse
10
+ def code
11
+ headers['Status'].to_s.split(' ')[0]
12
+ end
13
+
14
+ def message
15
+ headers['Status'].to_s.split(' ',2)[1]
16
+ end
17
+
18
+ # was the response successful?
19
+ def success?
20
+ response_code == 200
21
+ end
22
+
23
+ # was the URL not found?
24
+ def missing?
25
+ response_code == 404
26
+ end
27
+
28
+ # were we redirected?
29
+ def redirect?
30
+ (300..399).include?(response_code)
31
+ end
32
+
33
+ # was there a server-side error?
34
+ def error?
35
+ (500..599).include?(response_code)
36
+ end
37
+
38
+ alias_method :server_error?, :error?
39
+
40
+ # returns the redirection location or nil
41
+ def redirect_url
42
+ redirect? ? headers['location'] : nil
43
+ end
44
+
45
+ # does the redirect location match this regexp pattern?
46
+ def redirect_url_match?( pattern )
47
+ return false if redirect_url.nil?
48
+ p = Regexp.new(pattern) if pattern.class == String
49
+ p = pattern if pattern.class == Regexp
50
+ return false if p.nil?
51
+ p.match(redirect_url) != nil
52
+ end
53
+
54
+ # returns the template path of the file which was used to
55
+ # render this response (or nil)
56
+ def rendered_file(with_controller=false)
57
+ unless template.first_render.nil?
58
+ unless with_controller
59
+ template.first_render
60
+ else
61
+ template.first_render.split('/').last || template.first_render
62
+ end
63
+ end
64
+ end
65
+
66
+ # was this template rendered by a file?
67
+ def rendered_with_file?
68
+ !rendered_file.nil?
69
+ end
70
+
71
+ # a shortcut to the flash (or an empty hash if no flash.. hey! that rhymes!)
72
+ def flash
73
+ session['flash'] || {}
74
+ end
75
+
76
+ # do we have a flash?
77
+ def has_flash?
78
+ !session['flash'].empty?
79
+ end
80
+
81
+ # do we have a flash that has contents?
82
+ def has_flash_with_contents?
83
+ !flash.empty?
84
+ end
85
+
86
+ # does the specified flash object exist?
87
+ def has_flash_object?(name=nil)
88
+ !flash[name].nil?
89
+ end
90
+
91
+ # does the specified object exist in the session?
92
+ def has_session_object?(name=nil)
93
+ !session[name].nil?
94
+ end
95
+
96
+ # a shortcut to the template.assigns
97
+ def template_objects
98
+ template.assigns || {}
99
+ end
100
+
101
+ # does the specified template object exist?
102
+ def has_template_object?(name=nil)
103
+ !template_objects[name].nil?
104
+ end
105
+
106
+ # Returns the response cookies, converted to a Hash of (name => CGI::Cookie) pairs
107
+ # Example:
108
+ #
109
+ # assert_equal ['AuthorOfNewPage'], r.cookies['author'].value
110
+ def cookies
111
+ headers['cookie'].inject({}) { |hash, cookie| hash[cookie.name] = cookie; hash }
112
+ end
113
+
114
+ # Returns binary content (downloadable file), converted to a String
115
+ def binary_content
116
+ raise "Response body is not a Proc: #{body.inspect}" unless body.kind_of?(Proc)
117
+ require 'stringio'
118
+
119
+ sio = StringIO.new
120
+
121
+ begin
122
+ $stdout = sio
123
+ body.call
124
+ ensure
125
+ $stdout = STDOUT
126
+ end
127
+
128
+ sio.rewind
129
+ sio.read
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,2 @@
1
+ require "active_command/request"
2
+ require "active_command/response"
@@ -0,0 +1,10 @@
1
+
2
+ == May 20, 2006
3
+
4
+ * Added to_skeleton for writing fieldnames only. [Gunther Schmidl]
5
+ * Added initial tests, thanks to Scott Barron's acts_as_state_machine
6
+
7
+ == Jan 12 2006
8
+
9
+ * Added code to handle single table inheritance. May need to be modified for non-standard use of STI.
10
+
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2005 Geoffrey Grosenbach
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ = ar_fixtures
2
+
3
+ This library makes it easy to save ActiveRecord objects to reloadable files or fixtures. ActiveRecord is required.
4
+
5
+ See tasks/ar_fixtures.rake for what can be done from the command-line, or use "rake -T" and look for items in the "db" namespace.
6
+
7
+ == Resources
8
+
9
+ Subversion
10
+
11
+ * http://topfunky.net/svn/plugins/ar_fixtures
12
+
13
+ Blog
14
+
15
+ * http://nubyonrails.com
16
+
17
+ Author
18
+
19
+ * Geoffrey Grosenbach boss [at] topfunky [dot] com
@@ -0,0 +1,54 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => [:clean, :test]
7
+
8
+ desc "Delete test-generated files"
9
+ task :clean do
10
+ %w(sqlite sqlite3).each do |db_name|
11
+ rm_f File.join(File.dirname(__FILE__), 'test', "plugin.#{db_name}.db")
12
+ end
13
+ rm_f File.join(File.dirname(__FILE__), 'test', 'debug.log')
14
+ end
15
+
16
+ desc 'Test the plugin.'
17
+ Rake::TestTask.new(:test) do |t|
18
+ t.libs << 'lib'
19
+ t.pattern = 'test/**/*_test.rb'
20
+ t.verbose = true
21
+ end
22
+
23
+ desc 'Generate documentation for the plugin.'
24
+ Rake::RDocTask.new(:rdoc) do |rdoc|
25
+ rdoc.rdoc_dir = 'rdoc'
26
+ rdoc.title = 'ActiveRecord Fixtures'
27
+ rdoc.options << '--line-numbers' << '--inline-source'
28
+ rdoc.rdoc_files.include('README')
29
+ rdoc.rdoc_files.include('lib/**/*.rb')
30
+ end
31
+
32
+ #
33
+ # def sort_files(glob, pattern)
34
+ # %(for f in #{glob}; do grep "#{pattern}" $f > x; sort x > y; if ! diff x y > z ; then echo $f; echo; cat z; fi; done; rm -f x y z)
35
+ # end
36
+ #
37
+ # namespace :zentest do
38
+ #
39
+ # desc "Generates test stub code for libraries"
40
+ # task :lib do
41
+ # tests = Dir["test/*_test.rb"]
42
+ # libs = Dir["lib/*.rb"]
43
+ # ruby "-S -I. ZenTest -r #{tests.join ' '} #{libs.join ' '}"
44
+ # end
45
+ #
46
+ # task :sort do
47
+ # sh sort_files('lib/*.rb', 'def ')
48
+ # sh sort_files('test/*_test.rb', 'def.test_')
49
+ # end
50
+ #
51
+ # task :audit_libs => [ :lib, :sort ]
52
+ #
53
+ # end
54
+ #
@@ -0,0 +1,7 @@
1
+ author: topfunky
2
+ summary: Use the existing data in your database to generate fixtures, fixture skeletons, and reference YAML files.
3
+ homepage: http://nubyonrails.com
4
+ plugin: http://topfunky.net/svn/plugins/ar_fixtures
5
+ license: MIT
6
+ version: 0.2
7
+ rails_version: 1.0+
@@ -0,0 +1 @@
1
+ require 'ar_fixtures'
@@ -0,0 +1,102 @@
1
+ # Extension to make it easy to read and write data to a file.
2
+ class ActiveRecord::Base
3
+
4
+ class << self
5
+
6
+ # Writes content of this table to db/table_name.yml, or the specified file.
7
+ #
8
+ # Writes all content by default, but can be limited.
9
+ def dump_to_file(path=nil, limit=nil)
10
+ opts = {}
11
+ opts[:limit] = limit if limit
12
+ path ||= "db/#{table_name}.yml"
13
+ write_file(File.expand_path(path, RAILS_ROOT), self.find(:all, opts).to_yaml)
14
+ end
15
+
16
+ # Delete existing data in database and load fresh from file in db/table_name.yml
17
+ def load_from_file(path=nil)
18
+ path ||= "db/#{table_name}.yml"
19
+
20
+ self.destroy_all
21
+
22
+ if connection.respond_to?(:reset_pk_sequence!)
23
+ connection.reset_pk_sequence!(table_name)
24
+ end
25
+
26
+ records = YAML::load( File.open( File.expand_path(path, RAILS_ROOT) ) )
27
+ records.each do |record|
28
+ record_copy = self.new(record.attributes)
29
+ record_copy.id = record.id
30
+
31
+ # For Single Table Inheritance
32
+ klass_col = record.class.inheritance_column.to_sym
33
+ if record[klass_col]
34
+ record_copy.type = record[klass_col]
35
+ end
36
+
37
+ record_copy.save
38
+ end
39
+
40
+ if connection.respond_to?(:reset_pk_sequence!)
41
+ connection.reset_pk_sequence!(table_name)
42
+ end
43
+ end
44
+
45
+ # Write a file that can be loaded with +fixture :some_table+ in tests.
46
+ # Uses existing data in the database.
47
+ #
48
+ # Will be written to +test/fixtures/table_name.yml+. Can be restricted to some number of rows.
49
+ def to_fixture(limit=nil)
50
+ opts = {}
51
+ opts[:limit] = limit if limit
52
+
53
+ write_file(File.expand_path("test/fixtures/#{table_name}.yml", RAILS_ROOT),
54
+ self.find(:all, opts).inject({}) { |hsh, record|
55
+ hsh.merge("#{table_name.singularize}_#{record.id}" => record.attributes)
56
+ }.to_yaml)
57
+ habtm_to_fixture
58
+ end
59
+
60
+ # Write the habtm association table
61
+ def habtm_to_fixture
62
+ joins = self.reflect_on_all_associations.select { |j|
63
+ j.macro == :has_and_belongs_to_many
64
+ }
65
+ joins.each do |join|
66
+ hsh = {}
67
+ connection.select_all("SELECT * FROM #{join.options[:join_table]}").each_with_index { |record, i|
68
+ hsh["join_#{i}"] = record
69
+ }
70
+ write_file(File.expand_path("test/fixtures/#{join.options[:join_table]}.yml", RAILS_ROOT), hsh.to_yaml)
71
+ end
72
+ end
73
+
74
+ # Generates a basic fixture file in test/fixtures that lists the table's field names.
75
+ #
76
+ # You can use it as a starting point for your own fixtures.
77
+ #
78
+ # record_1:
79
+ # name:
80
+ # rating:
81
+ # record_2:
82
+ # name:
83
+ # rating:
84
+ #
85
+ def to_skeleton
86
+ record = {
87
+ "record_1" => self.new.attributes,
88
+ "record_2" => self.new.attributes
89
+ }
90
+ write_file(File.expand_path("test/fixtures/#{table_name}.yml", RAILS_ROOT),
91
+ record.to_yaml)
92
+ end
93
+
94
+ def write_file(path, content) # :nodoc:
95
+ f = File.new(path, "w+")
96
+ f.puts content
97
+ f.close
98
+ end
99
+
100
+ end
101
+
102
+ end
@@ -0,0 +1,39 @@
1
+
2
+ def env_or_raise(var_name, human_name)
3
+ if ENV[var_name].blank?
4
+ raise "No #{var_name} value given. Set #{var_name}=#{human_name}"
5
+ else
6
+ return ENV[var_name]
7
+ end
8
+ end
9
+
10
+ def model_or_raise
11
+ return env_or_raise('MODEL', 'ModelName')
12
+ end
13
+
14
+ def limit_or_nil_string
15
+ ENV['LIMIT'].blank? ? 'nil' : ENV['LIMIT']
16
+ end
17
+
18
+ namespace :db do
19
+ namespace :fixtures do
20
+ desc "Dump data to fixture files. Use MODEL=ModelName and LIMIT (optional)"
21
+ task :dump => :environment do
22
+ eval "#{model_or_raise}.to_fixture(#{limit_or_nil_string})"
23
+ end
24
+ end
25
+
26
+
27
+ namespace :data do
28
+ desc "Dump current data to YAML. Use MODEL=ModelName and LIMIT (optional)"
29
+ task :dump => :environment do
30
+ eval "#{model_or_raise}.dump_to_file(nil, #{limit_or_nil_string})"
31
+ puts "#{model_or_raise} has been dumped to the db folder."
32
+ end
33
+
34
+ desc "Load data from YAML dumped by the ar_fixtures plugin. Use MODEL=ModelName"
35
+ task :load => :environment do
36
+ eval "#{model_or_raise}.load_from_file"
37
+ end
38
+ end
39
+ end