sugoi-mail 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +35 -0
- data/Rakefile +10 -0
- data/app/apis/mailservice_api.rb +178 -0
- data/app/controllers/.sugoi_admin_controller.rb.swp +0 -0
- data/app/controllers/account_controller.rb +39 -0
- data/app/controllers/address_controller.rb +49 -0
- data/app/controllers/application.rb +4 -0
- data/app/controllers/commandline_controller.rb +15 -0
- data/app/controllers/domain_controller.rb +37 -0
- data/app/controllers/mailinglist_controller.rb +51 -0
- data/app/controllers/mailservice_controller.rb +497 -0
- data/app/controllers/sugoi_admin_controller.rb +93 -0
- data/app/helpers/account_helper.rb +2 -0
- data/app/helpers/address_helper.rb +2 -0
- data/app/helpers/application_helper.rb +3 -0
- data/app/helpers/domain_helper.rb +2 -0
- data/app/helpers/mailservice_helper.rb +2 -0
- data/app/helpers/sugoi_admin_helper.rb +2 -0
- data/app/models/address.rb +110 -0
- data/app/models/admin_message.rb +45 -0
- data/app/models/confirmationcode.rb +59 -0
- data/app/models/domain.rb +76 -0
- data/app/models/mailinglist.rb +336 -0
- data/app/models/mailinglist_class.rb +39 -0
- data/app/models/message.rb +293 -0
- data/app/models/proxy_link.rb +25 -0
- data/app/models/user.rb +150 -0
- data/app/views/account/login.rhtml +22 -0
- data/app/views/account/logout.rhtml +10 -0
- data/app/views/account/signup.rhtml +17 -0
- data/app/views/account/welcome.rhtml +13 -0
- data/app/views/address/_form.rhtml +7 -0
- data/app/views/address/edit.rhtml +10 -0
- data/app/views/address/list.rhtml +27 -0
- data/app/views/address/new.rhtml +8 -0
- data/app/views/address/show.rhtml +8 -0
- data/app/views/domain/login.rhtml +22 -0
- data/app/views/domain/logout.rhtml +10 -0
- data/app/views/domain/signup.rhtml +17 -0
- data/app/views/domain/welcome.rhtml +13 -0
- data/app/views/layouts/address.rhtml +13 -0
- data/app/views/layouts/scaffold.rhtml +13 -0
- data/app/views/mailinglist/_form.rhtml +28 -0
- data/app/views/mailinglist/edit.rhtml +10 -0
- data/app/views/mailinglist/list.rhtml +27 -0
- data/app/views/mailinglist/new.rhtml +8 -0
- data/app/views/mailinglist/show.rhtml +16 -0
- data/app/views/sugoi_admin/create_domain.rhtml +1 -0
- data/app/views/sugoi_admin/list_addresses.rhtml +1 -0
- data/app/views/sugoi_admin/list_domains.rhtml +2 -0
- data/app/views/sugoi_admin/list_mailinglists.rhtml +1 -0
- data/bin/mailc +32 -0
- data/bin/maild +133 -0
- data/bin/sugoi-admin +21 -0
- data/bin/sugoi-mail +20 -0
- data/config/boot.rb +44 -0
- data/config/environment.rb +54 -0
- data/config/environments/bench.rb +21 -0
- data/config/environments/coverage.rb +21 -0
- data/config/environments/development.rb +21 -0
- data/config/environments/production.rb +18 -0
- data/config/environments/test.rb +19 -0
- data/config/lighttpd.conf +46 -0
- data/config/routes.rb +29 -0
- data/db/migrate/001_mailproxy.rb +7 -0
- data/db/migrate/002_create_users.rb +13 -0
- data/db/migrate/003_create_mailinglists.rb +13 -0
- data/db/migrate/004_create_addresses.rb +12 -0
- data/db/migrate/005_create_addresses_mailinglists.rb +13 -0
- data/db/migrate/006_alter_mailinglists.rb +9 -0
- data/db/migrate/007_create_messages.rb +25 -0
- data/db/migrate/008_add_mailinglistid_to_users.rb +14 -0
- data/db/migrate/009_add_domainadmin_to_users.rb +9 -0
- data/db/migrate/010_add_domain_to_users.rb +16 -0
- data/db/migrate/011_add_active_to_addresses.rb +14 -0
- data/db/migrate/012_create_confirmationcodes.rb +14 -0
- data/db/migrate/013_add_description_to_mailinglists.rb +9 -0
- data/db/migrate/014_create_admin_messages.rb +69 -0
- data/db/migrate/015_add_messages_to_mailinglists.rb +26 -0
- data/db/migrate/016_add_mailinglist_admin_to_users.rb +9 -0
- data/db/migrate/017_add_mailinglist_types.rb +94 -0
- data/db/migrate/018_add_bounciness_to_addresses.rb +20 -0
- data/db/migrate/019_add_archived_to_mailinglist_classes.rb +25 -0
- data/db/migrate/020_add_envelope_data_to_messages.rb +11 -0
- data/db/migrate/021_add_addresses_users.rb +14 -0
- data/db/migrate/022_add_virtual_to_users.rb +14 -0
- data/db/migrate/023_drop_openposting_from_mailinglists.rb +9 -0
- data/db/migrate/024_add_proxy_links.rb +21 -0
- data/db/migrate/025_add_proxify_to_mailinglist_classes.rb +25 -0
- data/db/schema.mysql.sql +104 -0
- data/db/schema.postgresql.sql +104 -0
- data/db/schema.rb +85 -0
- data/db/schema.sqlite.sql +104 -0
- data/db/schema.sqlserver.sql +113 -0
- data/db/schema_version +1 -0
- data/doc/README_FOR_APP +179 -0
- data/doc/mailinglist_classes description.txt +28 -0
- data/installer/rails_installer_defaults.yml +5 -0
- data/lib/daemonize.rb +56 -0
- data/lib/domain_system.rb +87 -0
- data/lib/gurgitate-rules.rb +69 -0
- data/lib/limitedfork.rb +66 -0
- data/lib/login_system.rb +87 -0
- data/public/.htaccess +40 -0
- data/public/404.html +8 -0
- data/public/500.html +8 -0
- data/public/dispatch.cgi +10 -0
- data/public/dispatch.fcgi +24 -0
- data/public/dispatch.rb +10 -0
- data/public/favicon.ico +0 -0
- data/public/images/rails.png +0 -0
- data/public/javascripts/application.js +2 -0
- data/public/javascripts/controls.js +815 -0
- data/public/javascripts/dragdrop.js +913 -0
- data/public/javascripts/effects.js +958 -0
- data/public/javascripts/prototype.js +2006 -0
- data/public/robots.txt +1 -0
- data/public/stylesheets/scaffold.css +74 -0
- data/public/stylesheets/trestle.css +74 -0
- data/script/about +3 -0
- data/script/breakpointer +3 -0
- data/script/console +3 -0
- data/script/destroy +3 -0
- data/script/fakedeliver +19 -0
- data/script/generate +3 -0
- data/script/performance/benchmarker +3 -0
- data/script/performance/profiler +3 -0
- data/script/plugin +3 -0
- data/script/process/reaper +3 -0
- data/script/process/spawner +3 -0
- data/script/runner +3 -0
- data/script/server +3 -0
- data/sugoi-mail.gemspec +36 -0
- data/test/fixtures/addresses.yml +70 -0
- data/test/fixtures/addresses_mailinglists.yml +20 -0
- data/test/fixtures/admin_messages.yml +65 -0
- data/test/fixtures/confirmationcodes.yml +13 -0
- data/test/fixtures/domains.yml +9 -0
- data/test/fixtures/mailinglist_classes.yml +45 -0
- data/test/fixtures/mailinglists.yml +80 -0
- data/test/fixtures/messages.yml +154 -0
- data/test/fixtures/proxy_links.yml +5 -0
- data/test/fixtures/users.yml +50 -0
- data/test/functional/domain_controller_test.rb +74 -0
- data/test/functional/mailservice_controller_test.rb +546 -0
- data/test/integration/test_soap.rb +413 -0
- data/test/integration/test_xmlrpc.rb +198 -0
- data/test/mocks/test/net-smtp-stub.rb +24 -0
- data/test/test_helper.rb +28 -0
- data/test/unit/address_test.rb +44 -0
- data/test/unit/admin_message_test.rb +41 -0
- data/test/unit/confirmationcode_test.rb +64 -0
- data/test/unit/domain_test.rb +128 -0
- data/test/unit/mailinglist_class_test.rb +82 -0
- data/test/unit/mailinglist_test.rb +145 -0
- data/test/unit/message_test.rb +151 -0
- data/test/unit/user_test.rb +126 -0
- data/test/units.rb +4 -0
- data/vendor/plugins/active_command/init.rb +1 -0
- data/vendor/plugins/active_command/lib/active_command/request.rb +137 -0
- data/vendor/plugins/active_command/lib/active_command/response.rb +132 -0
- data/vendor/plugins/active_command/lib/active_command.rb +2 -0
- data/vendor/plugins/ar_fixtures/CHANGELOG +10 -0
- data/vendor/plugins/ar_fixtures/MIT-LICENSE +20 -0
- data/vendor/plugins/ar_fixtures/README +19 -0
- data/vendor/plugins/ar_fixtures/Rakefile +54 -0
- data/vendor/plugins/ar_fixtures/about.yml +7 -0
- data/vendor/plugins/ar_fixtures/init.rb +1 -0
- data/vendor/plugins/ar_fixtures/lib/ar_fixtures.rb +102 -0
- data/vendor/plugins/ar_fixtures/tasks/ar_fixtures.rake +39 -0
- data/vendor/plugins/ar_fixtures/test/ar_fixtures_test.rb +53 -0
- data/vendor/plugins/ar_fixtures/test/database.yml +18 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/beer.rb +5 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/beers.yml +9 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/beers_drunkards.yml +8 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/drunkard.rb +6 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/drunkards.yml +8 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/glass.rb +2 -0
- data/vendor/plugins/ar_fixtures/test/fixtures/glasses.yml +9 -0
- data/vendor/plugins/ar_fixtures/test/schema.rb +21 -0
- data/vendor/plugins/ar_fixtures/test/test_helper.rb +37 -0
- 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 @@
|
|
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,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
|