I'm trying to get Syntax Highlighting with Redcarpet working
My appliaction_helper.rb:
module ApplicationHelper
def markdown(text)
render_options = {
# will remove from the output HTML tags inputted by user
filter_html: true,
# will insert <br /> tags in paragraphs where are newlines
hard_wrap: true,
# hash for extra link options, for example 'nofollow'
link_attributes: { rel: 'nofollow' },
# Prettify
prettify: true
}
renderer = Redcarpet::Render::HTML.new(render_options)
extensions = {
#will parse links without need of enclosing them
autolink: true,
# blocks delimited with 3 ` or ~ will be considered as code block.
# No need to indent. You can provide language name too.
# ```ruby
# block of code
# ```
fenced_code_blocks: true,
# will ignore standard require for empty lines surrounding HTML blocks
lax_spacing: true,
# will not generate emphasis inside of words, for example no_emph_no
no_intra_emphasis: true,
# will parse strikethrough from ~~, for example: ~~bad~~
strikethrough: true,
# will parse superscript after ^, you can wrap superscript in ()
superscript: true
# will require a space after # in defining headers
# space_after_headers: true
}
Redcarpet::Markdown.new(renderer, extensions).render(text).html_safe
end
end
Although the output is displayed in a codeblock (redcarpet):
I can't find the Syntax Highlighting.
I just got into Redcarpet, someone know a solution for this?
Ok i found -> Markdown and code syntax highlighting in Ruby on Rails (using RedCarpet and CodeRay) which pretty much worked (together with some custom css for Coderay).
Gemfile:
gem 'redcarpet', github: 'vmg/redcarpet'
gem 'coderay'
Application_helper.rb
class CodeRayify < Redcarpet::Render::HTML
def block_code(code, language)
CodeRay.scan(code, language).div
end
end
def markdown(text)
coderayified = CodeRayify.new(:filter_html => true,
:hard_wrap => true)
options = {
:fenced_code_blocks => true,
:no_intra_emphasis => true,
:autolink => true,
:strikethrough => true,
:lax_html_blocks => true,
:superscript => true
}
markdown_to_html = Redcarpet::Markdown.new(coderayified, options)
markdown_to_html.render(text).html_safe
end
Here is a quick way to do it with Rouge:
require 'redcarpet'
require 'rouge'
require 'rouge/plugins/redcarpet'
class HTML < Redcarpet::Render::HTML
include Rouge::Plugins::Redcarpet # yep, that's it.
end
Of course this requires rouge to be in your Gemfile.
I don't think Redcarpet can do that. In my project I followed the Railscasts episode about Redcarpet which also tackles syntax highlighting. It makes use of Pygments and Albino.
Link to the ASCIIcast version is here.
I'm trying to determine whether a remote url is an image. Most url's have .jpg, .png etc...but some images, like google images, have no extension...i.e.
https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSbK2NSUILnFozlX-oCWQ0r2PS2gHPPF7c8XaxGuJFGe83KGJkhFtlLXU_u
I've tried using FastImage to determine whether a url is an image. It works when any URL is fed into it...
How could I ensure that remote urls use FastImage and uploaded files use the whitelist? Here is what have in my uploader. Avatar_remote_url isn't recognized...what do I do in the uploader to just test remote urls and not regular files.
def extension_white_list
if defined? avatar_remote_url && !FastImage.type(CGI::unescape(avatar_remote_url)).nil?
# ok to process
else # regular uploaded file should detect the following extensions
%w(jpg jpeg gif png)
end
end
if all you have to work with is a url like that you can send a HEAD request to the server to obtain the content type for the image. From that you can obtain the extension
require 'net/http'
require 'mime/types'
def get_extension(url)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Head.new(uri.request_uri)
response = http.request(request)
content_type = response['Content-Type']
MIME::Types[content_type].first.extensions.first
end
I'm working with the code you provided and some of the code provided in the CarrierWave Wiki for validating remote URLs.
You can create a new validator in lib/remote_image_validator.rb.
require 'fastimage'
class RemoteImageValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
raise(ArgumentError, "A regular expression must be supplied as the :format option of the options hash") unless options[:format].nil? || options[:format].is_a?(Regexp)
configuration = { :message => "is invalid or not responding", :format => URI::regexp(%w(http https)) }
configuration.update(options)
if value =~ configuration[:format]
begin
if FastImage.type(CGI::unescape(avatar_remote_url))
true
else
object.errors.add(attribute, configuration[:message]) and false
end
rescue
object.errors.add(attribute, configuration[:message]) and false
end
else
object.errors.add(attribute, configuration[:message]) and false
end
end
end
Then in your model
class User < ActiveRecord::Base
validates :avatar_remote_url,
:remote_image => {
:format => /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)/ix,
:unless => remote_avatar_url.blank?
}
end
I was having a similar issue where creating the different versions from the original was failing because ImageMagick could not figure out the correct encoder to use due to the missing extension. Here is a monkey-patch I applied in Rails that fixed my problem:
module CarrierWave
module Uploader
module Download
class RemoteFile
def original_filename
value = File.basename(file.base_uri.path)
mime_type = Mime::Type.lookup(file.content_type)
unless File.extname(value).present? || mime_type.blank?
value = "#{value}.#{mime_type.symbol}"
end
value
end
end
end
end
end
I believe this will address the problem you are having as well since it ensures the existence of a file extension when the content type is set appropriately.
UPDATE:
The master branch of carrierwave has a different solution to this problem that uses the Content-Disposition header to figure out the filename. Here is the relevant pull request on github.
I'm trying to integrate a rails 3 app with jasper following this wiki:
http://wiki.rubyonrails.org/rails/pages/HowtoIntegrateJasperReports
But it seems that a lot of information isn't updated so it's been very hard to make it work by myself. I've also read a topic at ruby-forum: http://www.ruby-forum.com/topic/139453
with some details explained but still couldn't make it work.
My first problem is related with the render_to_string method:
When the controller method runs I receive a "Template is missing" error:
this is the method:
def report
#customers = Customer.all
send_doc(render_to_string(:template => report_customers_path, :layout => false), '/pdfs', 'report.jasper', "customers", 'pdf')
end
Although this seems simple I'm not understanding why is this happening. Doesn't render_to_string with layout => false suposed to get me the string result of that action?
I also tried :action instead of :template, but it does the same.
If anybody with some expertise with this integration could help...
Thanks in advance,
André
We actually use jasperreports to create reports, and recently upgraded to Rails 3.0. To create the xml, we use xml.erb templates. Jasper reports runs in a separate glassfish server Here's the general idea:
url = URI.parse(my_url_string)
dataxml = render_to_string(:template => my_template_name).gsub(/\n/, '')
params = {'type' => 'pdf', 'compiledTemplateURI' => my_jasper_file, 'data' => dataxml }
request = Net::HTTP::POST.new(url.request_uri)
request.set_form_data(params)
obj = Net::HTTP.new(url.host, url.port)
obj.read_timeout = my_timeout_setting
response = obj.start { |http| http.request(request) }
case response
when Net::HTTPOK
send_data(response.body, :filename => my_chosen_filename, :type => "application/pdf", :disposition => "inline")
else
raise "failed to generate report"
end
I don't know anything about jasper, but it sounds like you want to do two things: render a PDF template and then send the raw output back w/ a PDF mime type:
pdf_contents = render_to_string(:template => 'users/report')
send_data(pdf_contents, :file_name => 'report.pdf', :type => 'application/pdf')
You're passing in the external URL as the template path, but that's probably wrong if you're getting errors about the template path. Fix the template path first.
Use savon to interact with jaserserver in rails3.
Here is an example:
require 'logger'
require 'savon'
logger = Logger.new(STDOUT)
logger.info "Test jasper via Savon-SOAP"
#client = Savon::Client.new {
wsdl.document = "http://localhost:8080/jasperserver/services/repository?wsdl"
http.auth.basic "jasperadmin", "jasperadmin"
}
logger.info "runReport method"
begin
result = #client.request :run_report do
soap.body = "<requestXmlString>
<![CDATA[
<request operationName='runReport' >
<argument name='RUN_OUTPUT_FORMAT'>PDF</argument>
<resourceDescriptor name='' wsType='' uriString='/reports/samples/AllAccounts' isNew='false'>
<label></label>
</resourceDescriptor>
</request>
]]>
</requestXmlString>"
end
send_data result.http.raw_body, :type => 'application/pdf', :filename => 'report.pdf', :disposition => 'attachment'
rescue Exception => e
logger.error "SOAP Error: #{e}"
end
Try to change the render_to_string() code to this:
#customers.to_xml
I would like my JSON output in Ruby on Rails to be "pretty" or nicely formatted.
Right now, I call to_json and my JSON is all on one line. At times this can be difficult to see if there is a problem in the JSON output stream.
Is there way to configure to make my JSON "pretty" or nicely formatted in Rails?
Use the pretty_generate() function, built into later versions of JSON. For example:
require 'json'
my_object = { :array => [1, 2, 3, { :sample => "hash"} ], :foo => "bar" }
puts JSON.pretty_generate(my_object)
Which gets you:
{
"array": [
1,
2,
3,
{
"sample": "hash"
}
],
"foo": "bar"
}
The <pre> tag in HTML, used with JSON.pretty_generate, will render the JSON pretty in your view. I was so happy when my illustrious boss showed me this:
<% if #data.present? %>
<pre><%= JSON.pretty_generate(#data) %></pre>
<% end %>
Thanks to Rack Middleware and Rails 3 you can output pretty JSON for every request without changing any controller of your app. I have written such middleware snippet and I get nicely printed JSON in browser and curl output.
class PrettyJsonResponse
def initialize(app)
#app = app
end
def call(env)
status, headers, response = #app.call(env)
if headers["Content-Type"] =~ /^application\/json/
obj = JSON.parse(response.body)
pretty_str = JSON.pretty_unparse(obj)
response = [pretty_str]
headers["Content-Length"] = pretty_str.bytesize.to_s
end
[status, headers, response]
end
end
The above code should be placed in app/middleware/pretty_json_response.rb of your Rails project.
And the final step is to register the middleware in config/environments/development.rb:
config.middleware.use PrettyJsonResponse
I don't recommend to use it in production.rb. The JSON reparsing may degrade response time and throughput of your production app. Eventually extra logic such as 'X-Pretty-Json: true' header may be introduced to trigger formatting for manual curl requests on demand.
(Tested with Rails 3.2.8-5.0.0, Ruby 1.9.3-2.2.0, Linux)
If you want to:
Prettify all outgoing JSON responses from your app automatically.
Avoid polluting Object#to_json/#as_json
Avoid parsing/re-rendering JSON using middleware (YUCK!)
Do it the RAILS WAY!
Then ... replace the ActionController::Renderer for JSON! Just add the following code to your ApplicationController:
ActionController::Renderers.add :json do |json, options|
unless json.kind_of?(String)
json = json.as_json(options) if json.respond_to?(:as_json)
json = JSON.pretty_generate(json, options)
end
if options[:callback].present?
self.content_type ||= Mime::JS
"#{options[:callback]}(#{json})"
else
self.content_type ||= Mime::JSON
json
end
end
Check out Awesome Print. Parse the JSON string into a Ruby Hash, then display it with ap like so:
require "awesome_print"
require "json"
json = '{"holy": ["nested", "json"], "batman!": {"a": 1, "b": 2}}'
ap(JSON.parse(json))
With the above, you'll see:
{
"holy" => [
[0] "nested",
[1] "json"
],
"batman!" => {
"a" => 1,
"b" => 2
}
}
Awesome Print will also add some color that Stack Overflow won't show you.
If you find that the pretty_generate option built into Ruby's JSON library is not "pretty" enough, I recommend my own NeatJSON gem for your formatting.
To use it:
gem install neatjson
and then use
JSON.neat_generate
instead of
JSON.pretty_generate
Like Ruby's pp it will keep objects and arrays on one line when they fit, but wrap to multiple as needed. For example:
{
"navigation.createroute.poi":[
{"text":"Lay in a course to the Hilton","params":{"poi":"Hilton"}},
{"text":"Take me to the airport","params":{"poi":"airport"}},
{"text":"Let's go to IHOP","params":{"poi":"IHOP"}},
{"text":"Show me how to get to The Med","params":{"poi":"The Med"}},
{"text":"Create a route to Arby's","params":{"poi":"Arby's"}},
{
"text":"Go to the Hilton by the Airport",
"params":{"poi":"Hilton","location":"Airport"}
},
{
"text":"Take me to the Fry's in Fresno",
"params":{"poi":"Fry's","location":"Fresno"}
}
],
"navigation.eta":[
{"text":"When will we get there?"},
{"text":"When will I arrive?"},
{"text":"What time will I get to the destination?"},
{"text":"What time will I reach the destination?"},
{"text":"What time will it be when I arrive?"}
]
}
It also supports a variety of formatting options to further customize your output. For example, how many spaces before/after colons? Before/after commas? Inside the brackets of arrays and objects? Do you want to sort the keys of your object? Do you want the colons to all be lined up?
Dumping an ActiveRecord object to JSON (in the Rails console):
pp User.first.as_json
# => {
"id" => 1,
"first_name" => "Polar",
"last_name" => "Bear"
}
Using <pre> HTML code and pretty_generate is good trick:
<%
require 'json'
hash = JSON[{hey: "test", num: [{one: 1, two: 2, threes: [{three: 3, tthree: 33}]}]}.to_json]
%>
<pre>
<%= JSON.pretty_generate(hash) %>
</pre>
Here is a middleware solution modified from this excellent answer by #gertas. This solution is not Rails specific--it should work with any Rack application.
The middleware technique used here, using #each, is explained at ASCIIcasts 151: Rack Middleware by Eifion Bedford.
This code goes in app/middleware/pretty_json_response.rb:
class PrettyJsonResponse
def initialize(app)
#app = app
end
def call(env)
#status, #headers, #response = #app.call(env)
[#status, #headers, self]
end
def each(&block)
#response.each do |body|
if #headers["Content-Type"] =~ /^application\/json/
body = pretty_print(body)
end
block.call(body)
end
end
private
def pretty_print(json)
obj = JSON.parse(json)
JSON.pretty_unparse(obj)
end
end
To turn it on, add this to config/environments/test.rb and config/environments/development.rb:
config.middleware.use "PrettyJsonResponse"
As #gertas warns in his version of this solution, avoid using it in production. It's somewhat slow.
Tested with Rails 4.1.6.
#At Controller
def branch
#data = Model.all
render json: JSON.pretty_generate(#data.as_json)
end
If you're looking to quickly implement this in a Rails controller action to send a JSON response:
def index
my_json = '{ "key": "value" }'
render json: JSON.pretty_generate( JSON.parse my_json )
end
Here's my solution which I derived from other posts during my own search.
This allows you to send the pp and jj output to a file as needed.
require "pp"
require "json"
class File
def pp(*objs)
objs.each {|obj|
PP.pp(obj, self)
}
objs.size <= 1 ? objs.first : objs
end
def jj(*objs)
objs.each {|obj|
obj = JSON.parse(obj.to_json)
self.puts JSON.pretty_generate(obj)
}
objs.size <= 1 ? objs.first : objs
end
end
test_object = { :name => { first: "Christopher", last: "Mullins" }, :grades => [ "English" => "B+", "Algebra" => "A+" ] }
test_json_object = JSON.parse(test_object.to_json)
File.open("log/object_dump.txt", "w") do |file|
file.pp(test_object)
end
File.open("log/json_dump.txt", "w") do |file|
file.jj(test_json_object)
end
I have used the gem CodeRay and it works pretty well. The format includes colors and it recognises a lot of different formats.
I have used it on a gem that can be used for debugging rails APIs and it works pretty well.
By the way, the gem is named 'api_explorer' (http://www.github.com/toptierlabs/api_explorer)
if you want to handle active_record object, puts is enough.
for example:
without puts
2.6.0 (main):0 > User.first.to_json
User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> "{\"id\":1,\"admin\":true,\"email\":\"admin#gmail.com\",\"password_digest\":\"$2a$10$TQy3P7NT8KrdCzliNUsZzuhmo40LGKoth2hwD3OI.kD0lYiIEwB1y\",\"created_at\":\"2021-07-20T08:34:19.350Z\",\"updated_at\":\"2021-07-20T08:34:19.350Z\",\"name\":\"Arden Stark\"}"
with puts
2.6.0 (main):0 > puts User.first.to_json
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
{"id":1,"admin":true,"email":"admin#gmail.com","password_digest":"$2a$10$TQy3P7NT8KrdCzliNUsZzuhmo40LGKoth2hwD3OI.kD0lYiIEwB1y","created_at":"2021-07-20T08:34:19.350Z","updated_at":"2021-07-20T08:34:19.350Z","name":"Arden Stark"}
=> nil
if you are handle the json data, JSON.pretty_generate is a good alternative
Example:
obj = {foo: [:bar, :baz], bat: {bam: 0, bad: 1}}
json = JSON.pretty_generate(obj)
puts json
Output:
{
"foo": [
"bar",
"baz"
],
"bat": {
"bam": 0,
"bad": 1
}
}
if it's in the ROR project, I always prefer to use gem pry-rails to format my codes in the rails console rather than awesome_print which is too verbose.
Example of pry-rails:
it also has syntax highlight.
# example of use:
a_hash = {user_info: {type: "query_service", e_mail: "my#email.com", phone: "+79876543322"}, cars_makers: ["bmw", "mitsubishi"], car_models: [bmw: {model: "1er", year_mfc: 2006}, mitsubishi: {model: "pajero", year_mfc: 1997}]}
pretty_html = a_hash.pretty_html
# include this module to your libs:
module MyPrettyPrint
def pretty_html indent = 0
result = ""
if self.class == Hash
self.each do |key, value|
result += "#{key}: #{[Array, Hash].include?(value.class) ? value.pretty_html(indent+1) : value}"
end
elsif self.class == Array
result = "[#{self.join(', ')}]"
end
"#{result}"
end
end
class Hash
include MyPrettyPrint
end
class Array
include MyPrettyPrint
end
Simplest example, I could think of:
my_json = '{ "name":"John", "age":30, "car":null }'
puts JSON.pretty_generate(JSON.parse(my_json))
Rails console example:
core dev 1555:0> my_json = '{ "name":"John", "age":30, "car":null }'
=> "{ \"name\":\"John\", \"age\":30, \"car\":null }"
core dev 1556:0> puts JSON.pretty_generate(JSON.parse(my_json))
{
"name": "John",
"age": 30,
"car": null
}
=> nil
Pretty print variant (Rails):
my_obj = {
'array' => [1, 2, 3, { "sample" => "hash"}, 44455, 677778, nil ],
foo: "bar", rrr: {"pid": 63, "state with nil and \"nil\"": false},
wwww: 'w' * 74
}
require 'pp'
puts my_obj.as_json.pretty_inspect.
gsub('=>', ': ').
gsub(/"(?:[^"\\]|\\.)*"|\bnil\b/) {|m| m == 'nil' ? 'null' : m }.
gsub(/\s+$/, "")
Result:
{"array": [1, 2, 3, {"sample": "hash"}, 44455, 677778, null],
"foo": "bar",
"rrr": {"pid": 63, "state with nil and \"nil\"": false},
"wwww":
"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"}
If you are using RABL you can configure it as described here to use JSON.pretty_generate:
class PrettyJson
def self.dump(object)
JSON.pretty_generate(object, {:indent => " "})
end
end
Rabl.configure do |config|
...
config.json_engine = PrettyJson if Rails.env.development?
...
end
A problem with using JSON.pretty_generate is that JSON schema validators will no longer be happy with your datetime strings. You can fix those in your config/initializers/rabl_config.rb with:
ActiveSupport::TimeWithZone.class_eval do
alias_method :orig_to_s, :to_s
def to_s(format = :default)
format == :default ? iso8601 : orig_to_s(format)
end
end
I use the following as I find the headers, status and JSON output useful as
a set. The call routine is broken out on recommendation from a railscasts presentation at: http://railscasts.com/episodes/151-rack-middleware?autoplay=true
class LogJson
def initialize(app)
#app = app
end
def call(env)
dup._call(env)
end
def _call(env)
#status, #headers, #response = #app.call(env)
[#status, #headers, self]
end
def each(&block)
if #headers["Content-Type"] =~ /^application\/json/
obj = JSON.parse(#response.body)
pretty_str = JSON.pretty_unparse(obj)
#headers["Content-Length"] = Rack::Utils.bytesize(pretty_str).to_s
Rails.logger.info ("HTTP Headers: #{ #headers } ")
Rails.logger.info ("HTTP Status: #{ #status } ")
Rails.logger.info ("JSON Response: #{ pretty_str} ")
end
#response.each(&block)
end
end
I had a JSON object in the rails console, and wanted to display it nicely in the console (as opposed to displaying like a massive concatenated string), it was as simple as:
data.as_json