mail_form 1.0.0 → 1.1.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.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
|