Event Model

Does anyone know the best way to let a controller know something
happened from a method in a model?

In other words, I want to run an some code in a worker thread in a
model, and update the view every so often. I could just put the code in
the controller, but it’s business logic that seems best suited to a
model.

Thanks in advance.

The whole point of the Action Cache is to avoid executing the action.

With your modifications, the action is always executed. The purpose of
the before_filter is to send the cached result instead of executing the
action - the ‘false’ line tells Rails to stop executing filters and not
call the action method. If you remove the before_filter code, the
action will always execute.

Hey

Here’s the code for action_cache around_filters…

def before(controller)
return unless @actions.include?(controller.action_name.intern)
action_cache_path = ActionCachePath.new(controller)
if cache = controller.read_fragment(action_cache_path.path)
controller.rendered_action_cache = true
set_content_type!(action_cache_path)
controller.send(:render_text, cache)
false
end
end

def after(controller)
return if !@actions.include?(controller.action_name.intern) ||
controller.rendered_action_cache
controller.write_fragment(ActionCachePath.path_for(controller),
controller.response.body)
end

Why isn’t the before_filter just the first line (checking to see if the
current action need be cached), with the rest of its code in the
after_filter? I’m trying to figure out what the consequences would be
of:

def before(controller)
return unless @actions.include?(controller.action_name.intern)
end

def after(controller)
action_cache_path = ActionCachePath.new(controller)
if cache = controller.read_fragment(action_cache_path.path)
controller.rendered_action_cache = true
set_content_type!(action_cache_path)
controller.send(:render_text, cache)
false
end

return if [email protected]?(controller.action_name.intern) ||

controller.rendered_action_cache
controller.write_fragment(ActionCachePath.path_for(controller),
controller.response.body)
end

Thanks in advance
Gustav P.
[email protected]

Hmm,

I’m not sure this really answered my original question, did it?

Tom F. wrote:

The whole point of the Action Cache is to avoid executing the action.

With your modifications, the action is always executed. The purpose of
the before_filter is to send the cached result instead of executing the
action - the ‘false’ line tells Rails to stop executing filters and not
call the action method. If you remove the before_filter code, the
action will always execute.

No, this didn’t answer the first question. But it did answer the
second, completely unrelated question about the Action Cache
before_filter code.

For the first question: Rails doesn’t do threading, and has a lock to
keep multiple threads out of the Rails code (trust me, don’t try and
get around this)

To run long-running background tasks, check out Ezra’s BackgroundRB
system:
Ruby on Rails Blog / What is Ruby on Rails for?, it
may help you do what you want

Thanks Tom!

I’ve since figured this out after long hours of sweating over a plugin!
:]

I asked because I wanted to start working on a plugin (patch?) that’d
let
you keep multiple versions of an action_cached page. I’ve since opted
for an around_filter approach (which also circumvents the code in the
action of course ;] ), and its working beautifully! At the moment the
syntax looks as follows:

class WelcomeController < ApplicationController

cache_filter :index, :faq do | cache |
if cache.session[:logged_in]
cache.as :logged_in
else
cache.as :logged_out
end
end

def index
end

def faq
end

end

Anyway, I’ve finished it earlier this evening and applied to have the
plugin kept
at rubyforge. I’ll post to the list once its checked in.

Thanks again for the help man! When I started out I though
action_caching would
still execute the code in the action (now it seems so obvious that it
shouldn’t, but
back then it wasn’t :] ) but just serve the rendered tempalte from cache
instead of
doing all the ERb stuff etc…

This is the first time I’ve gone peeking into the rails source, which
has given me a
new found respect for all the contributors!

Anyway, thanks again,

Cheery-o
Gustav P.
[email protected]

About the event from the model I mean.

Guest wrote:

Hmm,

I’m not sure this really answered my original question, did it?

Tom F. wrote:

The whole point of the Action Cache is to avoid executing the action.

With your modifications, the action is always executed. The purpose of
the before_filter is to send the cached result instead of executing the
action - the ‘false’ line tells Rails to stop executing filters and not
call the action method. If you remove the before_filter code, the
action will always execute.

Wow, I should have proof-read that last post ; /

Sorry about the spelling errors…they irk me as much as anyone.

Gustav P.
[email protected]

My action_cache plugin already allows this type of behavior, in a
different way.

I’ve used it in an app to cache for ‘admin’, ‘logged in user’ and ‘not
logged in user’, and my site uses themes, so the theme name is also
part of the cache key. It is configurable to allow any available
setting to be used to influence the cache.

Check it my blog postings (http://blog.craz8.com/) for details,
script\plugin install action_cache will get the latest code.

My plugin also fixes some bugs in Rails action_cache, and does stuff
like return 304s for unchanged content. The latest version can also
use the x-sendfile header in lighttpd and x-accel-redirect in nginx to
further reduce overhead.

Hi Tom

I checked out your plugin and it is excellent! The bottom code is the
part that let’s you assign custom keys?

ActionController::Caching::Actions::ActionCacheFilter.fragment_key =
Proc.new {|controller|

“AC:#{controller.request.host_with_port}:#{controller.params.sort.join(’:’).gsub(’
', ‘-’)}”
}

Obviously the developer can make the block more interesting as he’s got
access to the controller object etc. (but you wrote it, so you know :] )

The only thing I prefer about my plugin is the syntax, but perhaps I can
integrate it with your plugin so mine acts as a simpler wrapper. From
looking at your plugin, it seems like mine will already wrap yours with
no modifications to either! I only modify ActionCachePath, and add a
class method and class variable to ActionController…none of which look
like they intrude upon your work. If you don’t mind, I’ll run both on
the same project for a while and let you know how it goes.

Thanks for your great work dude! Its really excellent! In short, my
plugin doesn’t mod action_cache in any way that interferes with yours,
so if your plugin is installed on the same project, I’m pretty sure mine
will make full use of it, giving the best of both to the developer.

But like I said, I’ll be trying them out in parallel and see if they can
enjoy a symbiotic relationship.

I still haven’t uploaded mine to rubyforge, but the moment I do I’ll be
sure to let you know(if you’re interested in the least :] )

Cheery-o
Gustav P.
[email protected]