josevalim-simple_form 0.1
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/CHANGELOG +3 -0
- data/MIT-LICENSE +20 -0
- data/README +143 -0
- data/Rakefile +19 -0
- data/init.rb +1 -0
- data/lib/simple_form/base.rb +113 -0
- data/lib/simple_form/dsl.rb +105 -0
- data/lib/simple_form/errors.rb +57 -0
- data/lib/simple_form/notifier.rb +24 -0
- data/lib/simple_form.rb +29 -0
- data/test/base_test.rb +103 -0
- data/test/errors_test.rb +65 -0
- data/test/notifier_test.rb +89 -0
- data/test/test_helper.rb +33 -0
- metadata +66 -0
data/CHANGELOG
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 José Valim
|
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.
|
data/README
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
Simple Form
|
2
|
+
License: MIT
|
3
|
+
Version: 0.1
|
4
|
+
|
5
|
+
You can also read this README in pretty html at the GitHub project Wiki page:
|
6
|
+
|
7
|
+
http://wiki.github.com/josevalim/simple_form/
|
8
|
+
|
9
|
+
Description
|
10
|
+
-----------
|
11
|
+
|
12
|
+
Simple Form is a ready to go contact form. Just the following lines are needed
|
13
|
+
to have a contact form (including the e-mail):
|
14
|
+
|
15
|
+
class ContactForm < SimpleForm
|
16
|
+
subject "My Contact Form"
|
17
|
+
recipients "your.email@your.domain.com"
|
18
|
+
sender{|c| %{"#{c.name}" <#{c.email}>} }
|
19
|
+
|
20
|
+
attribute :name, :validate => true
|
21
|
+
attribute :email, :validate => /[^@]+@[^\.]+\.[\w\.\-]+/
|
22
|
+
attribute :company_name
|
23
|
+
attribute :telephone
|
24
|
+
attribute :message, :validate => true
|
25
|
+
attribute :nickname, :captcha => true
|
26
|
+
end
|
27
|
+
|
28
|
+
Then you start a script/console and type:
|
29
|
+
|
30
|
+
c = ContactForm.new(:name => 'José', :email => 'jose@email.com', :message => 'Cool!')
|
31
|
+
c.deliver
|
32
|
+
|
33
|
+
Check your inbox and the e-mail will be there, with the sent fields.
|
34
|
+
|
35
|
+
SimpleForm is tested and compatible with Rails 2.2.x and Rails 2.3.x. It also
|
36
|
+
supports I18n and error messages, just as an ActiveRecord model does.
|
37
|
+
|
38
|
+
Installation
|
39
|
+
------------
|
40
|
+
|
41
|
+
Install Simple Form is very easy. It is stored in GitHub, so just run the following:
|
42
|
+
|
43
|
+
gem sources -a http://gems.github.com
|
44
|
+
sudo gem install josevalim-simple_form
|
45
|
+
|
46
|
+
If you want it as plugin, just do:
|
47
|
+
|
48
|
+
script/plugin install git://github.com/josevalim/simple_form.git
|
49
|
+
|
50
|
+
API Overview
|
51
|
+
------------
|
52
|
+
|
53
|
+
== attributes(*attributes)
|
54
|
+
|
55
|
+
Declare your form attributes. All attributes declared here will be appended
|
56
|
+
to the e-mail, except the ones :captcha is true.
|
57
|
+
|
58
|
+
Options:
|
59
|
+
|
60
|
+
* :validate - When true, validates the attributes can't be blank.
|
61
|
+
When a regexp is given, check if the attribute matches is not blank and
|
62
|
+
then if it matches the regexp.
|
63
|
+
|
64
|
+
* :captcha - When true, validates the attributes must be blank.
|
65
|
+
This is a simple way to avoid spam and the input should be hidden with CSS.
|
66
|
+
|
67
|
+
Examples:
|
68
|
+
|
69
|
+
class ContactForm < SimpleForm
|
70
|
+
attributes :name, :validate => true
|
71
|
+
attributes :email, :validate => /[^@]+@[^\.]+\.[\w\.\-]+/
|
72
|
+
attributes :message
|
73
|
+
attributes :nickname, :captcha => true
|
74
|
+
end
|
75
|
+
|
76
|
+
c = ContactForm.new(:nickname => 'not_blank', :email => 'your@email.com', :name => 'José')
|
77
|
+
c.valid? #=> true
|
78
|
+
c.spam? #=> true (raises an error in development, to remember you to hide it)
|
79
|
+
c.deliver #=> false (just delivers if is not a spam and is valid)
|
80
|
+
|
81
|
+
c = ContactForm.new(:email => 'invalid')
|
82
|
+
c.valid? #=> false
|
83
|
+
c.errors.inspect #=> { :name => :blank, :email => :invalid }
|
84
|
+
c.errors.full_messages #=> [ "Name can't be blank", "Email is invalid" ]
|
85
|
+
|
86
|
+
c = ContactForm.new(:name => 'José', :email => 'your@email.com')
|
87
|
+
# save is an alias to deliver to allow it to work with InheritedResources
|
88
|
+
c.save #=> true
|
89
|
+
|
90
|
+
== subject(string=nil, &block)
|
91
|
+
|
92
|
+
Declares the subject of the contact email. It can be a string or a proc.
|
93
|
+
As a proc, it receives a simple form instance. When not specified, it defaults
|
94
|
+
to the class human name.
|
95
|
+
|
96
|
+
subject "My Contact Form"
|
97
|
+
subject {|c| "Contacted by #{c.name}"}
|
98
|
+
|
99
|
+
== sender(&block)
|
100
|
+
|
101
|
+
Declares contact email sender. It can be a string or a proc.
|
102
|
+
As a proc, it receives a simple form instance. By default is:
|
103
|
+
|
104
|
+
sender{ |c| c.email }
|
105
|
+
|
106
|
+
This requires that your SimpleForm object have at least an email attribute.
|
107
|
+
|
108
|
+
== headers(hash)
|
109
|
+
|
110
|
+
Additional headers to your e-mail.
|
111
|
+
|
112
|
+
== recipients(string_or_array)
|
113
|
+
|
114
|
+
Who will receive the e-mail. Can be a string or array.
|
115
|
+
|
116
|
+
I18n
|
117
|
+
----
|
118
|
+
|
119
|
+
All models, attributes and messages in SimpleForm can be used with localized.
|
120
|
+
Below is an I18n example file:
|
121
|
+
|
122
|
+
simple_form:
|
123
|
+
models:
|
124
|
+
contact_form: Formulário de contato
|
125
|
+
attributes:
|
126
|
+
name: Nome
|
127
|
+
email: E-mail
|
128
|
+
company_name: Empresa
|
129
|
+
telephone: Telefone
|
130
|
+
message: Mensagem
|
131
|
+
messages:
|
132
|
+
blank: "não pode ficar em branco"
|
133
|
+
invalid: "não é válido"
|
134
|
+
telephone: "deve haver oito dígitos"
|
135
|
+
|
136
|
+
Bugs and Feedback
|
137
|
+
-----------------
|
138
|
+
|
139
|
+
If you discover any bugs, please send an e-mail to jose.valim@gmail.com
|
140
|
+
If you just want to give some positive feedback or drop a line, that's fine too!
|
141
|
+
|
142
|
+
Copyright (c) 2009 José Valim
|
143
|
+
http://josevalim.blogspot.com/
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Run tests for InheritedResources.'
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.pattern = 'test/**/*_test.rb'
|
8
|
+
t.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'Generate documentation for InheritedResources.'
|
12
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
13
|
+
rdoc.rdoc_dir = 'rdoc'
|
14
|
+
rdoc.title = 'SimpleForm'
|
15
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
16
|
+
rdoc.rdoc_files.include('README')
|
17
|
+
rdoc.rdoc_files.include('MIT-LICENSE')
|
18
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
19
|
+
end
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
File.join(File.dirname(__FILE__), 'lib', 'simple_form')
|
@@ -0,0 +1,113 @@
|
|
1
|
+
class SimpleForm
|
2
|
+
|
3
|
+
# Initialize assigning the parameters given as hash (just as in ActiveRecord).
|
4
|
+
#
|
5
|
+
def initialize(params={})
|
6
|
+
params.each_pair do |attr, value|
|
7
|
+
self.send(:"#{attr}=", value)
|
8
|
+
end unless params.blank?
|
9
|
+
end
|
10
|
+
|
11
|
+
# In development, raises an error if the captcha field is not blank. This is
|
12
|
+
# is good to remember that the field should be hidden with CSS and shown only
|
13
|
+
# to robots.
|
14
|
+
#
|
15
|
+
# In test and in production, it returns true if aall captcha field are blank,
|
16
|
+
# returns false otherwise.
|
17
|
+
#
|
18
|
+
def spam?
|
19
|
+
form_captcha.each do |field|
|
20
|
+
next if send(field).blank?
|
21
|
+
|
22
|
+
if RAILS_ENV == 'development'
|
23
|
+
raise ScriptError, "The captcha field #{field} was supposed to be blank"
|
24
|
+
else
|
25
|
+
return true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
|
32
|
+
def not_spam?
|
33
|
+
!spam?
|
34
|
+
end
|
35
|
+
|
36
|
+
# The form is valid if all elements marked to be validated are not blank
|
37
|
+
# and elements given with a regexp match the regexp.
|
38
|
+
#
|
39
|
+
def valid?
|
40
|
+
return false unless errors.empty?
|
41
|
+
|
42
|
+
form_validatable.each_pair do |field, validation|
|
43
|
+
if send(field).blank?
|
44
|
+
errors.add(field, :blank)
|
45
|
+
next
|
46
|
+
end
|
47
|
+
|
48
|
+
errors.add(field, :invalid) if validation.is_a?(Regexp) && send(field) !~ validation
|
49
|
+
end
|
50
|
+
|
51
|
+
errors.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
def invalid?
|
55
|
+
!valid?
|
56
|
+
end
|
57
|
+
|
58
|
+
# Always return true so when using form_for, the default method will be post.
|
59
|
+
#
|
60
|
+
def new_record?
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
# Always return nil so when using form_for, the default method will be post.
|
65
|
+
#
|
66
|
+
def id
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
# If is not spam and the form is valid, we send the e-mail and returns true.
|
71
|
+
# Otherwise returns false.
|
72
|
+
#
|
73
|
+
def deliver
|
74
|
+
if self.not_spam? && self.valid?
|
75
|
+
SimpleForm::Notifier.deliver_contact(self)
|
76
|
+
return true
|
77
|
+
else
|
78
|
+
return false
|
79
|
+
end
|
80
|
+
end
|
81
|
+
alias :save :deliver
|
82
|
+
|
83
|
+
# Add a human attribute name interface on top of I18n. If email is received as
|
84
|
+
# attribute, it will look for a translated name on:
|
85
|
+
#
|
86
|
+
# simple_form:
|
87
|
+
# attributes:
|
88
|
+
# email: E-mail
|
89
|
+
#
|
90
|
+
def self.human_attribute_name(attribute, options={})
|
91
|
+
I18n.translate("attributes.#{attribute}", options.merge(:default => attribute.to_s.humanize, :scope => [:simple_form]))
|
92
|
+
end
|
93
|
+
|
94
|
+
# Add a human name interface on top of I18n. If you have a model named
|
95
|
+
# SimpleForm, it will search for the localized name on:
|
96
|
+
#
|
97
|
+
# simple_form:
|
98
|
+
# models:
|
99
|
+
# contact_form: Contact form
|
100
|
+
#
|
101
|
+
def self.human_name(options={})
|
102
|
+
underscored = self.name.demodulize.underscore
|
103
|
+
I18n.translate("models.#{underscored}", options.merge(:default => underscored.humanize, :scope => [:simple_form]))
|
104
|
+
end
|
105
|
+
|
106
|
+
# Return the errors in this form. The object returned as the same API as the
|
107
|
+
# ActiveRecord one.
|
108
|
+
#
|
109
|
+
def errors
|
110
|
+
@errors ||= SimpleForm::Errors.new(self)
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
class SimpleForm
|
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
|
+
# * <tt>:captcha</tt> - When true, validates the attributes must be blank
|
15
|
+
# This is a simple way to avoid spam
|
16
|
+
#
|
17
|
+
# == Examples
|
18
|
+
#
|
19
|
+
# class ContactForm < SimpleForm
|
20
|
+
# attributes :name, :validate => true
|
21
|
+
# attributes :email, :validate => /^([^@]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
|
22
|
+
# attributes :message
|
23
|
+
# attributes :nickname, :captcha => true
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
def attribute(*accessors)
|
27
|
+
options = accessors.extract_options!
|
28
|
+
|
29
|
+
attr_accessor *accessors
|
30
|
+
|
31
|
+
if options[:captcha]
|
32
|
+
write_inheritable_array(:form_captcha, accessors)
|
33
|
+
else
|
34
|
+
write_inheritable_array(:form_attributes, accessors)
|
35
|
+
end
|
36
|
+
|
37
|
+
if options[:validate]
|
38
|
+
validations = {}
|
39
|
+
accessors.each{ |a| validations[a] = options[:validate] }
|
40
|
+
|
41
|
+
write_inheritable_hash(:form_validatable, validations)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
alias :attributes :attribute
|
45
|
+
|
46
|
+
# Declares the subject of the contact email. It can be a string or a proc.
|
47
|
+
# As a proc, it receives a simple form instance. When not specified, it
|
48
|
+
# defaults to the class human name.
|
49
|
+
#
|
50
|
+
# == Examples
|
51
|
+
#
|
52
|
+
# class ContactForm < SimpleForm
|
53
|
+
# subject "My Contact Form"
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
def subject(string=nil, &block)
|
57
|
+
write_inheritable_attribute(:form_subject, string || block)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Declares contact email sender. It can be a string or a proc.
|
61
|
+
# As a proc, it receives a simple form instance. By default is:
|
62
|
+
#
|
63
|
+
# sender{ |c| c.email }
|
64
|
+
#
|
65
|
+
# This requires that your SimpleForm object have at least an email attribute.
|
66
|
+
#
|
67
|
+
# == Examples
|
68
|
+
#
|
69
|
+
# class ContactForm < SimpleForm
|
70
|
+
# # Change sender to include also the name
|
71
|
+
# sender{|c| %{"#{c.name}" <#{c.email}>} }
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
def sender(string=nil, &block)
|
75
|
+
write_inheritable_attribute(:form_sender, string || block)
|
76
|
+
end
|
77
|
+
alias :from :sender
|
78
|
+
|
79
|
+
# Additional headers to your e-mail.
|
80
|
+
#
|
81
|
+
# == Examples
|
82
|
+
#
|
83
|
+
# class ContactForm < SimpleForm
|
84
|
+
# headers { :content_type => 'text/html' }
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
def headers(hash)
|
88
|
+
write_inheritable_hash(:form_headers, hash)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Who will receive the e-mail. Can be a string or array.
|
92
|
+
#
|
93
|
+
# == Examples
|
94
|
+
#
|
95
|
+
# class ContactForm < SimpleForm
|
96
|
+
# recipients "jose.valim@gmail.com"
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
def recipients(string_or_array)
|
100
|
+
write_inheritable_array(:form_recipients, [*string_or_array])
|
101
|
+
end
|
102
|
+
alias :to :recipients
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Provides an Errors class similar with ActiveRecord ones.
|
2
|
+
#
|
3
|
+
# class ContactForm < SimpleForm
|
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
|
+
# simple_form.messages.name
|
14
|
+
# simple_form.messages.blank
|
15
|
+
#
|
16
|
+
# When validating email, it will search for:
|
17
|
+
#
|
18
|
+
# simple_form.messages.name
|
19
|
+
# simple_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 SimpleForm
|
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
|
+
|
35
|
+
def on(attribute)
|
36
|
+
attribute = attribute.to_sym
|
37
|
+
return nil unless self[attribute]
|
38
|
+
|
39
|
+
generate_message_for(attribute, self[attribute])
|
40
|
+
end
|
41
|
+
|
42
|
+
def full_messages
|
43
|
+
map do |attribute, message|
|
44
|
+
next if message.nil?
|
45
|
+
attribute = attribute.to_sym
|
46
|
+
"#{@base.class.human_attribute_name(attribute)} #{generate_message_for(attribute, message)}"
|
47
|
+
end.compact.reverse
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def generate_message_for(attribute, message)
|
53
|
+
I18n.t(attribute, :default => [ message, DEFAULT_MESSAGES[message] ], :scope => [:simple_form, :messages])
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# This is the class responsable to send the e-mails.
|
2
|
+
#
|
3
|
+
class SimpleForm
|
4
|
+
class Notifier < ActionMailer::Base
|
5
|
+
def contact(form)
|
6
|
+
@subject = form.class.form_subject
|
7
|
+
@subject = @subject.call(form) if @subject.is_a?(Proc)
|
8
|
+
|
9
|
+
@from = form.class.form_sender
|
10
|
+
@from = @from.call(form) if @from.is_a?(Proc)
|
11
|
+
|
12
|
+
@recipients = form.class.form_recipients
|
13
|
+
|
14
|
+
raise ScriptError, "You forgot to setup #{form.class.name} recipients" if @recipients.blank?
|
15
|
+
|
16
|
+
@body['form'] = form
|
17
|
+
@body['subject'] = @subject
|
18
|
+
|
19
|
+
@sent_on = Time.now.utc
|
20
|
+
@headers = form.class.form_headers
|
21
|
+
@content_type = 'text/html'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/simple_form.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
dir = File.dirname(__FILE__)
|
2
|
+
require File.join(dir, 'simple_form', 'base')
|
3
|
+
require File.join(dir, 'simple_form', 'dsl')
|
4
|
+
require File.join(dir, 'simple_form', 'errors')
|
5
|
+
require File.join(dir, 'simple_form', 'notifier')
|
6
|
+
|
7
|
+
class SimpleForm
|
8
|
+
extend SimpleForm::DSL
|
9
|
+
|
10
|
+
ACCESSORS = [ :form_attributes, :form_validatable, :form_subject,
|
11
|
+
:form_recipients, :form_sender, :form_captcha, :form_headers ]
|
12
|
+
|
13
|
+
DEFAULT_MESSAGES = { :blank => "can't be blank", :invalid => "is invalid" }
|
14
|
+
|
15
|
+
class_inheritable_reader *ACCESSORS
|
16
|
+
protected *ACCESSORS
|
17
|
+
|
18
|
+
# Configure default values
|
19
|
+
#
|
20
|
+
attribute :captcha => true
|
21
|
+
attribute :validate => true
|
22
|
+
|
23
|
+
headers({})
|
24
|
+
recipients([])
|
25
|
+
sender{|c| c.email }
|
26
|
+
subject{|c| c.class.human_name }
|
27
|
+
end
|
28
|
+
|
29
|
+
SimpleForm::Notifier.template_root = File.join(dir, '..', 'views')
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class SimpleFormBaseTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
ActionMailer::Base.deliveries = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_id_is_nil
|
10
|
+
assert_equal nil, ContactForm.new.id
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_is_always_a_new_record
|
14
|
+
assert ContactForm.new.new_record?
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_initialize_with_options
|
18
|
+
form = ContactForm.new(:name => 'José', :email => 'jose@my.email.com')
|
19
|
+
assert_equal 'José', form.name
|
20
|
+
assert_equal 'jose@my.email.com', form.email
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_spam_is_true_when_captcha_field_is_set
|
24
|
+
form = ContactForm.new(:nickname => 'not_blank')
|
25
|
+
assert form.spam?
|
26
|
+
assert !form.not_spam?
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_spam_is_false_when_captcha_field_is_not_set
|
30
|
+
form = ContactForm.new
|
31
|
+
assert !form.spam?
|
32
|
+
assert form.not_spam?
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_is_not_valid_when_validatable_attributes_are_blank
|
36
|
+
form = ContactForm.new
|
37
|
+
assert !form.valid?
|
38
|
+
assert form.invalid?
|
39
|
+
|
40
|
+
assert_equal(2, form.errors.count)
|
41
|
+
assert_equal({:email=>:blank, :name=>:blank}, form.errors)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_is_not_valid_when_validatable_regexp_does_not_match
|
45
|
+
form = ContactForm.new(:name => 'Jose', :email => 'not_valid')
|
46
|
+
assert !form.valid?
|
47
|
+
assert form.invalid?
|
48
|
+
|
49
|
+
assert_equal(1, form.errors.count)
|
50
|
+
assert_equal({:email=>:invalid}, form.errors)
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_is_valid_when_validatable_attributes_are_valid
|
54
|
+
form = ContactForm.new(:name => 'Jose', :email => 'is.valid@email.com')
|
55
|
+
assert form.valid?
|
56
|
+
assert !form.invalid?
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_deliver_is_false_when_is_a_spam
|
60
|
+
form = ContactForm.new(:name => 'Jose', :email => 'is.valid@email.com', :nickname => 'not_blank')
|
61
|
+
assert form.valid?
|
62
|
+
assert form.spam?
|
63
|
+
assert !form.deliver
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_deliver_is_false_when_is_invalid
|
67
|
+
form = ContactForm.new(:name => 'Jose', :email => 'is.com')
|
68
|
+
assert form.invalid?
|
69
|
+
assert form.not_spam?
|
70
|
+
assert !form.deliver
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_deliver_is_true_when_is_not_spam_and_valid
|
74
|
+
form = ContactForm.new(:name => 'Jose', :email => 'is.valid@email.com')
|
75
|
+
assert form.valid?
|
76
|
+
assert form.not_spam?
|
77
|
+
assert form.deliver
|
78
|
+
assert_equal 1, ActionMailer::Base.deliveries.size
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_human_name_returns_a_humanized_name
|
82
|
+
assert_equal 'Contact form', ContactForm.human_name
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_human_name_can_be_localized
|
86
|
+
I18n.backend.store_translations(:en, :simple_form => { :models => { :contact_form => 'Formulário de contato' } })
|
87
|
+
assert_equal 'Formulário de contato', ContactForm.human_name
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_human_attribute_name_returns_a_humanized_attribute
|
91
|
+
assert_equal 'Message', ContactForm.human_attribute_name(:message)
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_human_attribute_name_can_be_localized
|
95
|
+
I18n.backend.store_translations(:en, :simple_form => { :attributes => { :message => 'Mensagem' } })
|
96
|
+
assert_equal 'Mensagem', ContactForm.human_attribute_name(:message)
|
97
|
+
end
|
98
|
+
|
99
|
+
def teardown
|
100
|
+
I18n.reload!
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
data/test/errors_test.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class SimpleFormErrorsTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def test_errors_respond_to_some_hash_methods
|
6
|
+
assert ContactForm.new.errors.respond_to?(:each)
|
7
|
+
assert ContactForm.new.errors.respond_to?(:each_pair)
|
8
|
+
assert ContactForm.new.errors.respond_to?(:size)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_count_is_an_alias_to_size
|
12
|
+
errors = ContactForm.new.errors
|
13
|
+
assert_equal errors.size, errors.count
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_on_returns_the_message_in_the_given_attribute
|
17
|
+
form = ContactForm.new(:email => 'not_valid')
|
18
|
+
form.valid?
|
19
|
+
assert_equal "can't be blank", form.errors.on(:name)
|
20
|
+
assert_equal "is invalid", form.errors.on(:email)
|
21
|
+
assert_equal nil, form.errors.on(:message)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_on_returns_a_default_localized_message_in_the_given_attribute
|
25
|
+
I18n.backend.store_translations(:en, :simple_form => { :messages => { :invalid => 'is not valid', :blank => 'should be filled' } })
|
26
|
+
|
27
|
+
form = ContactForm.new(:email => 'not_valid')
|
28
|
+
form.valid?
|
29
|
+
|
30
|
+
assert_equal "should be filled", form.errors.on(:name)
|
31
|
+
assert_equal "is not valid", form.errors.on(:email)
|
32
|
+
assert_equal nil, form.errors.on(:message)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_on_returns_an_attribute_localized_message_in_the_given_attribute
|
36
|
+
I18n.backend.store_translations(:en, :simple_form => { :messages => { :email => 'fill in the email', :name => 'fill in the name' } })
|
37
|
+
|
38
|
+
form = ContactForm.new(:email => 'not_valid')
|
39
|
+
form.valid?
|
40
|
+
|
41
|
+
assert_equal "fill in the name", form.errors.on(:name)
|
42
|
+
assert_equal "fill in the email", form.errors.on(:email)
|
43
|
+
assert_equal nil, form.errors.on(:message)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_full_messages
|
47
|
+
form = ContactForm.new(:email => 'not_valid')
|
48
|
+
form.valid?
|
49
|
+
|
50
|
+
assert_equal ["Name can't be blank", "Email is invalid"], form.errors.full_messages
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_full_localized_messages
|
54
|
+
I18n.backend.store_translations(:en, :simple_form => { :messages => { :email => 'is not valid', :blank => 'should be filled' }, :attributes => { :email => 'E-mail' } })
|
55
|
+
|
56
|
+
form = ContactForm.new(:email => 'not_valid')
|
57
|
+
form.valid?
|
58
|
+
|
59
|
+
assert_equal ["Name should be filled", "E-mail is not valid"], form.errors.full_messages
|
60
|
+
end
|
61
|
+
|
62
|
+
def teardown
|
63
|
+
I18n.reload!
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class SimpleFormNotifierTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@form = ContactForm.new(:name => 'José', :email => 'my.email@my.domain.com', :message => 'Cool')
|
7
|
+
@advanced = AdvancedForm.new(:name => 'José', :email => 'my.email@my.domain.com', :message => "Cool\nno?")
|
8
|
+
ActionMailer::Base.deliveries = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_email_is_sent
|
12
|
+
@form.deliver
|
13
|
+
assert_equal 1, ActionMailer::Base.deliveries.size
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_subject_defaults_to_class_human_name
|
17
|
+
@form.deliver
|
18
|
+
assert_equal 'Contact form', ActionMailer::Base.deliveries.first.subject
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_subject_is_a_string
|
22
|
+
@advanced.deliver
|
23
|
+
assert_equal 'My Advanced Form', ActionMailer::Base.deliveries.first.subject
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_sender_defaults_to_form_email
|
27
|
+
@form.deliver
|
28
|
+
assert_equal ['my.email@my.domain.com'], ActionMailer::Base.deliveries.first.from
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_error_is_raised_when_recipients_is_nil
|
32
|
+
assert_raise ScriptError do
|
33
|
+
NullRecipient.new.deliver
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_recipients_is_a_string
|
38
|
+
@form.deliver
|
39
|
+
assert_equal ['my.email@my.domain.com'], ActionMailer::Base.deliveries.first.to
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_recipients_is_an_array
|
43
|
+
@advanced.deliver
|
44
|
+
assert_equal ['my.email@my.domain.com', 'my.first@email.com', 'my.second@email.com'], ActionMailer::Base.deliveries.first.to
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_headers_is_a_hash
|
48
|
+
@advanced.deliver
|
49
|
+
assert_equal '<mypath>', ActionMailer::Base.deliveries.first.header['return-path'].to_s
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_body_contains_subject
|
53
|
+
@form.deliver
|
54
|
+
assert_match /Contact form/, ActionMailer::Base.deliveries.first.body
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_body_contains_attributes_values
|
58
|
+
@form.deliver
|
59
|
+
assert_match /José/, ActionMailer::Base.deliveries.first.body
|
60
|
+
assert_match /my.email@my.domain.com/, ActionMailer::Base.deliveries.first.body
|
61
|
+
assert_match /Cool/, ActionMailer::Base.deliveries.first.body
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_body_contains_attributes_names
|
65
|
+
@form.deliver
|
66
|
+
assert_match /Name:/, ActionMailer::Base.deliveries.first.body
|
67
|
+
assert_match /Email:/, ActionMailer::Base.deliveries.first.body
|
68
|
+
assert_match /Message:/, ActionMailer::Base.deliveries.first.body
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_body_contains_localized_attributes_names
|
72
|
+
I18n.backend.store_translations(:en, :simple_form => { :attributes => { :email => 'E-mail', :message => 'Sent message' } })
|
73
|
+
@form.deliver
|
74
|
+
assert_match /E\-mail:/, ActionMailer::Base.deliveries.first.body
|
75
|
+
assert_match /Sent message:/, ActionMailer::Base.deliveries.first.body
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_body_simple_format_messages_with_break_line
|
79
|
+
@form.deliver
|
80
|
+
assert_no_match /<p>Cool/, ActionMailer::Base.deliveries.first.body
|
81
|
+
|
82
|
+
@advanced.deliver
|
83
|
+
assert_match /<p>Cool/, ActionMailer::Base.deliveries.last.body
|
84
|
+
end
|
85
|
+
|
86
|
+
def teardown
|
87
|
+
I18n.reload!
|
88
|
+
end
|
89
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
RAILS_ENV = ENV["RAILS_ENV"] = "test"
|
5
|
+
|
6
|
+
require 'active_support'
|
7
|
+
require 'active_support/test_case'
|
8
|
+
require 'action_mailer'
|
9
|
+
|
10
|
+
ActionMailer::Base.delivery_method = :test
|
11
|
+
|
12
|
+
# Load respond_to before defining ApplicationController
|
13
|
+
require File.dirname(__FILE__) + '/../lib/simple_form.rb'
|
14
|
+
|
15
|
+
class ContactForm < SimpleForm
|
16
|
+
recipients 'my.email@my.domain.com'
|
17
|
+
|
18
|
+
attribute :name, :validate => true
|
19
|
+
attribute :email, :validate => /[^@]+@[^\.]+\.[\w\.\-]+/
|
20
|
+
attribute :nickname, :captcha => true
|
21
|
+
attributes :tellphone, :message
|
22
|
+
end
|
23
|
+
|
24
|
+
class AdvancedForm < ContactForm
|
25
|
+
recipients [ 'my.first@email.com', 'my.second@email.com' ]
|
26
|
+
subject 'My Advanced Form'
|
27
|
+
sender{|c| %{"#{c.name}" <#{c.email}>} }
|
28
|
+
headers 'return-path' => 'mypath'
|
29
|
+
end
|
30
|
+
|
31
|
+
class NullRecipient < SimpleForm
|
32
|
+
sender 'my.email@my.domain.com'
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: josevalim-simple_form
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Jos\xC3\xA9 Valim"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-04-03 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Simple easy contact form for Rails.
|
17
|
+
email: jose.valim@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- CHANGELOG
|
26
|
+
- MIT-LICENSE
|
27
|
+
- README
|
28
|
+
- Rakefile
|
29
|
+
- init.rb
|
30
|
+
- lib/simple_form.rb
|
31
|
+
- lib/simple_form/base.rb
|
32
|
+
- lib/simple_form/dsl.rb
|
33
|
+
- lib/simple_form/errors.rb
|
34
|
+
- lib/simple_form/notifier.rb
|
35
|
+
has_rdoc: true
|
36
|
+
homepage: http://github.com/josevalim/simple_form
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --main
|
40
|
+
- README
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: "0"
|
48
|
+
version:
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
requirements: []
|
56
|
+
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 1.2.0
|
59
|
+
signing_key:
|
60
|
+
specification_version: 2
|
61
|
+
summary: Simple easy contact form for Rails.
|
62
|
+
test_files:
|
63
|
+
- test/base_test.rb
|
64
|
+
- test/errors_test.rb
|
65
|
+
- test/notifier_test.rb
|
66
|
+
- test/test_helper.rb
|