Ruby on Rails docsplit file path - ruby-on-rails

I have a pdftotext.rb file in /lib and the code is
module Pdftotext
require 'rubygems'
require 'docsplit'
class << self
def convert
Docsplit.extract_text("hello.pdf")
end
end
end
I have the hello.pdf file in the /assets folder and I tried "assets/hello.pdf" but it keeps telling me Error: Couldn't open file '/assets/hello.pdf': No such file or directory.
How can I get the right path to get the file to be converted?
By the way I am using rails 3.2.1, thanks.

Do you mean it is in RAILS_ROOT/assets/hello.pdf?
You should use File.join to get at the file. Like this:
module Pdftotext
require 'rubygems'
require 'docsplit'
class << self
def convert
Docsplit.extract_text(File.join(Rails.root, "assets", "hello.pdf"))
end
end
end
Using "/assets/hello.pdf" will try to get it from the file system root.

Related

undefined local variable or method for method located in lib directory file

I have some code i've inherited and am in the process of upgrading it to Rails 3.1. I'm suuuuper close to done but I got a bug.
In Rails Console I run User.first and I get this error
undefined local variable or method `acts_as_userstamp' for #<Class:0x000000046bef50>
Now acts_as_userstamp is a method located on line two inside my User model
class User < ActiveRecord::Base
#TODO /lib is not loading??? or is it??? why this method not work in browser?
acts_as_userstamp
And is defined in a file called app/lib/model_modifications.rb.
Now I recently discovered that my app/lib folder was not being autoloaded in my application.rb file and I think that's been fixed...or has it? Is this file correct? Or no?
require File.expand_path('../boot', __FILE__)
require 'rails/all'
# evil outdated soap middleware, TODO: kill it with fire
# Does this have to be loaded BEFORE the first line???
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', "vendor", "soap4r"))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', "vendor", "plugins", "soap4r-middleware", "lib"))
# evil outdated soap middleware, TODO: kill it with fire
require 'soap4r-middleware'
require File.join(File.dirname(__FILE__), '..', 'app', 'lib', 'soap.rb')
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require *Rails.groups(:assets => %w(development test))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module MyappDev
class Application < Rails::Application
# startup the lib directory goodies <-- IS THIS CORRECT???
# config.autoload_paths << "#{Rails.root}/lib"
# config.autoload_paths += %W( lib/ )
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
config.middleware.use MyAPIMiddleware
end
end
I'm trying to debug this file as I post this now. Here is a peak at it's internal structure...(i've just included the overall structure for the sake of brevity)
app/lib/model_modificatons.rb
class Bignum
...
end
class Fixnum
...
end
class ProcessorDaemon
...
end
module ActiveRecord
module UserMonitor
...
end
module MyLogger
...
end
end
class Object
...
end
class Struct
...
end
class String
...
end
class Fixnum
...
end
class OpenStruct
...
end
class ActiveRecord::Base
def self.visible_columns
...
end
...
def self.acts_as_userstamp
logger.info "HI fonso - acts_as_userstamp is called"
include ActiveRecord::UserMonitor
end
...
protected
def self.range_math(*ranges)
...
end
end
class Array
...
end
class DB
...
end
If you can spot a problem with the overall structure or anywhere else please let me know.
So why is this method not found? I'm trying to debug it as I'm posting this and I'm getting nothing.
I suspect the file app/lib/model_modifications.rb is not being loading. That nothing in the /lib directory is being loaded..but how do I confirm this?
Thank you for reading this far, I hope I've not rambled on too much.
autoload_path configuration does not load all the given files on the boot but defines folders where rails will be searching for defined constants.
When your application is loaded, most of the constants in your application are not there. Rails have a "clever" way of delaying loading the files by using a constant_missing method on Module. Basically, when Ruby encounters a constant in the code and fails to resolve it, it executes said method. THe sntandard implementation of this method is to raise UndefinedConstant exception, but rails overrides it to search all of its autoload_paths for a file with a name matching the missing constant, require it and then check again if the missing constant is now present.
So, in your code everything works as expected and you need to load this extension file manually. If you want to have some code that executes on the application boot, put your file within config/initializers folder.
Aside: Try avoiding monkey patching whenever possible. It might be looking clever, but adding more methods to already overpopulated classes will not make them easier to use.

why does my rails generator template method results in 'file_clash'

So I'm writing a rails generator to do the most simple of things: copy some model files from a gem's lib/generators/pathways/templates directory into a project in the app/models directory. My possibly mistaken understanding is that the template method is basically a file copy with source/target.
(note that "pathways" is the name of my gem that installs this generator)
Here's the guts of the copy code in the generator:
def copy_models
project_models_location = "#{Rails.root}/app/models/"
[
"pathways_experiment.rb",
...
].each do |filename|
puts "copying #{filename} to #{project_models_location}"
template filename, "#{project_models_location}"
end
end
The puts displays what I expected:
copying pathways_experiment.rb to
/Users/meuser/Projects/testing_gem/exp_gem_test/app/models/
however, the call to the templates method dumps this output:
file_clash app/models
I checked the target directory and there are no files in it, so it doesn't seem to be because the code is trying to overwrite the file.
here's the source of the entire generator in case I simply haven't included or extended the correct classes/modules:
require 'rails/generators'
require 'rails/generators/active_record'
module Pathways
class InstallGenerator < ActiveRecord::Generators::Base
include Rails::Generators::Migration
source_root File.expand_path("../templates", __FILE__)
def code_that_runs
puts "PATHWAYS: installing models"
copy_models
end
private
def copy_models
project_models_location = "#{Rails.root}/app/models/"
[
"pathways_experiment.rb",
...
].each do |filename|
puts "copying #{filename} to #{project_models_location}"
template filename, "#{project_models_location}"
end
end
end
end

LoadError (Unable to autoload constant XYZ, expected XYZ.rb to define it) in development environment

Recently, I can't make changes to my app without restarting my development server, otherwise I receive this error:
LoadError (Unable to autoload constant BotFeedback, expected ../../bot_feedback.rb to define it)
This hasn't been a problem before and I'm not entirely sure why this has become a problem. I have these settings configured in application.rb:
# Auto-load the bot and its subdirectories
config.paths.add File.join('app', 'bot'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'bot', '*')]
My app/bot folder includes files such as:
bot.rb with:
require "#{Rails.root}/app/bot/orderbot.rb"
Bot.on :message do |message|
OrderBot.new()
..
end
def somefunction
OrderBot.new()
..
end
orderbot.rb with:
require "#{Rails.root}/app/bot/bot_feedback.rb"
require "#{Rails.root}/app/bot/bot_demo.rb"
require "#{Rails.root}/app/bot/bot_helper.rb"
class OrderBot
include BotFeedback
include BotDemo
include BotHelper
(many more includes)
..
end
bot_feedback.rb with:
require "#{Rails.root}/app/models/concerns/sharedmethods.rb"
class OrderBot
include Sharedmethods
module BotFeedback
...
end
end
bot_demo.rb with:
class OrderBot
module BotDemo
..
end
end
bot_helper.rb with:
require "#{Rails.root}/app/models/concerns/sharedmethods.rb"
class OrderBot
include Sharedmethods
module BotHelper
...
end
end
My guess is that including the sharedmethods file is causing this because I don't see anything else being a problem. Changing the sharedmethods file in the rails app has always seemed to require restarting the server.
I would appreciate any help/suggestions.
UPDATE:
Looks like using 'load' instead of 'require' seems to solve the problem. I'm not sure this is the right way to go about it though.. because it will take up more memory if the files are being loaded again and again?
load "#{Rails.root}/app/bot/bot_feedback.rb"
load "#{Rails.root}/app/bot/bot_demo.rb"
load "#{Rails.root}/app/bot/bot_helper.rb"
Finally figured out the answer after learning everything about rails 'autoload' and 'require'
I don't actually need to 'require' any of the files because they are already autoloaded. The culprit was the 'module', it wasn't necessary.

How to use a RubyGems class in a Rails app

I need to stream a TAR file using data from the database in a Rails app.
I know that RubyGems has the TarWriter module that suits my use case perfectly.
The question is, how can I include the module in my Rails app?
I tried to require rubygems/package as follows:
require 'zlib'
require 'rubygems/package'
tar = StringIO.new
Gem::Package::TarWriter.new(tar) do |writer|
writer.add_file("a_file.txt", 0644) do |f|
(1..1000).each do |i|
f.write("some text\n")
end
end
writer.add_file("another_file.txt", 0644) do |f|
f.write("some more text\n")
end
end
tar.seek(0)
gz = Zlib::GzipWriter.new(File.new('this_is_a_tar_gz.tar.gz', 'wb'))
gz.write(tar.read)
tar.close
gz.close
The require failed on the controller. I tried to adding gem 'rubygems/package' on my Gemfile but it didn't work.
It's a noob question, how can I use RubyGems modules from a Rails app?
You should specify full path to module: Gem::Package::TarWriter and add require 'rubygems/package' to your controller.

Rack Error -- LoadError: cannot load such file

Trying to go through the tekpub rack tutorial but run into this error.
Boot Error
Something went wrong while loading app.ru
LoadError: cannot load such file -- haiku
There is a file named haiku.rb in the same directory as the app I am trying to run but I get the above error while trying to run the program. Here is the code:
class EnvironmentOutput
def initialize(app=nil)
#app = app
end
def call(env)
out = ""
unless(#app.nil?)
response = #app.call(env)[2]
out+=response
end
env.keys.each {|key| out+="<li>#{key}=#{env[key]}</li>"}
["200",{"Content-Type" => "text/html"},[out]]
end
end
require 'haml'
require 'haiku'
class MyApp
def call(env)
poem = Haiku.new.random
template = File.open("views/index.haml").read
engine = Haml::Engine.new(template)
out = engine.render(Object.new, :poem => poem)
["200",{"Content-Type" => "text/html"}, out]
end
end
use EnvironmentOutput
run MyApp.new
I'm sure its a small error as the code is the same as in the tutorial and it works for him...
Thanks
You'll want to read up on ruby load path (either $LOAD_PATH or $:). By default, ruby has a load path which includes wherever your gems are installed, which is why you can do require 'haml' without providing the full path to where your haml gem is located.
When you type require 'haiku', you're basically telling ruby to look for some file called haiku.rb somewhere in it's load path, and the LoadError comes from ruby not finding your haiku.rb file in any of the directories listed in $LOAD_PATH (or $:, which is just shorthand for $LOAD_PATH).
You can solve this in one of (at least) two ways:
change require 'haiku' to require File.dirname(__FILE__) + '/haiku.rb' to explicitly tell ruby what file to load
add the current working directory to your load path: $:.push(File.dirname(__FILE__)). This way you can keep the require 'haiku' part.

Resources