{% show_simple_captcha_tag %}

Showing simple captcha in liquid template

module Liquid
module Tags
module SimpleCaptcha
class HumanTest < ::Liquid::Tag
include ::ActionView::Helpers::FormTagHelper
include ::SimpleCaptcha::ViewHelper
attr_accessor :request, :session
def render(context)
controller = context.registers[:controller]
self.request = controller.request
self.session = controller.session
context.registers[:controller].send(:render_to_string, :partial => ::SimpleCaptcha.partial_path, :locals => { :registers => context.registers, :simple_captcha_options => simple_captcha_options({}) })
end
end
end
::Liquid::Template.register_tag('show_simple_captcha_tag', SimpleCaptcha::HumanTest)
end
end

view raw
simple_captcha.rb
hosted with ❤ by GitHub

activerecord GROUPed BY in batches

We are all familiar with activerecord .find_in_batches. The main idea behind it is not allowing to load thousands of ActiveRecord objects in memory which would cause tear down the server. I looked at this method and I looked at `.group` which applies GROUP BY clause. Just for fun, I thought what if I receive these “grouped_by” data in batches, something like

 scope.grouped_by_in_batches(group_by_column) do |batch, value|
  batch is an array same as we get in case of `find_in_batches`
  value is the grouped value of the column
 end

Hence I worked on this idea, made a pull request which obliviously did not work, as this was not a common use case, thats all fine. I agree to it. Even I never got to use it till date. However in attempt to do so, I really enjoyed writing test cases for it, getting interacted with a couple of ruby/rails expertise. Feeling happy about it.

rspec STDOUT

I happened to write some rspec for one ruby program which was accepting some input text in some form, and then it was expected to print the output to the console, or perhaps I did not want to separate the logic of printing. Anyways, that made me expect rspec should check the console output of my program, and after some googling(thanks to many rubyist) I got to work the following

require 'spec_helper'
describe "Transaction" do
it "should handle dummy numerals" do
transaction_input(%{
x1 is I
x5 is V
x10 is X
x50 is L
x100 is C
x500 is D
x1000 is M
how much is x1000 x100 ?
how much is x1 x1 ?
how much is x1 x5 ?
}
).should_output(%{
x1000 x100 is 1100
x1 x1 is 2
x1 x5 is 4
})
end
end

view raw
transaction_spec.rb
hosted with ❤ by GitHub

Wow, I liked it.

And the spec_helper made it for me

require "#{File.dirname(__FILE__)}/../lib/transactions.rb"
include Transactions
def capture_stdout(&block)
original_stdout = $stdout
$stdout = fake = StringIO.new
begin
yield
ensure
$stdout = original_stdout
end
fake.string
end
class TransactionInput
def initialize output
@output = output
end
def should_output output
@output.split("\n").should == output.split("\n")[1..-2].collect{|line| line.strip}
end
end
def transaction_input input
TransactionInput.new capture_stdout{ input.split("\n")[1..-2].each{|line| Message.new(line).process} }
end

view raw
spec_helper.rb
hosted with ❤ by GitHub

Highlight changes being made on ActiveRecord object inside email

I simply needed one helper method which would help me highlight changes being made on any ActiveRecord object inside email. Below is one example of that I have come up with and would like to extend it in my future projects too.

It gave me some insights into ActiveRecord::Base#previous_changes and ActiveRecord::Base#reflections. Nice to learn such ActiveRecord features.

samg/diffy also helped me out decorating text changes

Screenshot from 2014-01-16 13:50:15

Adding to my MailerHelper

module MailerHelper
def highligh_changes_made_to object, options={}
html = ""
attrs = options[:attrs] || object.class.attribute_names
html << "<br/><p>"
attrs.each do |attr|
html << "<p> #{attr.to_s.humanize} : "
if object.previous_changes.include? attr.to_s
if object.class.columns_hash[attr.to_s].type==:text
html << "<br/>"
html << text_changes(object.previous_changes[attr.to_s][0], object.previous_changes[attr.to_s][1])
else
html << "<font color='gray'>#{object_attr object, attr, object.previous_changes[attr.to_s][0]}</font> => "
html << "<b>#{object_attr object, attr, object.previous_changes[attr.to_s][1]}</b>"
end
else
html << "#{object_attr object, attr, (object.send attr.to_sym)}"
end
html << "</p>"
end
html << "<p/><br/>"
html.html_safe
end
def object_attr object, attr, foreign_key_value
return foreign_key_value unless attr.ends_with? "_id"
assoc = object.class.reflections.values.select{ |assoc| assoc.foreign_key==attr }.first
return "<NotFound>" unless assoc
assoc.klass.where(:id => foreign_key_value).first || '""'
end
def text_changes str1, str2
Diffy::Diff.new( str1, str2).collect do |line|
case line
when /^\+/ then
"<b>#{line[1..-1]}</b>"
when /^-/ then
"<font color='gray'>#{line[1..-1]}</font>"
when /^\// then
else
line
end
end.join("<br/>").to_s
end
end
class ActionMailer::Base
helper MailerHelper
end

view raw
mailer_helper.rb
hosted with ❤ by GitHub

My rails mailer knows request and current_user

How about accessing @request and @current_user in your mailer

# config/initializers/mailer_knows.rb
module MailerBefore
def before(hash)
hash.keys.each do |key|
define_method key.to_sym do
eval " @#{key} = hash[key] "
end
end
end
end
class ActionMailer::Base
extend MailerBefore
end
class ActionController::Base
before_filter :mailer_knows
def mailer_knows
ActionMailer::Base.before({
:request => request,
:current_user => (current_user and current_user.dup)
})
end
end

view raw
mailer_knows.rb
hosted with ❤ by GitHub

a quick javascript lightbox

I had to develop some feature which required some javascript lightbox,
I really not needed a fancy one, but a small or medium one
it was for some small confirmation and in addition a couple of inputs on confirmation
so you can imagine a small html form being poped up
I had to add one then, and I guessed tomorrow there might be couple of more coming

I found very nice options when googled
but I thought of implementing one of my own just for fun, and I got this a quick one

admin.lightbox.show(
  html: "my html goes here"
  title: "my title"
).done(->
  alert "Am done"

hi there

And it really took a very less time to build this one as follows

window.admin ||= {}
$.extend window.admin,
lightbox:
show: (options) ->
options = {} unless options
buttonDone = options.buttonDone or "Done"
buttonCancel = options.buttonCancel or "Cancel"
focus = options.focus or "input"
$("body").append "<div id='modal_shadow'></div>" unless $("div#modal_shadow")[0]
$("body").append "<div id='admin-lightbox'></div>" unless $("div#admin-lightbox")[0]
$("div#admin-lightbox").html "<div id='content'>" + options.html + "</div><div id='buttons'></div>"
$("div#admin-lightbox div#buttons").append "<button onclick='admin.lightbox.do_done(); return false;'>" + buttonDone + "</button>"
$("div#admin-lightbox div#buttons").append "<button onclick='admin.lightbox.do_cancel(); return false;'>" + buttonCancel + "</button>"
$("div#admin-lightbox").prepend "<div id='title'>" + options.title + "</div>" if options.title
$("div#modal_shadow").show()
$("div#admin-lightbox").show()
$($("div#admin-lightbox " + focus)[0]).focus()
admin.lightbox
callback_done: null
done: (callback) ->
admin.lightbox.callback_done = callback
admin.lightbox
do_done: ->
try
admin.lightbox.callback_done()
admin.lightbox.hide()
false
callback_cancel: null
cancel: (callback) ->
admin.lightbox.callback_cancel = callback
admin.lightbox
do_cancel: ->
try
admin.lightbox.callback_cancel()
admin.lightbox.hide()
false
hide: ->
$("div#modal_shadow").hide()
$("div#admin-lightbox").hide()
admin.lightbox

The most interesting part here is to be able to define callbacks like done and cancel.

body.active_admin #modal_shadow{
z-index: 999998;
position:fixed;
top: 0px; left: 0px;
height:100%; width: 100%;
background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2NsampKAwAFAgHu04pC4AAAAABJRU5ErkJggg==) repeat;
display:none;
padding: 0; margin: 0;
}
body.active_admin #admin-layout{
padding:10px;
margin:10px;
top: 100px;
min-height:100px;min-width:200px;
display:none;
background-color:white;
z-index:999999;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
box-shadow: 0px 5px 19px #777;
-o-box-shadow: 0px 5px 19px #777;
-webkit-box-shadow: 0px 5px 19px #777;
-moz-box-shadow: 0px 5px 19px #777;
position:fixed;
top: 50%;
left: 50%;
margin-left: -200px;
margin-top: -150px;
}
body.active_admin #admin-layout #title{
padding:2px 5px;
background-color: #efefef;
font-weight: bold;
color:#555;
font-size: 1.1em;
margin-bottom: 10px;
-webkit-border-top-left-radius: 5px;
-webkit-border-top-right-radius: 5px;
-moz-border-radius-topleft: 5px;
-moz-border-radius-topright: 5px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
body.active_admin #admin-layout #content{
float:left;
margin-bottom:10px;
}
body.active_admin #admin-layout #buttons{
height:42px;
width:96.5%;
padding:5px;
float:right;
background-color: #efefef;
float:right;
border-bottom: 1px solid #eee;
border-left: 1px solid #eee;
border-right: 1px solid #eee;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-moz-border-radius-bottomleft: 5px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
body.active_admin #admin-layout #buttons button{
margin:8px;
padding:8px;
padding-top:6px;
padding-bottom:6px;
float:right;
font-weight: bold;
color:#555;
font-size: 1.0em;
}

And I welcome all suggestions :)

smallest thread pool in ruby

class ThreadPool
attr_accessor :threads, :max_size
def initialize max_size=4
@max_size = max_size
@threads = []
end
def start *args, &block
while(threads.count>=max_size) do
threads.select!{ |thr| !thr.stop? }
sleep(0.1)
end
threads << Thread.new(args) do |args|
begin
args = args[0] if args.length==1
yield args
rescue Exception => e
puts e.message
puts e.backtrace
end
end
end
def join
threads.map(&:join)
end
end
# p = ThreadPool.new
# 1.upto(10) do |i|
# p.start(i) do |a|
# $stdout.flush
# puts "p #{a}"
# end
# end
# p.join

view raw
thread_pool.rb
hosted with ❤ by GitHub

activeadmin cool tweaks

tweak 1: Make some column quick-editable on the index list page

1

Ok… so I want to be quickly able to edit few names, here on the same list page, something like below

2

Thats simply great!

Now it makes me quickly update any name there itself on the list page, <enter> will make it, <escape> will ignore it, and <tab> will move to the next one. awesome.

And to make it work I just need to have one line of code change

All I need to say is `editable_test_column`, and its done.

ActiveAdmin.register Article do
index do
selectable_column
id_column
column :name, :sortable => :name do |resource|
editable_text_column resource, :name
end
column :article_type
column :created_at
column :updated_at
default_actions
end
end

view raw
article.rb
hosted with ❤ by GitHub

And here how it works, you will need to define a couple of things

You need to define editable_text_column, this you could place inside app/admin/lib/

module ActiveAdmin
module Views
class IndexAsTable < ActiveAdmin::Component
def editable_text_column resource, attr
val = resource.send(attr)
val = "&nbsp;" if val.blank?
html = %{
<div id='editable_text_column_#{resource.id}'
class='editable_text_column'
ondblclick='admin.editable_text_column_do(this)' >
#{val}
</div>
<input
data-path='#{resource.class.name.tableize}'
data-attr='#{attr}'
data-resource-id='#{resource.id}'
class='editable_text_column admin-editable'
id='editable_text_column_#{resource.id}'
style='display:none;' />
}
html.html_safe
end

view raw
custom_columns.rb
hosted with ❤ by GitHub

Then you will need to add some javascript …

var admin = {
init: function(){
admin.set_admin_editable_events();
},
set_admin_editable_events: function(){
$(".admin-editable").live("keypress", function(e){
if ( e.keyCode==27 )
$( e.currentTarget ).hide();
if ( e.keyCode==13 ){
var path = $( e.currentTarget ).attr("data-path");
var attr = $( e.currentTarget ).attr("data-attr");
var resource_id = $( e.currentTarget ).attr("data-resource-id");
var val = $( e.currentTarget ).val();
val = $.trim(val)
if (val.length==0)
val = "&nbsp;";
$("div#"+$( e.currentTarget ).attr("id")).html(val);
$( e.currentTarget ).hide();
var payload = {}
resource_class = path.slice(0,1) // e.g. path = meters, resource_class = meter
payload[resource_class] = {};
payload[resource_class][attr] = val;
$.put("/admin/"+path+"/"+resource_id, payload).done(function(result){
console.log(result);
});
}
});
$(".admin-editable").live("blur", function(e){
$( e.currentTarget ).hide();
});
},
editable_text_column_do: function(el){
var input = "input#"+$(el).attr("id")
$(input).width( $(el).width()+4 ).height( $(el).height()+4 );
$(input).css({top: ( $(el).offset().top2 ), left: ( $(el).offset().left2 ), position:'absolute'});
val = $.trim( $(el).html() );
if (val=="&nbsp;")
val = "";
$(input).val( val );
$(input).show();
$(input).focus();
}
}
$( document ).ready(function() {
admin.init();
});

view raw
active_admin.js
hosted with ❤ by GitHub

and some css stuff

input.editable_text_column {
background-color: #FBFF8C;
border: 1px none #FBFF8C;
box-shadow: 0 2px 19px #AAAAAA;
color: black;
display: none;
font-family: serif;
font-size: 1em;
font-style: italic;
height: 30px;
position: absolute;
text-align: center;
vertical-align: middle;
width: 180px;
z-index: 9090;
}
div.editable_text_column{
padding:4px;
background-color: #f9fbc2;
}

Thats it.

Next, I would love to quickly alter article type say having a dropdown there to save my time

tweak 2: quick editable dropdowns on list page

6

Ohh, now this is again great!   … no? It actually updates the article type on value change. nice.

Let see the code behind

ActiveAdmin.register Article do
index do
selectable_column
id_column
column :name, :sortable => :name do |resource|
editable_text_column resource, :name
end
column 'Type', :sortable => :article_type do |resource|
column_select(resource, :article_type, ["News", "Story", "Case Study", "Business"])
end
column :created_at
column :updated_at
default_actions
end
end

view raw
article.rb
hosted with ❤ by GitHub

and to define `column_select`

module ActiveAdmin
module Views
class IndexAsTable < ActiveAdmin::Component
include CustomHelper
def column_select resource, attr, list
val = resource.send(attr)
html = _select list, val, { "attrs" => %{
data-path='#{resource.class.name.tableize}'
data-attr='#{attr}'
data-resource-id='#{resource.id}'
class='admin-selectable'
}
}
html.html_safe
end

view raw
custom_columns.rb
hosted with ❤ by GitHub

CustomHelper is one of my helper modules that really helps me render dropdown the way I need, and provides me some nice options, one may choose to use the default rails select helpers

module CustomHelper
def _select set, selected, options={}
style = "margin:0;padding:0;#{options["style"]}"
selected = options["default"] if selected.blank?
cache = options["cache"] || nil
id = options["id"] || nil
id ||= "ch#{ch_uniq_id}" unless cache.blank?
html = ""
html << "<select "
html << " style='#{style}' "
html << " #{options["attrs"]} "
html << " data-cache='#{cache}' " unless cache.blank?
html << " id='#{id}' " unless id.blank?
html << ">"
if options["blank"]
html << "<option></option>"
end
unless cache.blank?
options_html = Rails.cache.fetch("CustomHelper:#{cache}", expires_in: 1.minute ) { _select_options set, selected, options }
else
options_html = _select_options set, selected, options
end
html << options_html
html << "</select>"
unless cache.blank?
html << %{
<script type="text/javascript">
$( document ).ready(function() {
$("select##{id}").val("#{selected.to_s.strip}");
});
</script>
}
end
html
end
def _select_options set, selected, options
html = ""
selected = selected.to_s.strip
arr_match = options["arr_match"] || 0
set.each do |option|
check = option
value = option
if option.is_a? Array
check = option[arr_match]
value = option[0]
option = option[1]
end
if selected==check.to_s.strip
html << "<option value='#{value}' selected>#{option}</option>"
else
html << "<option value='#{value}'>#{option}</option>"
end
end
html
end
def ch_uniq_id
@ch_uniq_id ||= Time.now.to_i
@ch_uniq_id += 1
end
end

view raw
custom_helper.rb
hosted with ❤ by GitHub

Then you need some javascript

var admin = {
init: function(){
admin.set_admin_selectable_events();
},
set_admin_selectable_events: function(){
$("select.admin-selectable").live("change", function(e){
var path = $( e.currentTarget ).attr("data-path");
var attr = $( e.currentTarget ).attr("data-attr");
var resource_id = $( e.currentTarget ).attr("data-resource-id");
var val = $( e.currentTarget ).val();
val = $.trim(val)
var payload = {}
resource_class = path.slice(0,1)
payload[resource_class] = {};
payload[resource_class][attr] = val;
$.put("/admin/"+path+"/"+resource_id, payload).done(function(result){
console.log(result);
});
});
}
}
$( document ).ready(function() {
admin.init();
});

view raw
active_admin.js
hosted with ❤ by GitHub

done.

I do have worked out several more tweaks like toggle button for boolean column, show/hide columns on the list page, auto-populate/suggest feature for string filters, one can make use ActiveAdmin icons too, then for one of my requirements I have set up the whole custom header and a dozens of custom pages. I would easily say that ActiveAdmin is just simple and awesome, one can really customize it to the extreme, the code structure will allow you to imagine and implement a number of custom scenarios.

rails user modifies email

I often thought of this, application user is actually modifying the email contents before mail gets delivered. And I just set one example of it 

# gem 'ckeditor_rails' # from https://github.com/tsechingho/ckeditor-rails
# allow modifying existing template
<textarea name="modified_email" class="ckeditor">
<%= File.read "#{Rails.root.to_s}/app/views/user_mailer/do_email.html.erb"%>
</textarea>
<%= javascript_include_tag "ckeditor-jquery" %>
<script type="text/javascript">
$('.ckeditor').ckeditor({
height: "800px",
allowedContent: true,
toolbar: [
{ name: 'document', items : [ 'Source', '-', 'Undo','Redo', '-','SpellChecker'] },
{ name: 'basicstyles', items : [ '-', 'Bold','Italic','Underline'] },
{ name: 'colors', items : [ '-', 'TextColor','BGColor' ] },
{ name: 'styles', items : [ '-', 'Styles','Format','Font','FontSize' ] },
{ name: 'tools', items : [ '-', 'Maximize' ] }
]
});
setTimeout(function(){
$("a.cke_button").attr("style", "padding:8px;");
$(".cke_chrome").attr("style", "width: 76% !important; overflow: hidden;");
}, 500);
</script>
# in your mailer
def do_email modified_contents
body = ActionView::Base.new.render :inline => CGI.unescapeHTML(modified_contents), :locals => { :token => token }
# you can have assigns as well
mail :to => recipients,
:subject => "Do Email",
:content_type => "text/html",
:body => body
end