Use ActiveSupport::Cache::FileStore directly in a model class - ruby-on-rails

I tried to use ActiveSupport::Cache::FileStore dirctly in a model class:
#backend_cache = ActiveSupport::Cache::FileCache.new Rails.root.join("tmp", "cache")
The program reports a NameError
NameError: uninitialized constant ActiveSupport::Cache::FileCache
Did you mean? FileTest
I added
require "active_support"
require "active_support/core_ext"
It still shows the error. I know that I can use Rails.Cache for the purpose, but the object I cached must be on the disk, which is different from other parts of the application.
The application is written in Rails 6.

I tried this inside a rails 6 console and it works just fine.
#backend_cache = ActiveSupport::Cache::FileStore.new(Rails.root.join("tmp", "cache"))
#backend_cache.write('x', 1) # => true
#backend_cache.read('x') # => 1
It's just typo I mentioned in the comment. It's ::FileStore.new instead of ::FileCache.new

Related

Rails 6 ActionText isn't working on Heroku (undefined method 'rich_text_area_tag')

I am using ActionText to edit a paragraph and it works perfectly locally but when I deploy it to Heroku the page which has the form with rich_text_area it throws an error saying undefined method rich_text_area_tag even though I followed the rails guide. I thought I needed to configure Active Storage on production but that's not the case.
Here is what I am getting in Heroku's logs:
ActionView::Template::Error (undefined method 'rich_text_area_tag' for #<#<Class> Did you mean? rich_text_area)
<%= f.label :something, class:'label' %>
<%= f.rich_text_area :something %>
I found this online, and it was helpful for me:
https://github.com/JoeWoodward/spree_helper_issue
I am not sure if this is the correct way to do it, but it's a temporary workaround.
SOLUTION:
In application_controller.rb enter the following:
require 'action_text'
class ApplicationController < ActionController::Base
helper ActionText::Engine.helpers
...
end
Docs for helper: https://apidock.com/rails/AbstractController/Helpers/ClassMethods/helper
First of all make sure that you have this line in config/application.rb:
require 'rails/all'
If it's a rails 6 app action_text/engine should be loaded.
If it doesn't it's possible taht zeitwerk is not loaded. This happens when you have a rails 5.2 app that was updated to rails 6.
In the same file (config/application.rb) you have to change config.load_defaults to 6.0:
config.load_defaults 6.0
If you want to know what happens in the background take a look at this link on line 125.
To avoid cluttering the ApplicationController code, you can use an initializer:
i.e. add a new file config/initializers/action_text.rb:
ActiveSupport.on_load(:action_view) do
include ActionText::ContentHelper
include ActionText::TagHelper
end
Inspired by p8's comment in a closed Rails issue.

rails - files in autoload_paths folder aren't loaded

I have a app/extensions folder where my custom exceptions reside and where I extend some of the Ruby/Rails classes. Currently there are two files: exceptions.rb and float.rb.
The folder is specified in the ActiveSupport::Dependencies.autoload_paths:
/Users/mityakoval/rails/efo/app/extensions/**
/Users/mityakoval/rails/efo/app/assets
/Users/mityakoval/rails/efo/app/channels
/Users/mityakoval/rails/efo/app/controllers
/Users/mityakoval/rails/efo/app/controllers/concerns
/Users/mityakoval/rails/efo/app/extensions
/Users/mityakoval/rails/efo/app/helpers
/Users/mityakoval/rails/efo/app/jobs
/Users/mityakoval/rails/efo/app/mailers
/Users/mityakoval/rails/efo/app/models
/Users/mityakoval/rails/efo/app/models/concerns
/Users/mityakoval/rails/efo/app/template.xlsx
/Users/mityakoval/.rvm/gems/ruby-2.4.1#web_app/gems/font-awesome-rails-4.7.0.2/app/assets
/Users/mityakoval/.rvm/gems/ruby-2.4.1#web_app/gems/font-awesome-rails-4.7.0.2/app/helpers
/Users/mityakoval/rails/efo/test/mailers/previews
The reason for it to be listed there twice is that it should be automatically loaded since it was placed under app directory and I have also manually added it to the autoload_paths in application.rb:
config.autoload_paths << File.join(Rails.root, 'app', 'extensions/**')
The strange thing is that my exceptions.rb is successfully loaded at all times, but the float.rb isn't unless eager loading is enabled.
Answers to this question say that it might be related to Spring (which I tend to believe), so I've added the folder to spring.rb:
%w(
.ruby-version
.rbenv-vars
tmp/restart.txt
tmp/caching-dev.txt
config/application.yml
app/extensions
).each { |path| Spring.watch(path) }
I've restarted Spring and the Rails server multiple times and nothing worked. Does anyone have any suggestions?
Ruby version: 2.4.1
Rails version: 5.1.5
EDIT
/Users/mityakoval/rails/efo/app/extensions/float.rb:
class Float
def comma_sep
self.to_s.gsub('.', ',')
end
end
rails console:
irb> num = 29.1
irb> num.comma_sep
NoMethodError: undefined method `comma_sep' for 29.1:Float
from (irb):2
A better way to monkeypatch a core class is by creating a module and including it in the class to be patched in an initializer:
# /lib/core_extensions/comma_seperated.rb
module CoreExtensions
module CommaSeperated
def comma_sep
self.to_s.gsub('.', ',')
end
end
end
# /app/initializers/core_extensions.rb
require Rails.root.join('lib', 'core_extensions', 'comma_seperated')
# or to require all files in dir:
Dir.glob(Rails.root.join('lib', 'core_extensions', '*.rb')).each do |f|
require f
end
Float.include CoreExtensions::CommaSeperated
Note that here we are not using the Rails autoloader at all and explicitly requiring the patch. Also note that we are placing the files in /lib not /app. Any files that are not application specific should be placed /lib.
Placing the monkey-patch in a module lets you test the code by including it in an arbitrary class.
class DummyFloat
include CoreExtensions::CommaSeperated
def initialize(value)
#value = value
end
def to_s
#value.to_s
end
end
RSpec.describe CoreExtensions::CommaSeperated do
subject { DummyFloat.new(1.01) }
it "produces a comma seperated string" do
expect(subject.comma_sep).to eq "1,01"
end
end
This also provides a much better stacktrace and makes it much easier to turn the monkey patch off and on.
But in this case I would argue that you don't need it in the first place - Rails has plenty of helpers to humanize and localize numbers in ActionView::Helpers::NumberHelper. NumberHelper also correctly provides helper methods instead of monkeypatching a core Ruby class which is generally best avoided.
See:
3 Ways to Monkey-Patch Without Making a Mess

Cannot override core ruby class in Rails 2.3.4

I want to extend the ruby class, for example,
# lib/core_ext/hash.rb
class Hash
def gop_compact
delete_if{|k, v| (k.blank? || v.blank?)}
end
end
I have created a separate folder in the /lib directory as follows,
lib/core_ext/hash.rb
And I tried to include this path in load_paths as follows,
# config/environment.rb
config.load_paths += %W( #{RAILS_ROOT}/lib/core_ext )
After all this setup, restarted the server and tried calling method on a Hash object but it throws an undefined method exception.
Note:- Rails version is 2.3.4
I spent lot of time on this but no luck yet. Any help is appreciated.
Thanks in advance!
Even though you've added the core_ext folder to your load paths, you'll still need to require it with require 'hash'. To minimize memory usage, Rails won't actually require ruby files just because you add them to your load_path.
>> Hash.instance_methods.grep(/gop/)
=> []
>> require "hash"
=> true
>> Hash.instance_methods.grep(/gop/)
=> [:gop_compact]

Rails ckeditor dragonfly Erorr

Gem => https://github.com/galetahub/ckeditor
Rails = 4.1.4
I've done
rails generate ckeditor:install --orm=active_record --backend=dragonfly
ckeditor_dragonfly.rb
# Load Dragonfly for Rails if it isn't loaded already.
require "dragonfly/rails/images"
# Use a separate Dragonfly "app" for CKEditor.
app = Dragonfly[:ckeditor]
app.configure_with(:rails)
app.configure_with(:imagemagick)
# Define the ckeditor_file_accessor macro.
app.define_macro(ActiveRecord::Base, :ckeditor_file_accessor) if defined?(ActiveRecord::Base)
app.define_macro_on_include(Mongoid::Document, :ckeditor_file_accessor) if defined?(Mongoid::Document)
app.configure do |c|
# Store files in public/uploads/ckeditor. This is not
# mandatory and the files don't even have to be stored under
# public. If not storing under public then set server_root to nil.
c.datastore.root_path = Rails.root.join("public", "uploads", "ckeditor", Rails.env).to_s
c.datastore.server_root = Rails.root.join("public").to_s
# Accept asset requests on /ckeditor_assets. Again, this is not
# mandatory. Just be sure to include :job somewhere.
c.url_format = "/uploads/ckeditor/:job/:basename.:format"
end
# Insert our Dragonfly "app" into the stack.
Rails.application.middleware.insert_after Rack::Cache, Dragonfly::Middleware, :ckeditor
But when I try to do something, an error:
Dragonfly::App[:ckeditor] is deprecated - use Dragonfly.app (for the default app) or Dragonfly.app(:ckeditor) (for extra named apps) instead. See docs at http://markevans.github.io/dragonfly for details
NoMethodError: undefined method `configure_with' for Dragonfly:Module
What ideas are there to solve the problem?
UPD. If correct these errors, it becomes:
Dragonfly::Configurable::UnregisteredPlugin: plugin :rails is not registered
Remove all ckeditor initializers.
Add new file with following content:
require 'dragonfly'
# Logger
Dragonfly.logger = Rails.logger
# Add model functionality
if defined?(ActiveRecord::Base)
ActiveRecord::Base.extend Dragonfly::Model
ActiveRecord::Base.extend Dragonfly::Model::Validations
end
Dragonfly.app(:ckeditor).configure do
# this generate path like this:
# /uploads/ckeditor/AhbB1sHOgZmIjIyMDEyLzExLzIzLzE3XzIxXzAwXzY0OF9zdXJ2ZWlsbGFuY2VfbmNjbi5wbmdbCDoGcDoKdGh1bWJJI.something.png
url_format '/uploads/ckeditor/:job/:basename.:format'
# some image from previous version can break without this
verify_urls false
plugin :imagemagick
# required if you want use paths from previous version
allow_legacy_urls true
# "secure" if images needs this
secret 'ce649ceaaa953967035b113647ba56db19fd263fc2af77737bae09d452ad769d'
datastore :file,
root_path: Rails.root.join('public', 'system','uploads', 'ckeditor', Rails.env),
server_root: Rails.root.join('public')
end
Rails.application.middleware.use Dragonfly::Middleware, :ckeditor
This will store image in (old style):
{Rails.root}/public/system/uploads/ckeditor/{development,production,etc...}
Eraden, your example works. I've replaced the contents of ckeditor_dragonfly.rb with what you've given and then "rake db:migrate" was finally successfull.
But then when I upload an image I get:
NoMethodError (undefined method ckeditor_file_accessor' for #<Class:0x007fb92c720118>):
app/models/ckeditor/asset.rb:5:in'
app/models/ckeditor/asset.rb:1:in <top (required)>'
app/models/ckeditor/picture.rb:1:in'
It seems, you need to replace "ckeditor_file_accessor :data" with "dragonfly_accessor :data" in /app/model/ckeditor/asset.rb. This solved this particular error for me, though I've got another one instead, but it seems to have nothing to do with the topic discussed.
(just for the case, I will write this problem here:
DRAGONFLY: validation of property format of data failed with error Command failed ('identify' '-ping' '-format' '%m %w %h' '/var/folders/x6/pwnc5kls5d17z4j715t45jkr0000gr/T/RackMultipart20150406-2109-1ho7120') with exit status and stderr dyld: Library not loaded: /usr/local/lib/liblzma.5.dylib
Referenced from: /usr/local/bin/identify
Reason: image not found
)

Production uninitialized constant custom class stored in lib (heroku)

I have a custom class stored in /lib (/lib/buffer_app.rb):
require 'HTTParty'
class BufferApp
include HTTParty
base_uri 'https://api.bufferapp.com/1'
def initialize(token, id)
#token = token
#id = id
end
def create(text)
message_hash = {"text" => text, "profile_ids[]" => #id, "access_token" => #token}
response = BufferApp.post('/updates/create.json', :body => {"text" => text, "profile_ids[]" => #id, "access_token" => #token})
end
end
I'm attempting to use this this class in an Active Admin resource and get the following error when in production (Heroku):
NameError (uninitialized constant Admin::EventsController::BufferApp):
It's worth noting I have this line in my application.rb and that this functionality works locally in development:
config.autoload_paths += %W(#{Rails.root}/lib)
If I try include BufferApp or require 'BufferApp' that line itself causes an error. Am I having a namespace issue? Does this need to be a module? Or is it a simple configuration oversight?
I had exactly the same problem with Rails 5 alpha. To solve it, I had to manually require the file:
require 'buffer_app'
and not: (require 'BufferApp')
Even if Michal Szyndel's answer makes great sense to me, after manually requiring the file, prefixing :: to the constant was non influential in my case.
Anyway I am not satisfied with the manual requiring solution because I need to add code which is environment specific. Why don't I need to require the files manually in development?
Change this
config.autoload_paths += %W(#{Rails.root}/lib)
to this
config.eager_load_paths += %W(#{Rails.root}/lib)
eager_load_paths will get eagerly loaded in production and on-demand in development. Doing it this way, you don't need to require every file explicitly.
See more info on this answer.
Error line says it all, you should reference class as ::BufferApp

Resources