How to extend the String class in a command line app? - ruby-on-rails

I primarily work in Rails and I'm using a command line data conversion gem, "Mongify" and I am stumped about how to extend core classes in a Ruby cli app.
I want to extend the String class with an .is_date? method to check whether a string can be converted to a Date. I've got it working in the Rails Console,
I added a string.rb file to lib/ext with the following;
class String
def is_date?
begin
return true if Date.parse(self)
rescue
#do nothing
end
return false
end
end
Then in a Rails console I do a require 'ext/string' and it will work.
But I can't figure out how to get it to work in the Mongify cli app. I copied string.rb into the lib folder of the gem and I've tried adding require 'string' to a number of different files in the gem, but I keep getting undefined method errors.
Can someone point me in the right direction?

How about you require it from lib/mongify.rb like so:
require 'string/extensions.rb'
And then put your code in lib/string/extensions.rb
Let us know the exact undefined method errors you're getting in case this isn't the solution.

To help you with the debugging exercise that would give you the answer you need. Start by putting a breakpoint right before the place of the function call.
In the debugger, load the required document and then step past your breakpoint to the next one after the call has occurred.
Once you have this working, then start earlier in the stack trace – in a file that loaded before that one. Keep moving backwards until you get to a sufficiently early part in the load process of the gem, and make that be the place you load your code.

Related

Unable to use active record time methods inside ruby on rails 5.0 model

I'm currently unable to use any of the active support time methods inside my ruby on rails 5.0 model like the following:
5.seconds
2.days
10.minutes
throws an error:
NoMethodError: undefined method `seconds' for AS::Duration:0x007f97a5903b90 #value=5, #parts=[[:seconds, 5]] Did you mean? send
EDIT: here is the actual code causing an issue.
ReminderJob.set(wait: 5.seconds).perform_later(self.user.id)
Even tho I can see people using the below code fine and it works
UserReminderJob.set(wait: 1.week).perform_later user
However, it works in my console and in my controllers and views.
The error message states that the object is AS::Duration:0x007f97a5903b90, NOT an integer -- therefore the example of 5.seconds will not reproduce the problem.
This is also unusual, since 5.seconds will normally return an ActiveSupport::Duration object, not AS::Duration.
I would therefore hazard a guess that you're actually using the as-duration ruby gem rather than built-in rails behaviour. This extends the the Integer class in a different way, and returns an object that doesn't behave like an integer.
I think that an actual reproduction of your error could be achieved with: 5.seconds.seconds. In standard rails, this works fine (and returns the same value as 5.seconds), since ActiveSupport::Duration instances behave like Integers. But with this gem, it fails with the above error.

Monkey patching a db model class in Rails with Mongoid causes weird behaviour

I am using a development script file to check out new possible ideas. Recently I tried to monkey patch MyDBObject from within that script file.
Assume an empty dev.rb file and add a monkey patch right in the top like so:
class MyDBObject
def test_function
'function works'
end
end
Starting up the pry console and loading the file yields random results.
First I received:
NoMethodError: undefined method `relations' for MyDBObject:Class
Later the script loaded, but I couldn't access the original class any longer:
undefined method `first' for MyDBObject:Class
I noticed that prepending the line:
MyDBObject
right before the monkey patching, the intended functionality is achieved.
This appears to be some sort of lazy loading of the class objects. Can somebody cast some light on this for me please?
Depending on the order in which source files are loaded, you'll either be redefining the entire class, or having your changes replaced.
I highly recommend giving this a read: http://www.justinweiss.com/articles/3-ways-to-monkey-patch-without-making-a-mess/ (TLDR - put your patch in a module and explicitly include it)

Now that ActiveRecord::Base.silence {} is gone, how do I bring back that functionality?

I do a lot of spatial queries that dump massive amounts of text in the form of logs every time I run queries. These slow down my programs enormously.
I'm being forced to update my rails to '4.1.2' from '4.0.0' and ActiveRecord::Base.silence has been completely deprecated as in, it doesn't work. Here's what used to work
ActiveRecord::Base.silence do
noisy_query
end
When I try this now, I get this error....
ArgumentError: wrong number of arguments (0 for 1)
from /Users/davidddouglas/.rvm/gems/ruby-1.9.3-p551/gems/activesupport-4.1.2/lib/active_support/core_ext/kernel/reporting.rb:82:in `capture'
In 4.0.0 it sent a deprecation warning, and now the script just doesn't work. Oddly enough, the function is still declared, it just doesn't work anymore and expects some kind of parameter. I've tried passing in nil and got this error:
NoMethodError: undefined method `reopen' for nil:NilClass
I'm looking for a way to monkeypatch the old functionality back into my program to get my scripts to work again. Not too worried about best practices as this is an application I'm using internally with little to no front end and 0 users other than myself.
Thanks
silence moved to a core extension on logger.
From their example,
logger = Logger.new("log/development.log")
logger.silence(Logger::INFO) do
logger.debug("In space, no one can hear you scream.")
logger.info("Scream all you want, small mailman!")
end

Install generator won't see a method I defined

I'm trying to use my Engine in another app to test the install generator and it seems to be failing. I haven't used my install generator for a long time, so I'm not sure when it broke (or if it ever truly smoothly worked). My project is based off radar/forem, so I tried to borrow a lot of their code (including the generator).
Edit: My installer works for the engines test/dummy but not in other apps. Why?
GH issue: https://github.com/NJayDevelopment/mongoid_forums/issues/16
Here is the log:
$ rails g mongoid_forums:install
What is your user class called? [User]
What is the current_user helper called in your app? [current_user]
Defining mongoid_forums_user method inside ApplicationController...
insert app/controllers/application_controller.rb
Adding mongoid_forums initializer (config/initializers/mongoid_forums.rb)...
create config/initializers/mongoid_forums.rb
(erb):5:in `template': undefined method `per_page' for MongoidForums:Module (NoMethodError)
The route is successfully added, however the initializer/mongoid_forums.rb is a blank file. The method is defined exactly how radar/forem does it, what could be the error?
Here is the relevant code:
Per page method definition: https://github.com/NJayDevelopment/mongoid_forums/blob/master/lib/mongoid_forums.rb#L33
Mattr accessor:
https://github.com/NJayDevelopment/mongoid_forums/blob/master/lib/mongoid_forums.rb#L9
Initializer template:
https://github.com/NJayDevelopment/mongoid_forums/blob/master/lib/generators/mongoid_forums/install/templates/initializer.rb
Install generator at error point:
https://github.com/NJayDevelopment/mongoid_forums/blob/master/lib/generators/mongoid_forums/install_generator.rb#L47
Turns out when you try requiring mongoid_forums in pry, you'll see that an error involving decorators occurs. The issue is fixed here in my pull request to decorators: parndt/decorators#13
It's because of the way files are required and how load! is called over there.
Waiting on PR status, that is the same version that radar/forem uses as well.

How do I use a custom log for my rake tasks in Ruby on Rails?

I have a rake task that calls functions like this:
namespace :blah do
task :hello_world => :environment do
logger.info("Hello World")
helloworld2
end
end
def helloworld2
logger.info("Hello Again, World")
end
I want the log output to a custom log, and I really don't want to have to pass a log reference every time I make a function call. I found this somewhere (can't find it again):
def logger
##logger ||= Logger.new("#{RAILS_HOME}/log/blah.log")
end
But this does not work for me and I am not sure what it even does because I grabbed the code a long time ago and haven't used it until now. I can't search for ## on google (tried +"##" rails) to see what it does. Any help on this issue would be great. I am hoping for a quick solution and not having to install a gem or plugin (unless there is a really really good reason to.
Thanks!
rake disables logging in production mode. make sure you're running in development mode if you want it to log
What do you mean by "does not work for me"? I just tried this same code and it worked - created a new log file and put some text in it.
##logger is a class variable, it's a language issue, not Rails' one. I believe there's no need in further explanations :)
You've probably mistaken typing "function helloworld2" :)
Advanced Rails Recipes Recipe 84 from #topfunky shows how to define a custom logger. He has some code in the environment config file (production would look like this): RAILS_ROOT/config/environments/production.rb:
config.logger = RAILS_DEFAULT_LOGGER = Logger.new(config.log_path)
I'd test that out instead of redefining the class variable as you have. He might have something on http://nubyonrails.com to check as well.

Resources