OK, I've googled and found some discussion about this and seen the scolding about breaking the MVC pattern as in "why do you need to do that?", but I *do* have a situation where it makes some sense. Let me describe... I have a new service called redeyestats.com and the major function is to send a daily email with a report (specifically a daily stats listing for sports players that the user is following). This report mirrors a page with the same info on the site. I want to keep things DRY, so it seemed like a good idea to create a Reporter class that would compile each player report for both cases of a) compiling the email and b) the site's page listing. Each player report has links in it to the player's page, their team page, and to a game page for their latest game. So, I do have a need to build links within this reporter object. It's not a model object in the sense of MVC, but it's not a controller or a view and , so, it doesn't resolve the named routes. I'm open to suggestions for another approach that will work for both of my use cases... or for a way to make this work as designed. Does anyone have suggestions on how to make this work? Thx
on 2009-03-04 06:58
on 2009-03-04 16:05
On Tue, 3 Mar 2009 20:56:47 -0800 (PST) lunaclaire <firstname.lastname@example.org> wrote: > I have a new service called redeyestats.com and the major function is > to send a daily email with a report (specifically a daily stats > listing for sports players that the user is following). This report > mirrors a page with the same info on the site. > > I want to keep things DRY, so it seemed like a good idea to create a > Reporter class that would compile each player report for both cases of > a) compiling the email and b) the site's page listing. Each player > report has links in it to the player's page, their team page, and to a > game page for their latest game. This sounds like a pretty straightforward use case for ActionMailer. You can add links to your email via actionmailer templates (via link_to). Then you can use the regular controller/view mechanism for your pages. So in summary 1) Store all of your player data in the model 2) Use an actionmailer template for the email 3) Use normal views for the pages SH -- Starr H. My blog: http://starrhorne.com Check out my Helpdesk RailsKit: http://railskits.com/helpdesk/
on 2009-03-04 19:12
It does seem like it should be straightforward, but there's a bunch of complex logic that I dont want to put directly into views. Initially I had it in a helper, then pulled it into the Reporter object I mentioned, but then I got the problem I mentioned. My latest has the logic in a Module. What I find interesting is that when called from the views (pages), it works fine; but when called from the mailer, I get the following: undefined method `player_url' for ReportHelper:Module Here's some of the code in the module: module ReportHelper include ActionView::Helpers::UrlHelper include ActionController::UrlWriter include ActionView::Helpers::TagHelper def self.html_tracker_report(player, stat, updates, last_update, for_email=false) output =  spacer = " " if for_email line = '<span style="font-weight: bold;">' + link_to(player.name, player_url(player), :style => "color: #666; font-weight:bold; text- decoration: none;") + '</span>' + spacer else line = '<span class="playerName">' + link_to(player.name, player_path(player)) +'</span>' + spacer end end Note the includes and note the logic ("if for_email") that is set up to separately deal with CSS issues in the email. It's slightly different where the email part uses player_url vs player_path, but I've tried both and still see problems in resolving the named route. One more detail that might give a clue: The emails are generated from a rake task (invoked by a cron job) rather than from some use action on the site. I dont think that makes a difference, but, maybe...? My guess is that I haven't included something... or maybe I'm not calling link_to correctly for this case. But, I dont see it so any help is appreciated.
on 2009-03-04 19:44
> One more detail that might give a clue: The emails are generated from > a rake task (invoked by a cron job) rather than from some use action > on the site. I dont think that makes a difference, but, maybe...? Named routes aren't accessible by default in the console, and I imagine they aren't in your rake task, either. Here's instructions on how to include them: http://stuartsierra.com/2008/01/08/testing-named-r... -- Starr H. My blog: http://starrhorne.com Check out my Helpdesk RailsKit: http://railskits.com/helpdesk/
on 2009-03-04 21:37
Thx again, Starr. The thing is, I already have the line: include ActionController::UrlWriter in the module. And get the error. And I don't think I can just put the 'default_url_options' line in there...isn't that an ActionMailer options hash? Or am I missing it completely as to where to put these lines?
on 2009-03-04 22:37
On Mar 4, 2:26 pm, lunaclaire <email@example.com> wrote: > > Or am I missing it completely as to where to put these lines? I'm not clear why you're trying to do this formatting in a helper - isn't this a task better suited for a partial? The typical Rails idiom would be to have methods in the model that return the objects you're interested in (in this case, players and however you're representing updates), while the view code takes care of producing the actual output. Note that the "no logic in views" rule is more like a guideline - not a reason to insist on lobotomized views. If there's logic that solely concerns views (ie show/hide things based on state, user authorization, etc), it belongs in the view. --Matt J.
on 2009-03-05 00:20
OK, thank you all for getting my head straightened out. I refactored and dumped the Reporter object and the ReportHelper module and went back to having all the needed code in ApplicationHelper. I liked the idea of encapsulating the entire report in an object to produce it and then rendering it line by line in the email, but this works. I guess everything just needs to be kept in its place. :-) Thx again and sorry for the noise.