Trying to Rails.cache.delete_matched from the runner - ruby-on-rails

On redmine 1.2/rails 2.3.11 I'm rendering a repository markdown file as html (as redmine_markdown_extra_viewer does), and now I'am trying to cache the result, which should be updated on each commit.
So I have a git hook that fetch the repo changes, and i'd like it to also clear the corresponding cache entries.
Cache generation (in a RepositoriesController::entry override):
cache_key =['repositories_md', #project.id.to_s, #path.to_s].join('/')
puts cache_key
#content = cache_store.fetch cache_key do
Kramdown::Document.new(#repository.cat(#path, #rev)).to_html
end
render :action => "entry_markdown"
The hook that should clear the cache, but has no effect:
# This is ok
ruby script/runner "Repository.fetch_changesets"
# This not
ruby script/runner "Rails.cache.delete_matched(/repositories_md\/.*/)"
So it doesn't work and i don't even know if i've taken the right direction to implement that. Any input much appreciated!

Which cache backend are you using?
If it's memcached or anything other than the FileStore or the MemoryStore, the delete_matched method is not supported.
You're probably better off letting them expire and just replace their cached contents as they get updated.

The problem is when using a Regular Expression as a fragment name, try using a String as a fragment name. Maybe get verbose. I had a similar problem with Dalli(with Memcached), and that was the reason.

Related

Rails 3 application/octet-stream

I am working on an application where I use paperclip for uploading images, then the image is manipulated in a flash app and returned to my application using application/octet-stream. The problem is that the parameters from flash are not available using params. I have seen examples where something like
File.open(..,..) {|f| f.write(request.body) }
but when I do this, the file is damaged some how.
How can I handle this in rails 3?
After you make sure that the request parameters have hit the Rails application, you may want to ensure that there were no parsing problems. Try to add these lines in you controller's action:
def update # (or whatever)
logger.debug "params: #{params.inspect}"
# I hope you do not test this using very large files ;)
logger.debug "request.raw_post: #{request.raw_post.inspect}"
# ...
end
Maybe the variable names got changed somehow? Maybe something escaped the parameter string one time too much?
Also, you have said that the file into which you want to save the request body is damaged. How exactly?
The request.body object does not need to be String. It may be a StringIO, for example, so you may want to type this:
File.open(..,..) {|f| f.write(request.body.read) }

Rails 3 - File name too long error

We have an online store running on Rails 3 Spree platform. Recently customers started reporting weird errors during checkout and after analyzing production logs I found the following error:
Errno::ENAMETOOLONG (File name too long - /var/www/store/tmp/cache/UPS-R43362140-US-NJ-FlorhamPark07932-1025786194_1%7C1025786087_1%7C1025786089_15%7C1025786146_4%7C1025786147_3%7C1025786098_3%7C1025786099_4%7C1025786100_2%7C1025786114_1%7C1025786120_1%7C1025786121_1%7C1025786181_1%7C1025786182_1%7C1025786208_120110412-2105-1e14pq5.lock)
I'm not sure why this file name is so long and if this error is specific to Rails or Spree. Also I'm not very familiar with Rails caching system. I would appreciate any help on how I can resolve this problem.
I'm guessing you are using spree_active_shipping, as that looks like a cache id for a UPS shipping quote. This will happen when someone creates an order that has a lot of line items in it. With enough line items this will of course create a very large filename for the cache, thus giving you the error.
One option would be to use memcache or redis for your Rails.cache instead of using the filesystem cache. Another would be to modify the algorithm that generates the cache_key within app/models/active_shipping.rb in the spree_active_shipping gem.
The latter option would probably be best, and you could simply have the generated cache key run through a hash like MD5 or SHA1. This way you'll get predictable cache key lengths.
Really this should be fixed within spree_active_shipping though, it shouldn't be generating unpredictably long cache keys, even if you a key-value store is used, that's wasted memory.
It is more related to your file system. Either set up a file system which supports longer file names or change the software to make better (md5?timestamp?unique id?) file names.
May be this help:
config.assets.digest and config.assets.debug can't both be true
It's a bug : https://github.com/rails/jquery-rails/issues/33
I am using rails 3.2.x and having same issue. I end up generating MD5 digest in the view helper method used to generate cache key.
FILENAME_MAX_SIZE = 200
def cache_key(prefix, params)
params = Array.wrap(params) if params.instance_of?(String)
key = "#{prefix}/" << params.entries.sort { |a,b| a[0].to_s <=> b[0].to_s }.map { |k,v| "#{k}:#{v}"}.join(',').to_s
if URI.encode_www_form_component(key).size > FILENAME_MAX_SIZE
key = Digest::MD5.hexdigest(key)
end
key
end
Here I have to check length of URI encoded key value using URI.encode_www_form_component(key).size because as you can see in my case, cache key is generated using : and , separators. Rails encodes the key before caching the results.
I took reference from the pull request.
Are you using paperclip gem? If yes, this issue is solved: https://github.com/thoughtbot/paperclip/issues/1246.
Please update your paperclip gem to the latest version.

Is there any gem can dump the data from and to yml files?

I'm find such a gem a whole day, but not find a good one. I want to write one, but I'm not able to do it.
The data in my database may be English text, which will be dump to a yml file with plain text. And some are non-English text, which will be binary type.
And both of them may have such code:
<% xxx %>
When I use rake db:fixtures:load to load them into database, error may occur: method xxx not found.
I wan't to find a good gem can handle this problem. Thank for any help
UPDATE
I have gave up finding such a gem. At first, I think it's a easy task, but now, after some researchings, I have to say, it's much harder than I expected.
The reason you are having problems is because the Fixture loader will pass your fixture through erb before loading the data. This means that if you have <% xxx %> in your yaml file then Rails will see that as erb and try to run a method called xxx.
There does not seem to be an easy way to turn off erb processing of fixtures. I have tried replacing the fixtures with CSV fixtures and this still does ERB pre-processing.
Without a simple answer I have to ask the question Why do you have these strings in your file?
Do you want them to be expanded by erb?
Err...I'm not sure if you actually need a gem for this? Rails natively can turn any model into YAML.
Let's say you have a model called "Objects". You could hit a route that looks like:
/objects.yaml
and you would get a giant text file of all your Objects in YAML form.
Of course, you would want to have something like:
respond_to do |format|
format.yaml {render :yaml => #objects}
end
in your restful controller.
If you'd rather not hit a route to do this, you can always do
#yaml = []
#objects.each do |object|
#yaml.push object.to_yaml
end
anywhere in ruby, which will give you an array of yaml objects, that you can then write to a file at your leisure.
I imagine that if rails itself is generating the yaml, then it would be able to then later load it as a fixture?

Caching Models in rails

I have a rails application, with a model that is a kind of repository.
The records stored in the DB for that model are (almost) never changed, but are read all the time. Also there is not a lot of them.
I would like to store these records in cache, in a generic way.
I would like to do something like acts_as_cached, but here are the issue I have:
I can not find a decent documentation for acts as cached (neither can I find it's repository)
I don't want to use memcached, but something simpler (static variable, or something like that).
Do you have any idea of what gems I could use to do that ?
Thanks
EDIT
I am still looking for something similar to cache_flu but without memcached
Could you store the data in a file and load it into a constant (as suggested on Ruby on Rails: Talk):
require "yaml"
class ApplicationController < ActionController::Base
MY_CONFIG = YAML.load(File.read(File.join(RAILS_ROOT, "config", "my_config.yml")))
end
I have started a gem called cache_me which can work with any cache_store
it's in Alpha mode but you can give a try and then open some pull request / Issues.
https://github.com/arunagw/cache_me
I will let you know when it's ready to use full mode.
acts_as_cached was superseded by cache_fu.
You can store data in rails default cache or, as seems to be the most popular choice, use mem_cache_store which uses memcached.
#production.rb
config.cache_store = :mem_cache_store, '127.0.0.1:11211', {:namespace => "production"}
#some_helper.rb
def get_some_data
Rails.cache.fetch('some_reference'){Model.find_some_data}
end
See also:
http://guides.rubyonrails.org/caching_with_rails.html
Also, if you're using passenger you'll need to do this:
if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
if forked
Rails.cache.instance_variable_get(:#data).reset if Rails.cache.class == ActiveSupport::Cache::MemCacheStore
else
# No need to do anything.
end
end
end

Exclude Sub Directory on Class Eager Load

I am facing an issue where my Rails application is set to cache classes when run in the staging or production environment. While load_paths only contains 'app/models', it appears that the initialization steps recursively caches everything in 'app/models'.
# Eager load application classes
def load_application_classes
if configuration.cache_classes
configuration.eager_load_paths.each do |load_path|
matcher = /\A#{Regexp.escape(load_path)}(.*)\.rb\Z/
Dir.glob("#{load_path}/**/*.rb").sort.each do |file|
require_dependency file.sub(matcher, '\1')
end
end
end
end
The problem in this is that we have a sub directory within 'app/models' that contains files with require statements that reference a concurrent JRuby environment. Since Rails knows nothing of this environment our application breaks on load.
As it stands, here are the proposed solutions...unfortunately only #1 is ideal.
1) The simplest solution would be to exclude the culprit sub directory, but have not found anything how to accomplish this.
2) Monkey patch the load_application_classes method to skip the specific sub directory.
3) Move the sub directory out from under 'app/models'. Feels a bit hackish and would require quite a few code changes.
Thoughts?
As a temporary measure you could go with a version of option 2 and override the definition of load_application_classes, replacing it with an empty implementation. That would force you to explicitly require the classes you need but it would give you complete control over what gets loaded and would be a completely transparent solution.
It sounds like your application is sufficiently sophisticated that it's growing beyond the Rails framework. I know that this doesn't directly answer your question so appologies in advance but you may want to consider looking at an alternative Ruby framework like Merb. Rails is great but sooner or later you bump into edge of the framework - sounds like that's where you are now.
We made the switch to Merb last year and haven't regreated it.
Chris

Resources