I'm trying to prettify an Ruby object using awesome_print so I can place this string inside an email and send it off. So in terms of code, (I know this is wrong), but here's what I'm trying to achieve:
my_str = (ap error.object).to_str
# Do something with my_str, like stick it in a <pre> tag inside an html email.
How do I convert the output from ap to string? Reason I'm asking is as I noticed, ap seems to only return the object.
It doesn't seem to be documented in the README.md, but if you look at the Kernel modifications the library makes here: https://github.com/michaeldv/awesome_print/blob/master/lib/awesome_print/core_ext/kernel.rb
You can see that in addition to the ap method, the awesome_print gem also adds an ai method to all objects.
1.9.3p392 :001 > require 'awesome_print'
=> true
1.9.3p392 :002 > test = {a: "b"}
=> {:a=>"b"}
1.9.3p392 :003 > ap test
{
:a => "b"
}
1.9.3p392 :006 > test.ai
=> "{\n :a\e[0;37m => \e[0m\e[0;33m\"b\"\e[0m\n}"
1.9.3p392 :007 > test.ai(html:true)
=> "<pre>{\n <pre>:a</pre><kbd style=\"color:slategray\"> => </kbd><pre><kbd style=\"color:brown\">"b"</kbd></pre>\n}</pre>"
That said, the output formatting might not be that useful (the html version adds a ton of whitespace, and the non-html version has the weird terminal coloring characters), and being an undocumented feature, it's liable to break without warning in a minor version update.
The other thing worth noting in the kernel.rb above is that ap and ai have aliases: awesome_print and awesome_inspect.
awesomeprint is meant for printing ASCII colors and stuff, not HTML. What I'd use is pygments gem:
# gem install pygments.rb
require 'pygments'
str = <<EOT
# This is an awesome comment on my rb script
a = 2
puts a
hsh = {asdf: 1, qwer: 2, uiop: 3}
EOT
Pygments.highlight str
https://github.com/tmm1/pygments.rb
Related
I have a YAML config file where I want to include specific ruby class/module constants instead of the actual value.
For example, instead of putting "loglevel: 0" in the config file, I want "loglevel: Logger::DEBUG".
Is there a way to have YAML decode or resolve a class or module constant like Logger::DEBUG?
This is what I've been playing with, but looking at the psych ruby code, I don't see anything that might support this.
config.yml
loglevel: !ruby/class:fixnum Logger::DEBUG
In irb
irb> require 'logger'
irb> config = YAML.load_file('config.yml')
config['loglevel'] contains "Logger::DEBUG" as a String instead of the actual value.
I can do an eval on it like so:
irb> p eval config['loglevel']
0
==> 0
I'm just wondering if there's a way to have YAML eval it? I'm okay with doing it in my code after doing a YAML load, but I wanted to make sure I left no stone unturned in my, what has turned into a lengthy, quest ;-).
Not sure of a YAML way, but best not to use eval...
In Ruby 2+
Object.const_get 'Logger::DEBUG'
Or the old school
def const_lookup const_name
const_name.split('::').inject(Object) do |rec, name|
rec.const_get(name)
end
end
const_lookup 'Logger::DEBUG'
Looks like you can do it for classes/modules but not their constants
2.0.0-p247 :046 > YAML.load("!ruby/class 'String'")
=> String
2.0.0-p247 :047 > YAML.load("!ruby/class 'String'").class
=> Class
2.0.0-p247 :065 > YAML.load("!ruby/class 'Logger'")
=> Logger
I'm learning Ruby, and went into irb to test something out with the Date class. In short, I did the following:
$ irb
irb(main):001:0> Date.new
=> #<Date:0x007f983103ee60>
irb(main):002:0> Date.constants
=> []
irb(main):003:0> help Date
=> nil
irb(main):004:0> Date.constants
=> [:MONTHNAMES, :ABBR_MONTHNAMES, :DAYNAMES, :ABBR_DAYNAMES, :ITALY, :ENGLAND, :JULIAN, :GREGORIAN, :Infinity]
irb(main):005:0>
I'm so confused by this. Questions:
Why would reading help documentation cause the output of Date.constants to change?
Presumably help is loading/initializing something. What is it? And why did Date.new work?
Is whatever this is something I need to worry about when writing .rb files?
This is tough to Google for. I'm on ruby 2.1.2 and irb 0.9.6.
The most likely cause of the addition of the Date constants after running help Date is that somewhere in the execution of the command, require 'date' (or require 'time') is called:
2.1.0 :001 > Date.constants
=> []
2.1.0 :002 > require 'date'
=> true
2.1.0 :003 > Date.constants
=> [:MONTHNAMES, :ABBR_MONTHNAMES, :DAYNAMES, :ABBR_DAYNAMES, :ITALY, :ENGLAND, :JULIAN, :GREGORIAN, :Infinity]
As for Date.new, it works because Date comes with a default constructor.
I doubt this will ever be problematic for you.
I got an error JSON::GeneratorError: source sequence is illegal/malformed utf-8 when trying to convert a hash into json string. I am wondering if this has anything to do with encoding, and how can I make to_json just treat \xAE as it is?
$ irb
2.0.0-p247 :001 > require 'json'
=> true
2.0.0-p247 :002 > a = {"description"=> "iPhone\xAE"}
=> {"description"=>"iPhone\xAE"}
2.0.0-p247 :003 > a.to_json
JSON::GeneratorError: source sequence is illegal/malformed utf-8
from (irb):3:in `to_json'
from (irb):3
from /Users/cchen21/.rvm/rubies/ruby-2.0.0-p247/bin/irb:16:in `<main>'
\xAE is not a valid character in UTF-8, you have to use \u00AE instead:
"iPhone\u00AE"
#=> "iPhone®"
Or convert it accordingly:
"iPhone\xAE".force_encoding("ISO-8859-1").encode("UTF-8")
#=> "iPhone®"
Every string in Ruby has a underlaying encoding. Depending on your LANG and LC_ALL environment variables, the interactive shell might be executing and interpreting your strings in a given encoding.
$ irb
1.9.3p392 :008 > __ENCODING__
=> #<Encoding:UTF-8>
(ignore that I’m using Ruby 1.9 instead of 2.0, the ideas are still the same).
__ENCODING__ returns the current source encoding. Yours will probably also say UTF-8.
When you create literal strings and use byte escapes (the \xAE) in your code, Ruby is trying to interpret that according to the string encoding:
1.9.3p392 :003 > a = {"description" => "iPhone\xAE"}
=> {"description"=>"iPhone\xAE"}
1.9.3p392 :004 > a["description"].encoding
=> #<Encoding:UTF-8>
So, the byte \xAE at the end of your literal string will be tried to be treated as a UTF-8 stream byte, but it is invalid. See what happens when I try to print it:
1.9.3-p392 :001 > puts "iPhone\xAE"
iPhone�
=> nil
You either need to provide the registered mark character in a valid UTF-8 encoding (either using the real character, or providing the two UTF-8 bytes):
1.9.3-p392 :002 > a = {"description1" => "iPhone®", "description2" => "iPhone\xc2\xae"}
=> {"description1"=>"iPhone®", "description2"=>"iPhone®"}
1.9.3-p392 :005 > a.to_json
=> "{\"description1\":\"iPhone®\",\"description2\":\"iPhone®\"}"
Or, if your input is ISO-8859-1 (Latin 1) and you know it for sure, you can tell Ruby to interpret your string as another encoding:
1.9.3-p392 :006 > a = {"description1" => "iPhone\xAE".force_encoding('ISO-8859-1') }
=> {"description1"=>"iPhone\xAE"}
1.9.3-p392 :007 > a.to_json
=> "{\"description1\":\"iPhone®\"}"
Hope it helps.
Given a string with hash tags, how do I arrive to a new string with all the hash tags wrapped with html anchor tags?
I have no idea how to do it.
use twitter-text gem to extract hashes and link them
https://github.com/twitter/twitter-text-rb
auto_link_hashtags method is what your ar looking for they have mnay more have a look
Example from rails console after including the gem in project
1.9.3p194 :004 > include Twitter::Autolink
=> Object
1.9.3p194 :007 > auto_link_hashtags " #goohh" , :hashtag_url_base => "http://xyzzcac.com/hash/"
#=> " <a class=\"tweet-url hashtag\" href=\"http://xyzzcac.com/hash/goohh\" rel=\"nofollow\" title=\"#goohh\">#goohh</a>"
I am using JSON implementation for Ruby in my rails project to parse the JSON string sent by ajax, but I found that although the json string is in UTF-8, the result coming out is in ASCII-8BIT by default, see below
jruby-1.6.7 :068 > json_text = '["に到着を待っている"]'
=> "[\"に到着を待っている\"]"
jruby-1.6.7 :069 > json_text.encoding
=> #<Encoding:UTF-8>
jruby-1.6.7 :070 > json_parsed = JSON.parse(json_text)
=> ["\u00E3\u0081\u00AB\u00E5\u0088\u00B0\u00E7\u009D\u0080\u00E3\u0082\u0092\u00E5\u00BE\u0085\u00E3\u0081\u00A3\u00E3\u0081\u00A6\u00E3\u0081\u0084\u00E3\u0082\u008B"]
jruby-1.6.7 :071 > json_parsed.first.encoding
=> #<Encoding:ASCII-8BIT>
I don't want it being escaped, I would like to have a UTF-8 result. Is there a way to set that? I check the documentation of the JSON project, finding not encoding options for the method JSON.parse. Maybe I missed something, how could I do that?
UPDATE:
as notified by #fl00r, this example is working fine in MRI, but not in JRUBY
This looks like a bug, as this actually works when using the pure version:
jruby-1.6-head :001 > require 'json/pure'
=> true
jruby-1.6-head :002 > json_text = '["に到着を待っている"]'
=> "[\"に到着を待っている\"]"
jruby-1.6-head :003 > json_parsed = JSON.parse(json_text)
=> ["に到着を待っている"]
jruby-1.6-head :004 > json_parsed.first.encoding
=> #<Encoding:UTF-8>
jruby-1.6-head :005 >
Edit: Just saw you opened a ticket for this...
Edit 2: This actually seems to have already been fixed by this commit. To install latest code from json:
$ git clone https://github.com/flori/json.git
$ cd json
$ rake jruby_gem
$ jruby -S gem install pkg/json-1.6.6-java.gem