Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Rely on ActiveModel for translation and error messages.

  • Loading branch information...
commit c37949dd8a85c04ee978124dc7886e934a61eb28 1 parent 72beecb
José Valim authored December 27, 2009
7  lib/mail_form.rb
... ...
@@ -1,6 +1,6 @@
  1
+require 'active_model'
1 2
 require 'mail_form/base'
2 3
 require 'mail_form/dsl'
3  
-require 'mail_form/errors'
4 4
 require 'mail_form/notifier'
5 5
 
6 6
 class MailForm
@@ -25,8 +25,9 @@ class MailForm
25 25
 
26 26
   headers({})
27 27
   sender {|c| c.email }
28  
-  subject{|c| c.class.human_name }
  28
+  subject{|c| c.class.model_name.human }
29 29
   template 'default'
30 30
 end
31 31
 
32  
-MailForm::Notifier.template_root = File.join(File.dirname(__FILE__), '..', 'views')
  32
+I18n.load_path.unshift File.expand_path('mail_form/locales/en.yml', File.dirname(__FILE__))
  33
+MailForm::Notifier.template_root = File.expand_path('../views', File.dirname(__FILE__))
30  lib/mail_form/base.rb
... ...
@@ -1,4 +1,9 @@
1 1
 class MailForm
  2
+  extend ActiveModel::Naming
  3
+  extend ActiveModel::Translation
  4
+  include ActiveModel::Validations
  5
+  include ActiveModel::Conversion
  6
+
2 7
   attr_accessor :request
3 8
 
4 9
   # Initialize assigning the parameters given as hash (just as in ActiveRecord).
@@ -93,34 +98,19 @@ def deliver(run_validations=true)
93 98
   end
94 99
   alias :save :deliver
95 100
 
96  
-  # Add a human attribute name interface on top of I18n. If email is received as
97  
-  # attribute, it will look for a translated name on:
98  
-  #
99  
-  #   mail_form:
100  
-  #     attributes:
101  
-  #       email: E-mail
102  
-  #
103  
-  def self.human_attribute_name(attribute, options={})
104  
-    I18n.translate("attributes.#{attribute}", options.merge(:default => attribute.to_s.humanize, :scope => [:mail_form]))
  101
+  def self.i18n_scope
  102
+    :mail_form
105 103
   end
106 104
 
107  
-  # Add a human name interface on top of I18n. If you have a model named
108  
-  # MailForm, it will search for the localized name on:
109  
-  #
110  
-  #   mail_form:
111  
-  #     models:
112  
-  #       contact_form: Contact form
113  
-  #
114  
-  def self.human_name(options={})
115  
-    underscored = self.name.demodulize.underscore
116  
-    I18n.translate("models.#{underscored}", options.merge(:default => underscored.humanize, :scope => [:mail_form]))
  105
+  def self.lookup_ancestors
  106
+    super - [MailForm]
117 107
   end
118 108
 
119 109
   # Return the errors in this form. The object returned as the same API as the
120 110
   # ActiveRecord one.
121 111
   #
122 112
   def errors
123  
-    @errors ||= MailForm::Errors.new(self)
  113
+    @errors ||= ActiveModel::Errors.new(self)
124 114
   end
125 115
 
126 116
 end
59  lib/mail_form/errors.rb
... ...
@@ -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
36  test/base_test.rb
@@ -37,8 +37,9 @@ def test_is_not_valid_when_validatable_attributes_are_blank
37 37
     assert !form.valid?
38 38
     assert form.invalid?
39 39
 
40  
-    assert_equal(2, form.errors.count)
41  
-    assert_equal({:email=>:blank, :name=>:blank}, form.errors)
  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 @@ def test_is_not_valid_when_validatable_regexp_does_not_match
47 48
     assert form.invalid?
48 49
 
49 50
     assert_equal(1, form.errors.count)
50  
-    assert_equal({:email=>:invalid}, form.errors)
  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 @@ def test_deliver_is_true_when_is_not_spam_and_valid
86 87
   end
87 88
 
88 89
   def test_human_name_returns_a_humanized_name
89  
-    assert_equal 'Contact form', ContactForm.human_name
  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.human_name
  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 @@ def test_human_attribute_name_returns_a_humanized_attribute
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')
  109
+    form.valid?
  110
+    assert_equal ["can't be blank"], form.errors[:name]
  111
+    assert_equal ["is invalid"],     form.errors[:email]
  112
+    assert_equal [],                 form.errors[:message]
  113
+  end
  114
+
  115
+  def test_activemodel_errors_lookups_model_keys
  116
+    I18n.backend.store_translations(:en, :mail_form => { :errors => { :models => { :contact_form =>
  117
+      { :attributes => { :email => { :invalid => 'fill in the email' },
  118
+                         :name => { :blank => 'fill in the name' } }
  119
+      }
  120
+    }}})
  121
+
  122
+    form = ContactForm.new(:email => 'not_valid')
  123
+    form.valid?
  124
+
  125
+    assert_equal ["fill in the name"],  form.errors[:name]
  126
+    assert_equal ["fill in the email"], form.errors[:email]
  127
+    assert_equal [],                    form.errors[:message]
  128
+  end
  129
+
106 130
   def teardown
107 131
     I18n.reload!
108 132
   end
85  test/errors_test.rb
... ...
@@ -1,85 +0,0 @@
1  
-require File.dirname(__FILE__) + '/test_helper'
2  
-
3  
-class MailFormErrorsTest < 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, :mail_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, :mail_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_array_like_option_acts_as_an_alias_for_on
47  
-    form = ContactForm.new(:email => 'not_valid')
48  
-    form.valid?
49  
-    assert_equal "can't be blank",       form.errors[:name]
50  
-    assert_equal form.errors.on(:name),  form.errors[:name]
51  
-    assert_equal "is invalid",           form.errors[:email]
52  
-    assert_equal form.errors.on(:email), form.errors[:email]
53  
-    assert_equal nil,                    form.errors[:message]
54  
-  end
55  
-
56  
-  def test_get_returns_the_real_value_in_the_given_attribute
57  
-    form = ContactForm.new(:email => 'not_valid')
58  
-    form.valid?
59  
-    assert_equal :blank,   form.errors.get(:name)
60  
-    assert_equal :invalid, form.errors.get(:email)
61  
-    assert_equal nil,      form.errors.get(:message)
62  
-  end
63  
-
64  
-  def test_full_messages
65  
-    form = ContactForm.new(:email => 'not_valid')
66  
-    form.valid?
67  
-
68  
-    assert form.errors.full_messages.include?("Name can't be blank")
69  
-    assert form.errors.full_messages.include?("Email is invalid")
70  
-  end
71  
-
72  
-  def test_full_localized_messages
73  
-    I18n.backend.store_translations(:en, :mail_form => { :messages => { :email => 'is not valid', :blank => 'should be filled' }, :attributes => { :email => 'E-mail' } })
74  
-
75  
-    form = ContactForm.new(:email => 'not_valid')
76  
-    form.valid?
77  
-
78  
-    assert form.errors.full_messages.include?("Name should be filled")
79  
-    assert form.errors.full_messages.include?("E-mail is not valid")
80  
-  end
81  
-
82  
-  def teardown
83  
-    I18n.reload!
84  
-  end
85  
-end
2  test/notifier_test.rb
@@ -83,7 +83,7 @@ def test_body_contains_attributes_names
83 83
   end
84 84
 
85 85
   def test_body_contains_localized_attributes_names
86  
-    I18n.backend.store_translations(:en, :mail_form => { :attributes => { :message => 'Sent message' } })
  86
+    I18n.backend.store_translations(:en, :mail_form => { :attributes => { :contact_form => { :message => 'Sent message' } } })
87 87
     @form.deliver
88 88
     assert_match /Sent message:/, ActionMailer::Base.deliveries.first.body
89 89
     assert_no_match /Message:/, ActionMailer::Base.deliveries.first.body

0 notes on commit c37949d

Please sign in to comment.
Something went wrong with that request. Please try again.