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.
- 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
|