I followed the tutorial on hirb rdoc but unfortunately, my rails console is not working at all.
I've already done sudo gem install hirb
and added hirb to my Gemfile:
gem 'hirb', '~>0.7.0'
Then I launched bundle install
And I get this result :
rails c
Loading development environment (Rails 3.2.11)
> require 'hirb'
=> false
> Hirb.enable
=> true
> Municipality.all
Municipality Load (0.8ms) SELECT "municipalities".* FROM "municipalities" ORDER BY name asc
=> [#<Municipality id: 1, district_id: 6, name: "Ambalamanasy II", created_at: "2013-01-16 12:11:45", updated_at: "2013-01-16 12:11:45">,
...
# doesn't work
Could anyone help?
If your using pry as your rails console... add this in your .pryrc file
require 'hirb'
Hirb.enable
old_print = Pry.config.print
Pry.config.print = proc do |output, value|
Hirb::View.view_or_page_output(value) || old_print.call(output, value)
end
Yoshdog's answer is outdated - it returns an error:
output error: # NoMethodError: undefined method `pager' for nil:NilClass
You can fix this by using the updated code from the docs:
begin
require 'hirb'
rescue LoadError
# Missing goodies, bummer
end
if defined? Hirb
# Slightly dirty hack to fully support in-session Hirb.disable/enable toggling
Hirb::View.instance_eval do
def enable_output_method
#output_method = true
#old_print = Pry.config.print
Pry.config.print = proc do |*args|
Hirb::View.view_or_page_output(args[1]) || #old_print.call(*args)
end
end
def disable_output_method
Pry.config.print = #old_print
#output_method = nil
end
end
Hirb.enable
end
This will also allow you to enable/disable Hirb, which may come in handy.
If you using pry it's works for me
$ pwd
/Users/me/path/rails-app
$ ls -la
-rw-r--r-- 1 ryosuke staff 554 12 26 17:50 .pryrc
and
begin
require 'hirb'
rescue LoadError
# Missing goodies, bummer
end
if defined? Hirb
# Slightly dirty hack to fully support in-session Hirb.disable/enable toggling
Hirb::View.instance_eval do
def enable_output_method
#output_method = true
#old_print = Pry.config.print
Pry.config.print = proc do |*args|
Hirb::View.view_or_page_output(args[1]) || #old_print.call(*args)
end
end
def disable_output_method
Pry.config.print = #old_print
#output_method = nil
end
end
Hirb.enable
end
Related
I have RoR experience, but I'm working on my first gem.
The gem is specifically for use in Rails apps and I want to rely on Rails.env in several cases.
I know requiring Rails in the .gemspec is a bad idea (at least bad practice) because Rails is big and comes with lots of its own dependencies.
But Rails.env isn't exactly an extension I can just pull in.
Rails.env functionality comes from railties which itself relies on active_support, action_dispatch and a bunch of other things:
require "rails/ruby_version_check"
require "pathname"
require "active_support"
require "active_support/core_ext/kernel/reporting"
require "active_support/core_ext/module/delegation"
require "active_support/core_ext/array/extract_options"
require "active_support/core_ext/object/blank"
require "rails/application"
require "rails/version"
require "active_support/railtie"
require "action_dispatch/railtie"
module Rails
extend ActiveSupport::Autoload
extend ActiveSupport::Benchmarkable
autoload :Info
autoload :InfoController
autoload :MailersController
autoload :WelcomeController
class << self
...
# Returns the current Rails environment.
#
# Rails.env # => "development"
# Rails.env.development? # => true
# Rails.env.production? # => false
def env
#_env ||= ActiveSupport::EnvironmentInquirer.new(ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || "development")
end
ActiveSupport::EnvironmentInquirer just gives me the ability to do Rails.env.production? which I don't really care about.
I could also just mimic this behavior by checking for ENV["RAILS_ENV"] and ENV["RACK_ENV"] but if Rails.env is changed, that doesn't change the ENV variables:
3.0.2 :001 > Rails.env
=> "development"
3.0.2 :005 > ENV["RAILS_ENV"]
=> "development"
3.0.2 :006 > ENV["RACK_ENV"]
=> "development"
3.0.2 :007 > Rails.env = 'test'
=> "test"
3.0.2 :008 > Rails.env
=> "test"
3.0.2 :009 > ENV["RAILS_ENV"]
=> "development"
3.0.2 :010 > ENV["RACK_ENV"]
=> "development"
Or I could just instantiate the class as a PORO, but this also seems like bad practice:
module Rails
def self.env
#_env ||=
ENV['RAILS_ENV'] ||
ENV['RACK_ENV'] ||
'development'
end
end
Right now I'm just rescuing when Rails throws a name error:
#environment =
begin
Rails.env
rescue NameError
'development'
end
Is there a standard way to accomplish this or is my rescue the best way to proceed?
You could use defined? to check whether a top-level constant Rails is defined:
def rails_env
::Rails.env if defined?(::Rails)
end
if you want to be extra safe:
def rails_env
::Rails.env if defined?(::Rails) && ::Rails.respond_to?(:env)
end
To enforce a plain string: (instead of a ActiveSupport::EnvironmentInquirer instance)
def rails_env
::Rails.env.to_s if defined?(::Rails) && ::Rails.respond_to?(:env)
end
With the above you could write:
#environment = rails_env || 'development'
I've been using Pry with Rails for a while via the Pry-Rails Gem.
I want to add Hirb and Awesome Print to Pry, so I've added initialisation code to my ~/.pryrc file as described here and here:
# ~/.pryrc
require 'rubygems'
# Hirb for Tables
begin
require 'hirb'
Hirb.enable
old_print = Pry.config.print
Pry.config.print = proc do |output, value|
Hirb::View.view_or_page_output(value) || old_print.call(output, value)
end
rescue LoadError => err
puts "no hirb :("
end
# Awesome Print
begin
require 'awesome_print'
Pry.config.print = proc { |output, value| output.puts value.ai }
rescue LoadError => err
puts "no awesome_print :("
end
However, when I run $rails c Pry can't find either Hirb or Awesome print.
Why is this?
is there a way (a gem, a plugin or something else) in rails 3.2 to know which line of code triggers a database query?
For example in my log I have:
User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 5 LIMIT 1
How can I know the line of code that triggers the query?
Thx...
I've found this solution:
module QueryTrace
def self.enable!
::ActiveRecord::LogSubscriber.send(:include, self)
end
def self.append_features(klass)
super
klass.class_eval do
unless method_defined?(:log_info_without_trace)
alias_method :log_info_without_trace, :sql
alias_method :sql, :log_info_with_trace
end
end
end
def log_info_with_trace(event)
log_info_without_trace(event)
trace_log = Rails.backtrace_cleaner.clean(caller).first
if trace_log && event.payload[:name] != 'SCHEMA'
logger.debug(" \\_ \e[33mCalled from:\e[0m " + trace_log)
end
end
end
In some initializer add QueryTrace.enable!
Rails 5.2+
Add this to your config/environments/test.rb or whatever environment you want to have the lines in. I am testing on rails 5.
ActiveRecord::Base.verbose_query_logs = true
You'll get the file and the line.
Using the active-record-query-trace gem:
In Gemfile:
gem 'active_record_query_trace'
Then bundle, then in config/environments/development.rb:
ActiveRecordQueryTrace.enabled = true
You can monkey patch the BufferedLogger to do what you want. Put this file in your config/initializers path:
require 'active_support/buffered_logger'
class ActiveSupport::BufferedLogger
def add(severity, message = nil, progname = nil, &block)
add_debugging_details(severity)
#log.add(severity, message, progname, &block)
end
private
EXCLUDE_CALLERS = Gem.paths.path.clone << 'script/rails' << RbConfig::CONFIG['rubylibdir'] << __FILE__
def add_debugging_details(severity)
caller_in_app = caller.select do |line|
EXCLUDE_CALLERS.detect { |gem_path| line.starts_with?(gem_path) }.nil?
end
return if caller_in_app.empty?
#log.add(severity, "Your code in \e[1;33m#{caller_in_app.first}\e[0;0m triggered:")
end
end if Rails.env.development?
I am looking at this boot.rb file:
http://github.com/bestbuyremix/BBYIDX/blob/master/config/boot.rb
And after trying to understand it, it is as if I have learned nothing so far.
Can someone detail what is going on here?
I have no idea how someone could even come up with this?
# Don't change this file!
# Configure your app in config/environment.rb and config/environments/*.rb
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
module Rails
class << self
def boot!
unless booted?
preinitialize
pick_boot.run
end
end
def booted?
defined? Rails::Initializer
end
def pick_boot
(vendor_rails? ? VendorBoot : GemBoot).new
end
def vendor_rails?
File.exist?("#{RAILS_ROOT}/vendor/rails")
end
def preinitialize
load(preinitializer_path) if File.exist?(preinitializer_path)
end
def preinitializer_path
"#{RAILS_ROOT}/config/preinitializer.rb"
end
end
class Boot
def run
load_initializer
Rails::Initializer.run(:set_load_path)
end
end
class VendorBoot < Boot
def load_initializer
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
end
end
class GemBoot < Boot
def load_initializer
self.class.load_rubygems
load_rails_gem
require 'initializer'
end
def load_rails_gem
if version = self.class.gem_version
gem 'rails', version
else
gem 'rails'
end
rescue Gem::LoadError => load_error
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
exit 1
end
class << self
def rubygems_version
Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
end
def gem_version
if defined? RAILS_GEM_VERSION
RAILS_GEM_VERSION
elsif ENV.include?('RAILS_GEM_VERSION')
ENV['RAILS_GEM_VERSION']
else
parse_gem_version(read_environment_rb)
end
end
def load_rubygems
require 'rubygems'
min_version = '1.1.1'
unless rubygems_version >= min_version
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
exit 1
end
rescue LoadError
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
exit 1
end
def parse_gem_version(text)
$1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
end
private
def read_environment_rb
File.read("#{RAILS_ROOT}/config/environment.rb")
end
end
end
end
# All that for this:
Rails.boot!
If you are learning Rails, this is not the place to do it. Perhaps you have the thought that in order to use it, you need to understand how the code flows from the beginning? Don't do that. :)
If you're learning rails, use any of the many guides and tutorials to build a basic site.
As for this bit of code, some concepts that it employs involve ruby's iconic class << self Here is a critical read on meta classes: http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/
The Rails.boot! at the bottom leads you to the conclusion "the method boot! is called on the object Rails ... going back up to the top, you see
module Rails
class << self
def boot!
unless booted?
preinitialize
pick_boot.run
end
end
...
Here you can see the magic behind class << self ... it created the boot! method on the module itself. from there you can trace the method call throughout the file, as it checks for the existence of a preinitializer file...
pick_boot returns an object, either VendorBoot or GemBoot depending on the result of vendor_rails? and then call the run method on it.
From there you have some standard class inheritance of the Boot classes, as it sets up the rest of the libraries. Hopefully that gets you started. :)
This is actually very good OO style... small methods and classes that all do a simple task. There's also OO inheritance and several common ruby idioms. All in all, a very good bit of ruby code. :)
Update
Here's a rough estimate of how it would look if coded in a more procedural style:
RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)
unless defined? Rails::Initializer
preinitializer_path = "#{RAILS_ROOT}/config/preinitializer.rb"
load() if File.exist?(preinitializer_path)
if File.exist?("#{RAILS_ROOT}/vendor/rails")
require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
Rails::Initializer.run(:install_gem_spec_stubs)
Rails::Initializer.run(:set_load_path)
else
begin
require 'rubygems'
min_version = '1.1.1'
rubygems_version = Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
unless rubygems_version >= min_version
$stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
exit 1
end
rescue LoadError
$stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
exit 1
end
begin
if defined? RAILS_GEM_VERSION
version = RAILS_GEM_VERSION
elsif ENV.include?('RAILS_GEM_VERSION')
version = ENV['RAILS_GEM_VERSION']
else
version = $1 if (File.read("#{RAILS_ROOT}/config/environment.rb")) =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~=]*\s*[\d.]+)["']/
end
if version
gem 'rails', version
else
gem 'rails'
end
rescue Gem::LoadError => load_error
$stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
exit 1
end
require 'initializer'
end
end
What this is really doing is a bunch of fancy footwork to determine where the rails source code is.
You have the ability to 'freeze' your current rails gem source code into the vendor directory. This is useful when you might have more than one version of rails installed and want to make sure that your application is developed and run with that version only.
This code is checking to see if a version of rails has been frozen into the vendor directory, and if so, use that. If a frozen version isn't available it tries to use the local gems, but first makes sure they meet a minimum version requirement.
For more information on 'freezing' your gems, look at the descriptions of the rake tasks availble to your project with "rake -T".
I recently upgraded my application from Rails version 2.1.2 to version 2.2.2. It was tested in on development and on my staging system. When I moved to production it fails to load all the way through the environment.rb file. (Why, oh why, is it always on production!?!)
Below is my environment.rb file
# Be sure to restart your web server when you modify this file.
# Uncomment below to force Rails into production mode when
# you don't control web/app server and can't set it the proper way
# ENV['RAILS_ENV'] ||= 'production'
# Specifies gem version of Rails to use when vendor/rails is not present
#RAILS_GEM_VERSION = '2.1.0' unless defined? RAILS_GEM_VERSION
RAILS_GEM_VERSION = '2.2.2' unless defined? RAILS_GEM_VERSION
puts "loading rails..."
# Bootstrap the Rails environment, frameworks, and default configuration
require File.join(File.dirname(__FILE__), 'boot')
puts "require boot file"
require 'socket'
puts "require socket"
Rails::Initializer.run do |config|
puts "inside config section"
# Settings in config/environments/* take precedence over those specified here
# Skip frameworks you're not going to use (only works if using vendor/rails)
# config.frameworks -= [ :action_web_service, :action_mailer ]
# Only load the plugins named here, by default all plugins in vendor/plugins are loaded
# config.plugins = %W( exception_notification ssl_requirement )
# Add additional load paths for your own custom dirs
# config.load_paths += %W( #{RAILS_ROOT}/extras )
# Force all environments to use the same logger level
# (by default production uses :info, the others :debug)
# config.log_level = :debug
# Use the database for sessions instead of the file system
# (create the session table with 'rake db:sessions:create')
config.action_controller.session_store = :active_record_store
puts "setting session store type"
# Use SQL instead of Active Record's schema dumper when creating the test database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
# Activate observers that should always be running
# config.active_record.observers = :cacher, :garbage_collector
# Make Active Record use UTC-base instead of local time
# config.active_record.default_timezone = :utc
#config.gem "will_paginate", :source => "http://gems.rubyforge.org"
# Action Mailer configuration - from page 567-568 of the Agile Development book
# config.action_mailer.delivery_method = :smtp
#
config.action_mailer.smtp_settings = {
:address => "smtp.redacted.com",
:port => "25",
:domain => "redacted.com"
}
puts "setting smtp settings"
# See Rails::Configuration for more options
end
puts "outside config section ... before inflectors"
# Add new inflection rules using the following format
# (all these examples are active by default):
ActiveSupport::Inflector.inflections do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
inflect.uncountable %w( sid fcc )
end
puts "after inflectors"
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
# Mime::Type.register "application/x-mobile", :mobile
# Include your application configuration below
require 'will_paginate'
puts "require will paginate"
# insert at top of ActiveRecord::Base.rb
# Indicates whether field names should be lowercased for legacy databse fields.
# If true, the field Product_Name will be +product_name+. If false, it will remain +Product_Name+.
# This is false, by default.
#cattr_accessor :downcase_legacy_field_names, :instance_writer => false
###downcase_legacy_field_names = false
# insert into column_methods_hash of ActiveRecord::Base.rb
# attr_final = downcase_legacy_field_names ? attr.to_s.downcase : attr
puts "here comes the monkey patch"
module ActiveRecord
class Base
# Indicates whether field names should be lowercased for legacy databse fields.
# If true, the field Product_Name will be +product_name+. If false, it will remain +Product_Name+.
# This is false, by default.
cattr_accessor :downcase_legacy_field_names, :instance_writer => false
##downcase_legacy_field_names = false
end
end
puts "monkey patch part 2"
# set all accessor methods to lowercase (underscore)
# add set_columns_to_lower to each model that needs it
class << ActiveRecord::Base
# Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key
# and true as the value. This makes it possible to do O(1) lookups in respond_to? to check if a given method for attribute
# is available.
def column_methods_hash #:nodoc:
#dynamic_methods_hash ||= column_names.inject(Hash.new(false)) do |methods, attr|
attr_final = downcase_legacy_field_names ? attr.to_s.downcase : attr
attr_name = attr_final
methods[attr_final.to_sym] = attr_name
methods["#{attr_final}=".to_sym] = attr_name
methods["#{attr_final}?".to_sym] = attr_name
methods["#{attr_final}_before_type_cast".to_sym] = attr_name
methods
end
end
# adapted from: http://wiki.rubyonrails.org/rails/pages/HowToUseLegacySchemas
def downcase_legacy_field_methods
column_names.each do |name|
next if name == primary_key
a = name.to_s.underscore
define_method(a.to_sym) do
read_attribute(name)
end
define_method("#{a}=".to_sym) do |value|
write_attribute(name, value)
end
define_method("#{a}?".to_sym) do
self.send("#{name}?".to_sym)
end
end
end
end
puts "monkey patch part 3"
ActiveRecord::Base.downcase_legacy_field_names = true
puts "monkey patch part 4"
module ActiveSupport
module Inflector
def textize(str)
str.to_s.gsub(/'/, '').downcase
#gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
#gsub(/([a-z\d])([A-Z])/,'\1_\2').
#tr("-", "_").
#downcase
end
end
end
puts "monkey patch part 5"
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module String #:nodoc:
module Inflections
def textize
Inflector.textize(self)
end
end
end
end
end
###################################################################
### Code moved to the specific environment files.
### This way the schema gets reloaded on a deploy
###################################################################
## Establishes connections for the root classes of the various databases that
## must be connected to for SUI.
puts "load the database if we are in test mode"
if RAILS_ENV == "test" then
puts "if I see this and I'm not loading test, we have a problem"
Ird.load_database
end
puts "setting up the execption notifier"
ExceptionNotifier.exception_recipients = %w(me#redacted.com)
if RAILS_ENV == "Production"
ExceptionNotifier.sender_address = %("SUI Service" <service#redacted.com>)
ExceptionNotifier.email_prefix = "[SUI ERROR] "
else
ExceptionNotifier.sender_address = %("SUI #{RAILS_ENV.to_s.humanize} Service" <service#redacted.com>)
ExceptionNotifier.email_prefix = "[#{RAILS_ENV.to_s.humanize}: SUI ERROR] "
end
puts "local_ip function"
def local_ip
orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
UDPSocket.open do |s|
s.connect '64.233.187.99', 1
s.addr.last
end
ensure
Socket.do_not_reverse_lookup = orig
end
puts "I am located at:#{local_ip}:"
puts "environment.rb is loaded"
If I set the rails gem to be used to version 2.1.2 everything loads and all the puts statements print as expected. When I change the gem version to 2.2.2 the last statement that I see printed is "setting smtp settings".
When I move the Rails::Initializer do |config| section to the bottom it fails in ways worse than where it is right now.
The ruby version that is loaded on the system is Ruby 1.8.6 patchlevel 111. It is running on RHEL5-64bit.
I'm stumped. Ideas? Suggestions?
Did you run rake rails:update?
Also, you might want to move most of the code into config/initializers/[anything].rb, allthough I hardly think that itself will solve your problems.