sugoi-mail 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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