{% 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

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.

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

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

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

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

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

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

google “chef-solo rails deploy git submodule checkout branch sha”

Working with chef resource deploy, faced several issues with Git provider, for examples

– enable_submodule does not work properly
– it does not get the latest code from submodules
– it does not allow you to choose specific branch and sha of any submodule
– in fact for main repo it does not allow you to switch to any specific branch and sha
– for some reason it says branch=version, who knows why ….

I tried correcting all above, and below is one of my examples, its working for me


# solo.rb
require File.expand_path('../lib/global_constants.rb', __FILE__)
require File.expand_path('../lib/git_addition.rb', __FILE__)
root = File.absolute_path(File.dirname(__FILE__))
file_cache_path root
cookbook_path [ root + '/cookbooks', root + '/custom_cookbooks']
data_bag_path root + '/data_bags'
node_path root + '/nodes'
role_path root + '/roles'
#log_level :debug
#log_location STDOUT
#verbose_logging false
# lib/git_addition.rb
require 'chef/log'
require 'chef/provider'
require 'chef/mixin/shell_out'
require 'fileutils'
require 'shellwords'
class Chef
class Provider
class Git < Chef::Provider
def fetch_updates
#setup_remote_tracking_branches if @new_resource.remote != 'origin'
converge_by("fetch updates for #{@new_resource.remote}") do
fetch_command = "rm Gemfile.lock; git fetch #{@new_resource.remote} && git fetch #{@new_resource.remote} –tags && git checkout #{@new_resource.branch} && git reset –hard #{@new_resource.sha}"
Chef::Log.debug "Fetching updates from #{new_resource.remote} and resetting to revision #{target_revision}"
shell_out!(fetch_command, run_options(:cwd => @new_resource.destination))
end
end
def checkout
sha_ref = target_revision
converge_by("checkout ref #{sha_ref} branch #{@new_resource.branch}") do
shell_out!("rm Gemfile.lock; git fetch -u && git checkout #{@new_resource.branch} && git reset –hard #{@new_resource.sha} ", run_options(:cwd => @new_resource.destination))
Chef::Log.info "#{@new_resource} checked out branch: #{@new_resource.branch} reference: #{sha_ref}"
end
end
def target_revision
@target_revision ||= begin
if sha_hash?(@new_resource.sha)
@target_revision = @new_resource.sha
else
@target_revision = remote_resolve_reference
end
end
end
alias :revision_slug :target_revision
end
end
end
class Chef
class Resource
class Deploy < Chef::Resource
attr_accessor :sha
def sha(arg=nil)
set_or_return(
:sha,
arg,
:kind_of => [ String ]
)
end
end
end
end
# main recipe
app_root = "#{$pw_home_dir}/myapp-deploy"
current_path = "#{app_root}/current"
cache_path = "#{app_root}/shared/cached-copy"
package "g++"
package "nodejs"
package "mysql-client"
package "libmysqlclient-dev"
rvm_ruby node.rvm_ruby
rvm_default_ruby node.rvm_ruby
deploy_revision app_root do
action $chef_rails_deploy
user node.user
group node.group
repo node.repo
branch ($cfg["myapp_branch"] or node.myapp_branch)
sha ($cfg["myapp_sha"] or node.myapp_sha)
env = { "RAILS_ENV" => $rails_env }
Chef::Mixin::DeepMerge.merge(node.environment, env)
environment env
before_migrate do
myapp_config cache_path
myapp_checkout cache_path
rvm_shell "bundle" do
ruby_string node.rvm_ruby
cwd cache_path
user node.user
group node.group
code %{ bundle –path #{cache_path} –gemfile #{cache_path}/Gemfile }
end
end
purge_before_symlink %w{tmp}
create_dirs_before_symlink %w{uploads tmp}
symlinks {}
symlink_before_migrate({
"log" => "log",
"tmp" => "tmp",
"public" => "public",
"cached-copy/config/database.yml" => "config/database.yml",
"cached-copy/config/config.yml" => "config/config.yml"
})
migrate true
migration_command "echo 'skipping RAILS_ENV=#{$rails_env} bundle exec rake db:migrate –trace' "
shallow_clone true # TBD
keep_releases 10
before_restart do
myapp_checkout "#{app_root}/current"
#assets ($cfg["myapp-revision"] or "HEAD") do
# app_path cache_path
#end
if production?
#rvm_gem "passenger" do
# options " -y "
#end
# follow myapp/installprofile.apache
#restart_command "touch tmp/restart.txt"
end
end
end
# definitions/submodule.rb
define :submodule, :name=>nil do
return if rollback?
rvm_shell "submodule #{params[:name]}" do
ruby_string node.rvm_ruby
cwd params[:name]
user node.user
group node.group
code %{ git submodule init && git submodule update }
end
end
# definitions/checkout.rb
define :checkout, :name=>nil, :cwd=>nil, :branch=>nil, :sha=>nil do
rvm_shell "#{params[:name]} #{params[:branch]} #{params[:sha]} => #{params[:cwd]}" do
ruby_string node.rvm_ruby
cwd params[:cwd]
user node.user
group node.group
code %{ git checkout #{params[:branch]} && git pull && git reset –hard #{params[:sha]} }
end
end
# definitions/myapp_checkout.rb
define :myapp_checkout, :name=>nil do
return if rollback?
path = params[:name]
submodule path
checkout "sm1" do
cwd "#{path}/vendor/plugins/sm1"
branch ($cfg["myapp_sm1_branch"] or node.myapp_sm1_branch)
sha ($cfg["myapp_sm1_sha"] or node.myapp_sm1_sha)
end
checkout "sm2" do
cwd "#{path}/vendor/plugins/sm2"
branch ($cfg["myapp_sm2_branch"] or node.myapp_sm2_branch)
sha ($cfg["myapp_sm2_sha"] or node.myapp_sm2_sha)
end
end

view raw

default.rb

hosted with ❤ by GitHub

dealing with concerns

Taking care of concerns, my views are

They are meant not to have large/GOD classes

They are not specific to ActiveRecord

They are there to help us out find out dependencies easier

They should not be dependent on each other, if module A has concern :b, then there should exist paths “root/a.rb” and “/root/a/b.rb“. Though this we ourself have to make sure about concerns path by writing additional code at initialization

I always willing to write clean and neat code, and have end up maintaining my concerns the following ways

  1. Reopening Class
  2. Include Module
  3. Extend ActiveSupport::Concern

I do have one doubt though, out of 3 approaches, which one is good for faster execution?


# config/initializers/concerns.rb
class << ActiveRecord::Base
def concerned_with(*concerns)
concerns.each do |concern|
require_dependency "#{name.underscore}/#{concern}"
klass = concern.to_s.classify.constantize rescue nil
send(:include, klass) if klass.is_a? Module
end
end
end
# Approach #1 opening User class
# app/models/user/validations.rb
class User << ActiveRecord::Base
validates :mobile, :length => { :in => 6..20 }, :allow_blank => true, :allow_nil => true
validates_presence_of :country, :name
before_create :is_zip_validated_by_yahoo?
# and so on
end
# Approach #2 Let User include module
# app/models/user/module_name.rb
module ModuleName
def blah_blah_blah
end # and so on ….
end
# Approach #3 extend ActiveSupport::Concern
# app/models/user/ensure_something_type.rb
module EnsureSomethingType
extend ActiveSupport::Concern
included do
before_create :ensure_something_type
belongs_to :something_type
has_one :something_base_type, :through => :something_type
end
def ensure_something_type
self.something_type ||= SomethingType.find_by_name("something something")
end
end
# app/models/user.rb
  concerned_with  :validations,
    :data_uploader,
    :ensure_something_type,
    :jingo_filters,
    :macro_reports,
    :pricing,

view raw

concerns.rb

hosted with ❤ by GitHub

handle_redirect_loop_if_appears


class ApplicationController < ActionController::Base
before_filter :handle_redirect_loop_if_appears
after_filter :set_session_back_url
def handle_redirect_loop_if_appears
return session[:redirect_loop_count] = nil unless request_repeats?
return session[:redirect_loop_count] = 1 unless session[:redirect_loop_count]
max_observed_time_diff_betn_reqs_when_in_loop = 10000
max_loop_count = 3
session[:last_request_time] = Time.now.to_i
session[:redirect_loop_count] += 1
return if session[:redirect_loop_count] < max_loop_count
if last_request_after < max_observed_time_diff_betn_reqs_when_in_loop
session[:last_request_time] = nil
session[:redirect_loop_count] = nil
redirect_to rescue_url and return
end
end
def last_request_after
return unless session[:last_request_time]
time_diff = Time.now.to_isession[:last_request_time].to_i
time_diff = time_diff * (1) if time_diff < 0
end
def rescue_url
home_url
end
def home_url
'/'
end
def request_repeats?
session[:back_url] == request.fullpath
end
def set_session_back_url
return unless request.get?
return if request.xhr?
session[:back_url] = request.fullpath
end
end

DRYing if @current_user.nil?

While working on one of rails applications, as I usually tend to check whether user is logged in, specially in views as follows

<% if @current_user.nil? %>
  <a href='url to login page'>
<% else %>
  <a href='some url where logged in user have access'>
<% end %>

And over some period I found this pattern repeating everywhere.

I thought of DRYing it, I wanted to have a kind of before_filter for every link that appear on the page, every link should go for login if that page or feature require user entity. and this should be handled by a common thing, similar to before_filter: login_require, on server side. I intend to achieve similar in views. A while back when I read up about html5 custom data attribute, and unobtrusive javascript etc, referring to them, I got one idea as described below, though it is not something that I am making use of custom data attribute exactly, but I found this idea useful and working. May be someone would have good suggestions here for me.

I will put any link which require user login as follows

<a href="/feature/page/" login-require >Feature</a>

And then I will have my after_load.js which will have the following event binding

jQuery('a[login-require]').bind('click', function() {
  <% if @current_user.nil? %>
    openOverlay('overlay-login');
    return false;
  <% else %>
    return true;
  <% end %>
});