mail_form 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +105 -51
- data/Rakefile +1 -0
- data/lib/mail_form.rb +48 -32
- data/lib/mail_form/base.rb +6 -124
- data/lib/mail_form/delivery.rb +239 -0
- data/lib/mail_form/shim.rb +50 -0
- data/lib/mail_form/version.rb +1 -1
- data/lib/views/mail_form/contact.erb +38 -0
- data/test/mail_form_test.rb +190 -0
- data/test/{base_test.rb → resource_test.rb} +31 -7
- data/test/test_helper.rb +25 -8
- metadata +7 -9
- data/lib/mail_form/dsl.rb +0 -171
- data/lib/mail_form/errors.rb +0 -59
- data/lib/mail_form/notifier.rb +0 -48
- data/test/errors_test.rb +0 -85
- data/test/notifier_test.rb +0 -183
- data/views/mail_form/notifier/contact.erb +0 -30
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'test_helper'
|
2
2
|
|
3
3
|
class MailFormBaseTest < ActiveSupport::TestCase
|
4
4
|
|
@@ -37,8 +37,9 @@ class MailFormBaseTest < ActiveSupport::TestCase
|
|
37
37
|
assert !form.valid?
|
38
38
|
assert form.invalid?
|
39
39
|
|
40
|
-
assert_equal
|
41
|
-
assert_equal
|
40
|
+
assert_equal 2, form.errors.count
|
41
|
+
assert_equal ["can't be blank"], form.errors[:email]
|
42
|
+
assert_equal ["can't be blank"], form.errors[:name]
|
42
43
|
end
|
43
44
|
|
44
45
|
def test_is_not_valid_when_validatable_regexp_does_not_match
|
@@ -47,7 +48,7 @@ class MailFormBaseTest < ActiveSupport::TestCase
|
|
47
48
|
assert form.invalid?
|
48
49
|
|
49
50
|
assert_equal(1, form.errors.count)
|
50
|
-
assert_equal
|
51
|
+
assert_equal ["is invalid"], form.errors[:email]
|
51
52
|
end
|
52
53
|
|
53
54
|
def test_is_valid_when_validatable_attributes_are_valid
|
@@ -86,12 +87,12 @@ class MailFormBaseTest < ActiveSupport::TestCase
|
|
86
87
|
end
|
87
88
|
|
88
89
|
def test_human_name_returns_a_humanized_name
|
89
|
-
assert_equal 'Contact form', ContactForm.
|
90
|
+
assert_equal 'Contact form', ContactForm.model_name.human
|
90
91
|
end
|
91
92
|
|
92
93
|
def test_human_name_can_be_localized
|
93
94
|
I18n.backend.store_translations(:en, :mail_form => { :models => { :contact_form => 'Formulário de contato' } })
|
94
|
-
assert_equal 'Formulário de contato', ContactForm.
|
95
|
+
assert_equal 'Formulário de contato', ContactForm.model_name.human
|
95
96
|
end
|
96
97
|
|
97
98
|
def test_human_attribute_name_returns_a_humanized_attribute
|
@@ -99,10 +100,33 @@ class MailFormBaseTest < ActiveSupport::TestCase
|
|
99
100
|
end
|
100
101
|
|
101
102
|
def test_human_attribute_name_can_be_localized
|
102
|
-
I18n.backend.store_translations(:en, :mail_form => { :attributes => { :message => 'Mensagem' } })
|
103
|
+
I18n.backend.store_translations(:en, :mail_form => { :attributes => { :contact_form => { :message => 'Mensagem' } } })
|
103
104
|
assert_equal 'Mensagem', ContactForm.human_attribute_name(:message)
|
104
105
|
end
|
105
106
|
|
107
|
+
def test_activemodel_linked_errors
|
108
|
+
form = ContactForm.new(:email => 'not_valid', :category => "invalid")
|
109
|
+
form.valid?
|
110
|
+
assert_equal ["can't be blank"], form.errors[:name]
|
111
|
+
assert_equal ["is invalid"], form.errors[:email]
|
112
|
+
assert_equal ["is not included in the list"], form.errors[:category]
|
113
|
+
assert_equal [], form.errors[:message]
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_activemodel_errors_lookups_model_keys
|
117
|
+
I18n.backend.store_translations(:en, :mail_form => { :errors => { :models => { :contact_form =>
|
118
|
+
{ :attributes => { :email => { :invalid => 'fill in the email' },
|
119
|
+
:name => { :blank => 'fill in the name' } }
|
120
|
+
}
|
121
|
+
}}})
|
122
|
+
|
123
|
+
form = ContactForm.new(:email => 'not_valid')
|
124
|
+
form.valid?
|
125
|
+
|
126
|
+
assert_equal ["fill in the name"], form.errors[:name]
|
127
|
+
assert_equal ["fill in the email"], form.errors[:email]
|
128
|
+
end
|
129
|
+
|
106
130
|
def teardown
|
107
131
|
I18n.reload!
|
108
132
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,25 +1,38 @@
|
|
1
|
-
require 'test/unit'
|
2
1
|
require 'rubygems'
|
3
2
|
|
3
|
+
begin
|
4
|
+
require 'test/unit'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
4
8
|
RAILS_ENV = ENV["RAILS_ENV"] = "test"
|
5
9
|
|
6
10
|
require 'active_support'
|
7
11
|
require 'active_support/test_case'
|
8
|
-
require '
|
12
|
+
require 'action_controller'
|
9
13
|
require 'action_controller/test_case'
|
14
|
+
require 'action_mailer'
|
10
15
|
|
11
16
|
ActionMailer::Base.delivery_method = :test
|
12
17
|
|
13
|
-
|
14
|
-
require
|
18
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
19
|
+
require 'mail_form'
|
15
20
|
|
16
|
-
class ContactForm < MailForm
|
21
|
+
class ContactForm < MailForm::Base
|
17
22
|
recipients 'my.email@my.domain.com'
|
18
23
|
|
19
24
|
attribute :name, :validate => true
|
20
25
|
attribute :email, :validate => /[^@]+@[^\.]+\.[\w\.\-]+/
|
26
|
+
attribute :category, :validate => ["Interface bug", "General"], :allow_blank => true
|
21
27
|
attribute :nickname, :captcha => true
|
22
|
-
|
28
|
+
|
29
|
+
attributes :created_at, :message, :validate => :callback
|
30
|
+
|
31
|
+
before_create :set_created_at
|
32
|
+
|
33
|
+
def set_created_at
|
34
|
+
created_at = Date.today
|
35
|
+
end
|
23
36
|
|
24
37
|
def callback
|
25
38
|
@_callback_run = true
|
@@ -48,7 +61,7 @@ class FileForm < ContactForm
|
|
48
61
|
end
|
49
62
|
end
|
50
63
|
|
51
|
-
class NullRecipient < MailForm
|
64
|
+
class NullRecipient < MailForm::Base
|
52
65
|
sender 'my.email@my.domain.com'
|
53
66
|
end
|
54
67
|
|
@@ -56,8 +69,12 @@ class TemplateForm < ContactForm
|
|
56
69
|
template 'custom_template'
|
57
70
|
end
|
58
71
|
|
72
|
+
class WrongForm < ContactForm
|
73
|
+
template 'does_not_exist'
|
74
|
+
end
|
75
|
+
|
59
76
|
# Needed to correctly test an uploaded file
|
60
|
-
class
|
77
|
+
class Rack::Test::UploadedFile
|
61
78
|
def read
|
62
79
|
@tempfile.read
|
63
80
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mail_form
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Jos\xC3\xA9 Valim"
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date:
|
13
|
+
date: 2010-02-07 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -29,11 +29,10 @@ files:
|
|
29
29
|
- Rakefile
|
30
30
|
- lib/mail_form.rb
|
31
31
|
- lib/mail_form/base.rb
|
32
|
-
- lib/mail_form/
|
33
|
-
- lib/mail_form/
|
34
|
-
- lib/mail_form/notifier.rb
|
32
|
+
- lib/mail_form/delivery.rb
|
33
|
+
- lib/mail_form/shim.rb
|
35
34
|
- lib/mail_form/version.rb
|
36
|
-
- views/mail_form/
|
35
|
+
- lib/views/mail_form/contact.erb
|
37
36
|
has_rdoc: true
|
38
37
|
homepage: http://github.com/plataformatec/mail_form
|
39
38
|
licenses: []
|
@@ -63,7 +62,6 @@ signing_key:
|
|
63
62
|
specification_version: 3
|
64
63
|
summary: Send e-mail straight from forms in Rails with I18n, validations, attachments and request information.
|
65
64
|
test_files:
|
66
|
-
- test/
|
67
|
-
- test/
|
68
|
-
- test/notifier_test.rb
|
65
|
+
- test/mail_form_test.rb
|
66
|
+
- test/resource_test.rb
|
69
67
|
- test/test_helper.rb
|
data/lib/mail_form/dsl.rb
DELETED
@@ -1,171 +0,0 @@
|
|
1
|
-
class MailForm
|
2
|
-
module DSL
|
3
|
-
|
4
|
-
protected
|
5
|
-
|
6
|
-
# Declare your form attributes. All attributes declared here will be appended
|
7
|
-
# to the e-mail, except the ones captcha is true.
|
8
|
-
#
|
9
|
-
# == Options
|
10
|
-
#
|
11
|
-
# * <tt>:validate</tt> - When true, validates the attributes can't be blank.
|
12
|
-
# When a regexp is given, check if the attribute matches is not blank and
|
13
|
-
# then if it matches the regexp.
|
14
|
-
#
|
15
|
-
# Whenever :validate is a symbol, the method given as symbol will be
|
16
|
-
# called. You can then add validations as you do in ActiveRecord (errors.add).
|
17
|
-
#
|
18
|
-
# * <tt>:attachment</tt> - When given, expects a file to be sent and attaches
|
19
|
-
# it to the e-mail. Don't forget to set your form to multitype.
|
20
|
-
#
|
21
|
-
# * <tt>:captcha</tt> - When true, validates the attributes must be blank
|
22
|
-
# This is a simple way to avoid spam
|
23
|
-
#
|
24
|
-
# == Examples
|
25
|
-
#
|
26
|
-
# class ContactForm < MailForm
|
27
|
-
# attributes :name, :validate => true
|
28
|
-
# attributes :email, :validate => /^([^@]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
|
29
|
-
# attributes :message
|
30
|
-
# attributes :type
|
31
|
-
# attributes :screenshot, :attachment => true, :validate => :interface_bug?
|
32
|
-
# attributes :nickname, :captcha => true
|
33
|
-
#
|
34
|
-
# def interface_bug?
|
35
|
-
# if type == 'Interface bug' && screenshot.nil?
|
36
|
-
# self.errors.add(:screenshot, "can't be blank when you are reporting an interface bug")
|
37
|
-
# end
|
38
|
-
# end
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
def attribute(*accessors)
|
42
|
-
options = accessors.extract_options!
|
43
|
-
|
44
|
-
attr_accessor *accessors
|
45
|
-
|
46
|
-
if options[:attachment]
|
47
|
-
write_inheritable_array(:form_attachments, accessors)
|
48
|
-
elsif options[:captcha]
|
49
|
-
write_inheritable_array(:form_captcha, accessors)
|
50
|
-
else
|
51
|
-
write_inheritable_array(:form_attributes, accessors)
|
52
|
-
end
|
53
|
-
|
54
|
-
if options[:validate]
|
55
|
-
validations = {}
|
56
|
-
accessors.each{ |a| validations[a] = options[:validate] }
|
57
|
-
|
58
|
-
write_inheritable_hash(:form_validatable, validations)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
alias :attributes :attribute
|
62
|
-
|
63
|
-
# Declares contact email sender. It can be a string or a proc or a symbol.
|
64
|
-
#
|
65
|
-
# When a symbol is given, it will call a method on the form object with
|
66
|
-
# the same name as the symbol. As a proc, it receives a simple form
|
67
|
-
# instance. By default is the class human name.
|
68
|
-
#
|
69
|
-
# == Examples
|
70
|
-
#
|
71
|
-
# class ContactForm < MailForm
|
72
|
-
# subject "My Contact Form"
|
73
|
-
# end
|
74
|
-
#
|
75
|
-
def subject(duck=nil, &block)
|
76
|
-
write_inheritable_attribute(:form_subject, duck || block)
|
77
|
-
end
|
78
|
-
|
79
|
-
# Declares contact email sender. It can be a string or a proc or a symbol.
|
80
|
-
#
|
81
|
-
# When a symbol is given, it will call a method on the form object with
|
82
|
-
# the same name as the symbol. As a proc, it receives a simple form
|
83
|
-
# instance. By default is:
|
84
|
-
#
|
85
|
-
# sender{ |c| c.email }
|
86
|
-
#
|
87
|
-
# This requires that your MailForm object have an email attribute.
|
88
|
-
#
|
89
|
-
# == Examples
|
90
|
-
#
|
91
|
-
# class ContactForm < MailForm
|
92
|
-
# # Change sender to include also the name
|
93
|
-
# sender { |c| %{"#{c.name}" <#{c.email}>} }
|
94
|
-
# end
|
95
|
-
#
|
96
|
-
def sender(duck=nil, &block)
|
97
|
-
write_inheritable_attribute(:form_sender, duck || block)
|
98
|
-
end
|
99
|
-
alias :from :sender
|
100
|
-
|
101
|
-
# Who will receive the e-mail. Can be a string or array or a symbol or a proc.
|
102
|
-
#
|
103
|
-
# When a symbol is given, it will call a method on the form object with
|
104
|
-
# the same name as the symbol. As a proc, it receives a simple form instance.
|
105
|
-
#
|
106
|
-
# Both the proc and the symbol must return a string or an array. By default
|
107
|
-
# is nil.
|
108
|
-
#
|
109
|
-
# == Examples
|
110
|
-
#
|
111
|
-
# class ContactForm < MailForm
|
112
|
-
# recipients [ "first.manager@domain.com", "second.manager@domain.com" ]
|
113
|
-
# end
|
114
|
-
#
|
115
|
-
def recipients(duck=nil, &block)
|
116
|
-
write_inheritable_attribute(:form_recipients, duck || block)
|
117
|
-
end
|
118
|
-
alias :to :recipients
|
119
|
-
|
120
|
-
# Additional headers to your e-mail.
|
121
|
-
#
|
122
|
-
# == Examples
|
123
|
-
#
|
124
|
-
# class ContactForm < MailForm
|
125
|
-
# headers { :content_type => 'text/html' }
|
126
|
-
# end
|
127
|
-
#
|
128
|
-
def headers(hash)
|
129
|
-
write_inheritable_hash(:form_headers, hash)
|
130
|
-
end
|
131
|
-
|
132
|
-
# Customized template for your e-mail, if you don't want to use default
|
133
|
-
# 'contact' template or need more than one contact form with different
|
134
|
-
# template layouts.
|
135
|
-
#
|
136
|
-
# When a symbol is given, it will call a method on the form object with
|
137
|
-
# the same name as the symbol. As a proc, it receives a simple form
|
138
|
-
# instance. Both method and proc must return a string with the template
|
139
|
-
# name. Defaults to 'contact'.
|
140
|
-
#
|
141
|
-
# == Examples
|
142
|
-
#
|
143
|
-
# class ContactForm < MailForm
|
144
|
-
# # look for a template in views/mail_form/notifier/my_template.erb
|
145
|
-
# template 'my_template'
|
146
|
-
# end
|
147
|
-
#
|
148
|
-
def template(new_template)
|
149
|
-
write_inheritable_attribute(:form_template, new_template)
|
150
|
-
end
|
151
|
-
|
152
|
-
# Values from request object to be appended to the contact form.
|
153
|
-
# Whenever used, you have to send the request object when initializing the object:
|
154
|
-
#
|
155
|
-
# @contact_form = ContactForm.new(params[:contact_form], request)
|
156
|
-
#
|
157
|
-
# You can get the values to be appended from the AbstractRequest
|
158
|
-
# documentation (http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html)
|
159
|
-
#
|
160
|
-
# == Examples
|
161
|
-
#
|
162
|
-
# class ContactForm < MailForm
|
163
|
-
# append :remote_ip, :user_agent, :session, :cookies
|
164
|
-
# end
|
165
|
-
#
|
166
|
-
def append(*values)
|
167
|
-
write_inheritable_array(:form_appendable, values)
|
168
|
-
end
|
169
|
-
|
170
|
-
end
|
171
|
-
end
|
data/lib/mail_form/errors.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
# Provides an Errors class similar with ActiveRecord ones.
|
2
|
-
#
|
3
|
-
# class ContactForm < MailForm
|
4
|
-
# attributes :name, :validate => true
|
5
|
-
# attributes :email, :validate => /^([^@]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
|
6
|
-
# attributes :message
|
7
|
-
# attributes :nickname, :captcha => true
|
8
|
-
# end
|
9
|
-
#
|
10
|
-
# When validating an attribute name as above, it will search for messages in
|
11
|
-
# the following order:
|
12
|
-
#
|
13
|
-
# mail_form.messages.name
|
14
|
-
# mail_form.messages.blank
|
15
|
-
#
|
16
|
-
# When validating email, it will search for:
|
17
|
-
#
|
18
|
-
# mail_form.messages.name
|
19
|
-
# mail_form.messages.invalid
|
20
|
-
#
|
21
|
-
# If the message is not available, it will output: "can't be blank" in the first
|
22
|
-
# case and "is invalid" in the second.
|
23
|
-
#
|
24
|
-
class MailForm
|
25
|
-
class Errors < Hash
|
26
|
-
|
27
|
-
def initialize(base, *args)
|
28
|
-
@base = base
|
29
|
-
super(*args)
|
30
|
-
end
|
31
|
-
|
32
|
-
alias :add :store
|
33
|
-
alias :count :size
|
34
|
-
alias :get :[]
|
35
|
-
|
36
|
-
def on(attribute)
|
37
|
-
attribute = attribute.to_sym
|
38
|
-
return nil unless get(attribute)
|
39
|
-
|
40
|
-
generate_message_for(attribute, get(attribute))
|
41
|
-
end
|
42
|
-
alias :[] :on
|
43
|
-
|
44
|
-
def full_messages
|
45
|
-
map do |attribute, message|
|
46
|
-
next if message.nil?
|
47
|
-
attribute = attribute.to_sym
|
48
|
-
"#{@base.class.human_attribute_name(attribute)} #{generate_message_for(attribute, message)}"
|
49
|
-
end.compact.reverse
|
50
|
-
end
|
51
|
-
|
52
|
-
protected
|
53
|
-
|
54
|
-
def generate_message_for(attribute, message)
|
55
|
-
I18n.t(attribute, :default => [ message, DEFAULT_MESSAGES[message] ], :scope => [:mail_form, :messages])
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
data/lib/mail_form/notifier.rb
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
# This is the class responsable to send the e-mails.
|
2
|
-
#
|
3
|
-
class MailForm
|
4
|
-
class Notifier < ActionMailer::Base
|
5
|
-
|
6
|
-
def contact(form)
|
7
|
-
@from = get_from_class_and_eval(form, :form_sender)
|
8
|
-
@subject = get_from_class_and_eval(form, :form_subject)
|
9
|
-
@recipients = get_from_class_and_eval(form, :form_recipients)
|
10
|
-
@template = get_from_class_and_eval(form, :form_template)
|
11
|
-
|
12
|
-
raise ScriptError, "You forgot to setup #{form.class.name} recipients" if @recipients.blank?
|
13
|
-
raise ScriptError, "You set :append values but forgot to give me the request object" if form.request.nil? && !form.class.form_appendable.blank?
|
14
|
-
|
15
|
-
@body['form'] = form
|
16
|
-
@body['subject'] = @subject
|
17
|
-
|
18
|
-
@sent_on = Time.now.utc
|
19
|
-
@headers = form.class.form_headers
|
20
|
-
@content_type = 'text/html'
|
21
|
-
|
22
|
-
form.class.form_attachments.each do |attribute|
|
23
|
-
value = form.send(attribute)
|
24
|
-
if value.respond_to?(:read)
|
25
|
-
attachment value.content_type.to_s do |att|
|
26
|
-
att.filename = value.original_filename
|
27
|
-
att.body = value.read
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
protected
|
34
|
-
|
35
|
-
def get_from_class_and_eval(form, method)
|
36
|
-
duck = form.class.send(method)
|
37
|
-
|
38
|
-
if duck.is_a?(Proc)
|
39
|
-
duck.call(form)
|
40
|
-
elsif duck.is_a?(Symbol)
|
41
|
-
form.send(duck)
|
42
|
-
else
|
43
|
-
duck
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|