views:

65

answers:

3

For my Rails app, we developed an half home-brewed email system. We created a model called Email which then gets added to a queue to be sent (using a web service).

To create templates, we've been just mashing strings together in the model, ie:

Email < ActiveRecord::Base

   def self.stock_message(recipient)
     email = Email.create do |e|
       e.recipient = recipient
       e.message = String.new
       e.message << "first line <br />"
       e.message << "second line <br />"
     end 
   end

end

#to send:
e = Email.stock_message "[email protected]"

This clearly violates MVC and really becomes a problem when I want to format strings using helper methods. How can I properly separate the view code from the model?

+5  A: 

There's a dedicated tutorial on Rails website about that. In short, you can put your email templates under views folder and they will be treated pretty much like traditional html templates for web-browsers.

Also, from my experience, handling of emails is very inconsistent in different versions of Rails, so you may need to fumble around a little.

Nikita Rybak
A: 

Why are you using "an half home-brewed email system", instead of the one provided by Rails?

http://guides.rubyonrails.org/action_mailer_basics.html

David Corbin
+2  A: 

I think you can use render_to_string method, but as it is not availble in model, you need to call it from controller:

# model
Email < ActiveRecord::Base
  def self.stock_message(recipient, message)
    email = Email.create do |e|
      e.recipient = recipient
      e.message = message
    end 
  end
end

# controller
e = Email.stock_message "[email protected]", render_to_string "email/my_email"

If you need to pass some variables to render method, then just add :locals => {:var1 => value, :var2 => value2}.

# view
first line <br />
second line <br />

In this example you should store views for emails in app/views/emails/ directory.

However, as @David said, why not use mailer provided by Rails? It would be better solution.

klew
Any tips for making #render_to_string available in the model? Thanks...really good answer btw.