Thursday, November 5, 2015

Upload Image using CKeditor - Rails

Hello Guys,

   Today i've configure CKeditor (https://github.com/galetahub/ckeditor) to my Rails application and i found there is no upload button along with Image insert dialog.
So i've modified the ckeditor/config.js to below and it then show new tab called 'Upload' in Image insert dialog.

See. config.js

CKEDITOR.editorConfig = function (config) {

  // ... other configuration ...
  config.language = 'en';
  config.toolbar_regular = [
    { name: 'document', items: ['Source'] },
    { name: 'clipboard', groups: [ 'clipboard', 'undo' ], items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] },
    { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ], items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat' ] },
    '/',
    { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align', 'bidi' ], items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', 'CreateDiv', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] },
    { name: 'links', items: [ 'Link', 'Unlink', 'Anchor' ] },
    { name: 'insert', items: ['Table', 'Image', 'HorizontalRule', 'SpecialChar' ] },
    '/',
    { name: 'styles', items: [ 'Styles', 'Format', 'Font', 'FontSize' ] },
    { name: 'colors', items: [ 'TextColor', 'BGColor' ] },
    { name: 'tools', items: [ 'Maximize'] },
    { name: 'plugins', items: ['CodeSnippet', 'Cite'] }
  ];
  config.toolbar_lite = config.toolbar_regular.concat({ name: "lite", items: ["lite_ToggleShow", "lite_AcceptAll", "lite_RejectAll"] });
    config.toolbar = 'regular';
  config.allowedContent = true;
   /* Filebrowser routes */
  // The location of an external file browser, that should be launched when "Browse Server" button is pressed.
  config.filebrowserBrowseUrl = "/ckeditor/attachment_files";
  // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Flash dialog.
  config.filebrowserFlashBrowseUrl = "/ckeditor/attachment_files";
  // The location of a script that handles file uploads in the Flash dialog.
  config.filebrowserFlashUploadUrl = "/ckeditor/attachment_files";
  // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Link tab of Image dialog.
  config.filebrowserImageBrowseLinkUrl = "/ckeditor/pictures";
  // The location of an external file browser, that should be launched when "Browse Server" button is pressed in the Image dialog.
  config.filebrowserImageBrowseUrl = "/ckeditor/pictures";
  // The location of a script that handles file uploads in the Image dialog.
  config.filebrowserImageUploadUrl = "/ckeditor/pictures";
  // The location of a script that handles file uploads.
  config.filebrowserUploadUrl = "/ckeditor/attachment_files";
  // Rails CSRF token
  config.filebrowserParams = function(){
    var csrf_token, csrf_param, meta,
        metas = document.getElementsByTagName('meta'),
        params = new Object();
    for ( var i = 0 ; i < metas.length ; i++ ){
      meta = metas[i];
      switch(meta.name) {
        case "csrf-token":
          csrf_token = meta.content;
          break;
        case "csrf-param":
          csrf_param = meta.content;
          break;
        default:
          continue;
      }
    }
    if (csrf_param !== undefined && csrf_token !== undefined) {
      params[csrf_param] = csrf_token;
    }
    return params;
  };
  config.addQueryString = function( url, params ){
    var queryString = [];
    if ( !params ) {
      return url;
    } else {
      for ( var i in params )
        queryString.push( i + "=" + encodeURIComponent( params[ i ] ) );
    }
    return url + ( ( url.indexOf( "?" ) != -1 ) ? "&" : "?" ) + queryString.join( "&" );
  };
  // Integrate Rails CSRF token into file upload dialogs (link, image, attachment and flash)
  CKEDITOR.on( 'dialogDefinition', function( ev ){
    // Take the dialog name and its definition from the event data.
    var dialogName = ev.data.name;
    var dialogDefinition = ev.data.definition;
    var content, upload;
    if (CKEDITOR.tools.indexOf(['link', 'image', 'attachment', 'flash'], dialogName) > -1) {
      content = (dialogDefinition.getContents('Upload') || dialogDefinition.getContents('upload'));
      upload = (content == null ? null : content.get('upload'));
      if (upload && upload.filebrowser && upload.filebrowser['params'] === undefined) {
        upload.filebrowser['params'] = config.filebrowserParams();
        upload.action = config.addQueryString(upload.action, upload.filebrowser['params']);
      }
    }
  });
};

Hope this article helps you.

Wednesday, August 27, 2014

Unlock ReadOnly Model Object

Phasing some interesting problem after creating record for model which has HasMany relationship.

I have class say 'Category' & 'CategoryOptions'.

Category Has Many CategoryOptions

When i create record for CategoryOption using below syntax it locks the newly created object.

category = Category.first
category_option = category.category_options.create(params[:category_option])

If i do 

category_option.readonly?
=> true

Now i'm trying to update category_option using

category_option.update_attributes(params[:category_option])

but it raises Exception like 

ActiveRecord::ReadOnlyRecord

To remove readonly lock from object use below method

category_option.send(:instance_variable_set, :@readonly, false)

Now try

category_option.readonly?
=> false

category_option.update_attributes(params[:category_option]) works perfectly.

Hope this article will help you to remove Readonly lock from Model Object.

Wednesday, June 18, 2014

Install WKHTMLTOPDF

Hello Guys,
        Here i'm providing steps to install Wkhtmltopdf.

1. Download WKHTMLTOPDF source from http://wkhtmltopdf.org/downloads.html
2. Dobule click on downloaded source.
3. Go to terminal and type : which wkhtmltopdf. That gives you path like below.   /usr/local/bin/wkhtmltopdf4. wkhtmltopdf --version : gives you version no of installed wkhtmltopdf.

Tuesday, July 2, 2013

Delayed job to use specific connection via ruby

Hello Guys,
           Yesterday  i was phasing one interesting problem. Sharing single database between 2 rails application but now i've requirement to use application specific table for delayed jobs.

Lets assume i've application called DemoApp & TestApp. And both sharing single DB called 'demo_app_prod'. Now for TestApp i required separate DB called 'test_app_prod' which has single table called 'delayed_jobs'.

Step1:

at TestApp you have database.yaml like
 login: &login
  adapter: mysql
  username: admin
  host: localhost  

  password:
 
development:
  <<: *login
  database:
demo_app_dev

test:
  <<: *login
  database:
demo_app_test
 
production:
  <<: *login
  database:
demo_app_prod  

staging:
  <<: *login
  database: test_app_prod


Step2:
at TestApp added migration called 
   rails generate migration add_delayed_job

  class AddDelayedJob < ActiveRecord::Migration
  def connection
    ActiveRecord::Base.establish_connection(Rails.env).connection
  end

 
  def up
    oldEnv = Rails.env
    Rails.env = 'staging' #set environment variable from your database.yml
    ActiveRecord::Base.establish_connection(Rails.env) 
  
    create_table :delayed_jobs, :force => true do |table|
      table.integer  :priority, :default => 0 

      table.integer  :attempts, :default => 0  
      table.text     :handler                      
      table.text     :last_error                  
      table.datetime :run_at                       
      table.datetime :locked_at                    
      table.datetime :failed_at                    
      table.string   :locked_by          
      table.timestamps
    end
    Rails.env = oldEnv
    ActiveRecord::Base.establish_connection ActiveRecord::Base.configurations[Rails.env]

  end
 
  def down   
    oldEnv = Rails.env
    Rails.env = '
staging'
    ActiveRecord::Base.establish_connection(Rails.env).connection

    drop_table :delayed_jobs
    Rails.env = oldEnv
    ActiveRecord::Base.establish_connection ActiveRecord::Base.configurations[Rails.env]

  end
end


Step3:

 In initializers/delayed_job.rb add below lines

Delayed::Job.class_eval do
  establish_connection ActiveRecord::Base.configurations["local"]
end


This the easy way to establish multiple db connection via ruby for delayed job.

Thursday, February 7, 2013

Rebuild the corrupted legacy data.


Hello Guys,
        Yesterday i phase one problem regarding positioning with legacy database. For my rails application i have used the awesome_nested_set to manage nesting/threading. Case is to rearrange the position and for that i have used pretty nice method called 'rebuild!'.

Assume i have model called 'Post' and have nesting per Category .

# id: integer
# category_id: integer
# lft :integer
# parent_id :integer
# position :integer
# rgt :integer
class Post < ActiveRecord::Base
  acts_as_nested_set :scope => :category
end

In the legacy database, having 3 categories called 'Alpha', 'Beta', 'Gama'. In which category Alpha's data mess out.
To over come this problem invoke command on console.
> script/console
> category = Category.find_by_name('Alpha')
> category.posts.rebuild!

Now cross check the data and it results as per need. Hope this post is helpful to you guys. Cheers!!

Tuesday, January 29, 2013

Integrate Bcms Blog along with BrowserCMS

Hello Guys,

        Want to integrate bcms_blog along with browser CMS via ruby? then simply follow the below steps.

http://modules.browsercms.org/modules/3-bcms-blog

Install gem called
gem install bcms_blog 

Specify configuration in environment.rb as
config.gem 'bcms_blog', :version=>'1.1.1'

Modify routes.rb
map.routes_for_bcms_blog
map.routes_for_browser_cms

No go to the your directory from command prompt and execute below commands.
script/generate browser_cms 
rake db:migrate

Now login to cms web page & go to Content Library Menu and on left side panel you'll see the Blog section and under that 3 sub sections.
 a. Blog
 b. Blog Comment
 c. Blog Post

Now creating and publishing blog follow procedure listed below:

1. Go to Blog section & create it.
2. Create category for blog section from Categorization -> Category Type..
3. Add blog post from Blog Post section.
4. Now publish all and on front end you'll see successfully created blog.
5. If you get any error like 
     ERROR: undefined method `_blog_post_path' for #<#:..> 
    Then
      include Cms::BlogHelper in ApplicationHelper
    And
     add  below method under Cms::BlogHelper
     def self.included(controller_class)
        Rails.logger.info "~~ BlogHelper included in #{ controller_class.inspect.to_s }"
     end 
6. Now on posted blog you have option for Comment.. and user's added comment only visible if they moderate it and publish.

Hope you guys, enjoy my blog.. and it's helpful .. For more information see https://github.com/browsermedia/bcms_blog/blob/master/doc/release_notes.txt

Thursday, December 27, 2012

Assign class or function to Dom element on the fly

Hello Guys,
        Want to assign the class to dom element on the fly? then simply use javascript function which listed below.

demo.html

Lets assume we have anchor tag on it's click we have to apply css class.

<a id="anchor" href="" target='_blank' class='active' onclick="javascript:open_url(this.id, 'google.com');"> Open this link in new window or tab </a>

// javascript  function
<script type='javascript'>
  function open_url(id, url){
   // verify dom has 'active' class or not
   if ($('#' + id).hasClass('active')) {
     if(url != ''){
    // it's open url in new window
     window.open(url);
   }
  }
}
</script>

Thursday, December 13, 2012

Preventing Recursive Method Calls in Salesforce

Hello Guys,
        Yesterday i was playing with salesforce custom object. I had task to update the object once particular field get updated /inserted (for same object). 

Eg. I have Student__c is custom object on salesforce.

Structure of Student__c object is like:
Id, Name__c, Score_in_maths__c, Score_in_science__c, Total_score__c

So when trying to update any score value required to update Total_score__c  accordingly.  To fulfill  this i have added trigger on Student__c (after update) but it results as recursive loop.

To overcome above issue just followed the steps mention in http://blog.jeffdouglas.com/2009/10/02/preventing-recursive-future-method-calls-in-salesforce/. And it works for me.

Free feel to leave comment or ask queries. :)

Thursday, October 4, 2012

Generate chart using axlsx gem

Hello Rubies,
        I have generated the graph via axlsx gem of ruby. Follow the easy steps to generate 3D stacked bar graph.

Install axlsx gem via
   gem install axlsx

Lets, generate graph.rb file and than run ruby graph.rb

require "rubygems"
require "axlsx"

 p = Axlsx::Package.new
 wb = p.workbook

 wb.styles do |s|
    wb.add_worksheet(:name => "Bar graph demo") do |sheet|
        sheet.add_row ["A Simple Bar Chart"]
        sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A1", :end_at => "F27", :grouping => :stacked, :show_legend => false, :shape => :box, :barDir => :col) do |chart|
         chart.valAxis.title = "Volumes"
         chart.catAxis.title = "Periods"
         chart.add_series :data => [1,2,3], :labels => ['Mar', 'Apr','May'], :colors => ['92D050', '92D050', '92D050']
         chart.add_series :data => [4,2,6], :labels => ['Mar', 'Apr', 'May'], :colors => ['FFFF00', 'FFFF00','FFFF00']
       end
   end  
end

file = File.open('/home/Desktop/graph.xlsx', 'w')
p.serialize(file)

Lets invoke ruby graph.rb on console and get the stacked bar chart.

Thursday, September 20, 2012

Axlsx to support line break (\n)

Hello Rubies,
      Yesterday when i was playing with axlsx gem find something interesting. Requirement is need to allow line break in content. And current axlsx gem does not support that feature. So add this patch to your existing gem or either point directly to git repository b'coze that patch is unpublished as for now.

Add this line to axlsx1.2.3/lib/axlsx/workbook/worksheet/worksheet.rb

Remove line #500  

str.gsub(/[[:cntrl:]]/,'')

and Replace with

  if RUBY_VERSION == "1.8.7"
    nasty_control_char_matcher = Regexp.new("[\x01\x02\x03\x04\x05\x06\x07\x08\x1F\v\xE2]")
  else
    nasty_control_char_matcher = Regexp.new("[\x01\x02\x03\x04\x05\x06\x07\x08\x1F\v\u2028]")
  end

  str.gsub(nasty_control_char_matcher,'')

or

gem 'axlsx', '1.2.3', :git => 'git://github.com/randym/axlsx.git'

Hope this post is useful to you folks :).

Wednesday, September 5, 2012

jumping of browser window when using cursor keys

Hello Guys,
           There is wired problem when using auto completer on page and try to use arrow key for navigation.. it simply jump the browser window.

To over come this problem just add the patch in controls.js

replace line 212 to 214 with

    if(this.index > 0) {this.index--;}
    else {
      this.index = this.entryCount-1;
      this.update.scrollTop = this.update.scrollHeight;
    }
    selection = this.getEntry(this.index);
    selection_top = selection.offsetTop;
    if(selection_top < this.update.scrollTop){
    this.update.scrollTop = this.update.scrollTop-selection.offsetHeight;
    }

replace line 217 to 220 with

    if(this.index < this.entryCount-1) {this.index++;}
    else {
      this.index = 0;
      this.update.scrollTop = 0;
    }
    selection = this.getEntry(this.index);
    selection_bottom = selection.offsetTop+selection.offsetHeight;
    if(selection_bottom > this.update.scrollTop+this.update.offsetHeight){
      this.update.scrollTop = this.update.scrollTop+selection.offsetHeight;
    }
  
add line after 297
  this.update.scrollTop = 0;

In short by replacing two functions markPrevious() & markNext() will fix our problem.

Execute raw query and manual connection

Hello Rubies,
           Some time when we have huge query that it will be easy to use RAW SQL compare to ruby's active record query.

ActiveRecord::Base.connection.query <<-END
   /* Raw sql query */
  Select * from table where conditions
END

Custom connection and query

env = RAILS_ENV
config = YAML::load(File.open('config/database.yml'))
ActiveRecord::Base.establish_connection(config[env])

schemas = ActiveRecord::Base.connection.select_values("select * from pg_namespace where nspname not in ('public','information_schema') AND nspname NOT LIKE 'pg%'").inspect

Toggle div using ruby on rails

Hello Guys,
        Toggle is the function of prototype.js. We just have to use it to perform toggling.

eg.

html = "Toggle me <span id='collapse'>"
html << link_to_function(image_tag("arrow_normal.png", :style => 'border:none;'), "$('collapse').toggle();$('expand').toggle(); new Effect.Highlight('DIVID',{endcolor:'#ffffff', startcolor:'#ffffc8', duration:2.0}); return false;")
html << "</span>"    
html << "<span id='expand' style='display:none'>"
html << link_to_function(image_tag("arrow-down.png", :style => 'border:none;'), "$('collapse').toggle();$('expand').toggle();return false;")
html << "<div id='DIVID'> HELLO </div> </span>"

Initially it show the text as Toggle me with right arrow. but when you click on that i replace the right arrow to down arrow. And display the container area with text HELLO as per above eg.

Wednesday, August 29, 2012

undefined method

Hello Guys,
            When i was trying to configure browser cms along with ruby 1.8.7 and rails 2.3.11. It raise the error like `==': undefined method `name' for "abstract":String.

Than i have find the related solution. So follow below things.

Replace method ==(other) at gems/rails-2.3.11/lib/rails/gem_dependency.rb:277

def ==(other)
   if self.respond_to?(:name) && other.respond_to?(:name)
       self.name == other.name && self.requirement == other.requirement
    else
      if other.respond_to?(:requirement)
        self.requirement == other.requirement
      else
        false
      end
    end
end

Hope this will save you life :)

Saturday, August 4, 2012

Replace double space with   in javascript

Hello Guys,
        Last time when i was playing with double spaces.. found the interesting thing. When passing the double space string from javascript (view) to controller , it converts the valid space to non-breaking space.

Lets see the eg.

View: index.rhtml

a = "This  is the pen"
a.gsub("  ", "&nbsp;&nsbsp;")

<script language='javascript/text'>
 
  /* Now assign the value to input element by */
  $('txtid').value = <%= a %>;

 // Get value back encodeURIComponent($('txtid'))

</script>
 
at controller

def any_method
   # replace '\xC2\xA0' or '&nbsp;' with ' '
   params[:a].gsub("\xC2\xA0", " ").gsub("&nbsp;", " ")
end

Hope above article is helpful to you guys.

Disable right mouse click script

Hello Guys,
        Wanna to disable the right click? Follow the below JavaScript to achieve that.

eg.
test.html

<html>
  <body>
    <div id='img'>
       <%= image_tag('https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiH4hixyVqT9hmPJ3J2xBoC7972VOGveRP864H_eGjWZyeIrzxVdHs3GgshxDAS0LdvmtzFBmSxNw8yC3Plz7zUH2fE594sKTp2FTvbaITKcM1ajz8u8GTTMbol3KXUJLs5NPtdfLqc_A/s220-h/cutex.jpeg') %>
    </div>
  </body>
 
  <script language="javascript" type="text/javascript">
 
   // Disable right click 
   var message = "you can't right click on image";

   function clickIE4(){
     if (event.button == 2) {
        return false;
    }
  }

  function clickNS4(e){

    if (document.layers || document.getElementById && !document.all) {
   
      if (e.which == 2 || e.which == 3) {
          return false;
      }
    }
  }

  if (document.layers) {
    document.captureEvents(Event.MOUSEDOWN);
    document.onmousedown = clickNS4;
  }
  else
    if (document.all && !document.getElementById) {
      document.onmousedown = clickIE4;       
    }

   document.oncontextmenu = new Function("alert(message); return false")
  </script>
</html>

Friday, July 27, 2012

Arbitrary precision decimal floating-point type for Ruby

Hello Rubies,
           Accurately convert numbers  to decimal or exact precision point. Use the Flt gem do discover the below scenario. 

Flt::DecNum is a standards-compliant arbitrary precision decimal floating-point type for Ruby. It is based on the Python Decimal class. 

Usage:

sudo gem install flt

require 'flt'
include Flt
 
x = 0.00000020586
y = Flt::DecNum(x.to_s)
Flt::DecNum.context.precision = 2
puts y/Flt::DecNum(1)

result should be 2.1E-7

For more information just follow the http://flt.rubyforge.org/.

Thursday, July 26, 2012

Import csv file using ruby processor

Hello Guys,
        Let's discuss how to import .csv file into database using ruby processor.

Read the .csv file:

require 'fastercsv'

rows = CSV.read("#{RAILS_ROOT}/test.csv")
header = rows[0]
rows[1..-1].each do |row|
    data = {}
    header.each_with_index do |key, index|
      data[key.downcase] = row[index].strip
    end
    ModelObject.create!(data)
end

test.csv looks like

No,Name,Percentage
1,Priyanka,81
2,Rahul,82
3,Ruby,75

Wednesday, July 25, 2012

Cannot deserialize instance of date from VALUE_STRING on salesforce

Hello Guys,
        I am working on salesforce from past few days. Just discover the bug related to date field setting using databasedotcom gem. When we are setting date value using ruby 1.9.2 it works as per expectation but with ruby 1.8.7 it gives error like 'Cannot deserialize instance of date from VALUE_STRING value'. To resolve this issue need to install latest gem version databasedotcom-1.2.7.

See this thread on github to get more detail

Monday, July 23, 2012

Generate Rss feed with rails application

  Hey guys,
      Lets today we create the rss feed with our existing rails application. Consider we have controller called post and have index method to show all the available posts. Now meanwhile we need to create feed for available posts as well.

controller:

def index
  @posts = Post.find(:all, :order => "created_at desc")
  respond_to do |format|
     format.html { render :template => 'posts/index.rhtml' }
     format.xml { render :template => 'posts/index.rxml', :layout => false
        headers["Content-Type"] = "application/rss+xml"
     }
  end
end

view:

index.rxml

xml.instruct!
xml.rss "version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/" do
  xml.channel do
    xml.title 'Available Posts'
    xml.description h("Here is the posts ... blah blah")
   
    @posts.each do |post|
      xml.item do
        xml.title post.title
        xml.link url_for(:only_path => false,
          :controller => 'posts',
          :action => 'show',
          :fishery => post.id)
        xml.description post.description
        xml.pubDate CGI.rfc1123_date(post.created_at)
      end
    end
  end
end

index.rhtml

# Add auto discovery tag to access rss feed

<%= auto_discovery_link_tag :rss, {:controller => "posts", :action => "index"}%>

See your rss feed for posts is ready!! Whenever auto discovery tag found it enables the rss icon on browser. Keep in mind Either you have to use predefined xml node or need to create XSL template. You can also emend the stylesheet into XSL template.