Custom model callbacks in RubyOnRails

RubyOnRails provides us with many model callbacks around the object’s lifecycle when object is being created, updated or destroyed. For example: before_create, after_create, before_update, after_destroy etc. We use them to write & run our code around the object’s lifecycle by defining a method and associating them as one of the callbacks.

But then how can we make a piece of code execute as a callback for any another defined method except create, update, save and destroy? For example, let’s say we have a model Article and we want to execute something just before and after an article is being published without hooking into model’s before_save and after_save callbacks?

RubyOnRails or more precisely ActiveRecord provides us with a module ActiveModel::Callbacks, which allows us to define and register custom callbacks using define_model_callbacks method. Lets have a look at the snippet below for the above scenario:
Continue reading

 

Reasons to consider Spree when choosing an e-commerce platform

Don’t select your next e-commerce platform without reading about these 13 factors first.

Online business has become a dominant and growing force. Global sales through e-commerce topped $1 trillion in 2012, with North American and Asia-Pacific nations accounting for nearly 70% of it. Projections are that global e-commerce sales will reach $1.5 trillion in 2016.

“Conduct better due diligence of the platform”

Over 60% of medium to large e-commerce site owners claim they should have done better due diligence on the platform they selected for their store. Much too often do businesses face constrained growth or incur significant losses due to misguided platform selections.

ecommerce-development

If you are ready to sell online, choosing the best e-commerce system for your business can be a challenging and confusing process. Based on our deep expertise of rails e-commerce and Spree development, this blog will help make sense of 13 factors you should be considering for selecting an e-commerce platform for your store and how spree stacks up against the competition on those factors.

1. License
There is no “enterprise” edition of Spree – its all the same software. Enterprise clients, small and medium sized businesses can use Open Source Spree for commercial purpose without paying any license fee.
Continue reading

 

Research firm SourcingLine publishes Vinsol in the list of top Ruby on Rails developers across the globe

The new research identifies leading web & application developers that work extensively with Ruby on Rails.

WASHINGTON, Updated At: June 25, 2014 – Today SourcingLine published new research on leading web and application developers with extensive Ruby on Rails experience.

The top firms inaugurated into the Ruby on Rails Developers Leaders Matrix are as follows:

Vinsol, Quick Left, Idyllic Software, philosophie, Burnside Digital, Perfectial, DevMynd Software, CognitiveClouds, and VeriQual.

Analysts reached out to firms with a demonstrated history of successful projects for both domestic international clients. Official findings are based on a firm’s proven experience, positive client reviews, and market presence. Companion directories were also published, which allow buyers to search for vendors that best fit their project needs and requirements.

“The flexibility and rapid deployment speed of Ruby on Rails make it ideal for many custom development projects,” explained Joshua Margolin, Senior Analyst at SourcingLine. “The vendors in our research have a proven record of using Rails to deliver viable, high-quality solutions to their clients.”
Continue reading

 

Exporting large data to CSV using mysql outfile in multi-host Rails env.

In one of our current project we had a requirement where we needed to allow the site admin to download raw DB data as CSV file for some offline analysis. So, according to the requirement, we allowed the admin to select a database table and a date range to download the generated CSV data.

Our initial approach was to send the CSV file asynchronously using delayed job. It worked like this:
Admin submits the request, system queues it and sends admin an email with the attached CSV file. The reason we did this asynchronously was to avoid timeout during CSV generation.

While testing & benchmarking this approach, we ecountered two issues when we had a large data to export.

  • Too much memory was used by the ruby process when generating the CSV
  • CSV size could be larger than the supported attachment size by the email service provider, hence could result in an undelivered email

Continue reading

 

Generate paperclip missing styles on the fly

Like most developers, who use paperclip gem with their RubyOnRails applications to support picture uploading and generation of distinct styles/thumbnails of pictures, for displaying them in various views, we also do the same in a lot of our apps.

After running one such web app in production for 2 years, the app needed to be redesigned. This required us to generate couple more styles/sizes for each uploaded image.

Paperclip provides a method ‘reprocess!(:style)’ to generate all/one style(s).

Now, when we planned to move this new version of the app to production, we had to generate those missing styles. There were a few thousand thumbnails to be generated, and our estimated time to generate these missing styles was around half an hour. Since we could not have the site available to users without the graphics, we had to put the site in maintenance mode until the new styles got generated. We also realized that as more images get uploaded and used in the system, this downtime if we ever needed to resize graphics again would go up. We could also not do this conversion without taking the site down as more images may get uploaded while we might be resizing using a script.
Continue reading

 

Full-Calendar Rails Engine

A couple of years ago we integrated jQuery FullCalendar plugin with a rails backend. The plugin became reasonably popular and was being used in many Rails apps.

Recently we upgraded it to include an efficient full-sized, drag & drop calendar functionality within a Rails Engine and release it as a gem. With Rails 4 deprecating Rails::Plugin(commit) this would come really handy.

It easily blends within a rails application. Provides a great UI experience with the use of AJAX to fetch events on-the-fly for each month and hooks for user-triggered events (like clicking or dragging an event) for an easy event editing functionality. The view can be easily customized using the configurations provided.

A demo version of this engine implementation can be viewed at http://vinsol.com/fullcalendar-demo

Work in progress : Optimizing Recurring Event functionality.

Source code is hosted on github. Feel free to fork and send a pull request etc.

 

Guide to Caching in Rails using Memcache

Guide to Caching in Rails using Memcache 1

The post intends to cover the topics and tools that can help in implementing Memcache as caching store in Rails and debugging issues with it.

To help newbies grasp it from start, it also provides references to installing and validating the memcache install without Rails too.

“Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering”

Installing Memcache

  • Mac OS X Snow Leopard
    • brew install memcached
  • Ubuntu
    • sudo apt-get install memcached

More information about Installing Memcache can be found here

Starting Memcache

  • memcached -vv

-v option controls verbosity to STDOUT/STDERR. Multiple -v’s increase verbosity. Memcache Settings can be inspected in detail using echo "stats settings" | nc localhost 11211. Get the thirst quenched more at http://linux.die.net/man/1/memcached or man memcached for all options.

Connecting to Memcache Server through Telnet

  • telnet localhost 11211 can be used to connect locally to run/inspect memcache data store
  • Its recommended to follow Using Memcache Commands to get a full hang of memcache commands
  • For the sake of completeness, here are three main commands (store/retrieve/remove key/values)
    • Write to Memcache (Value need to be entered in new line)
      • set abc 0 60 5 # where abc is the key, 60 is duration in seconds and 5 is length of data
      • hello # data to store in abc key
    • Read from Memcache
      • get abc
    • Delete from Memcache
      • delete abc

Implementing and Using in Rails

Installing Dalli (Memcache Client)

Configure Memcache as cache store in Rails

  • Set perform_caching and specify cache_store in the environment file (e.g. RAILS_ROOT/config/environments/production.rb)
    • config.action_controller.perform_caching = true
    • config.cache_store = :dalli_store, { :namespace => “my_project”, :expires_in => 1.day, :socket_timeout => 3, :compress => true }
      • Detailed explanation of Dalli Client options can be found here

Getting Ready for the Fight/Debugging

  • IRB as always helps us get started:
    • require ‘rubygems’
    • require ‘dalli’
    • CACHE = Dalli::Client.new(’127.0.0.1′, { :namespace => “my_project”, :expires_in => 3600, :socket_timeout => 3, :compress => true }) # Options are self-explanatory
    • CACHE.set(‘key’, ‘value’, 180) # last option is expiry time in seconds
    • CACHE.get(‘key’) 2

  • Memcache does not provide any command to list all keys present but at times seeing the keys and their expiry time can be a life saviour. Here is a Ruby Script to list all memcache keys

    Sample Output:

    id expires bytes cache_key
    1 2014-01-22 19:05:09 +0530 5 my_project:key

Using Memcache to store expensive calculations and avoid recalculations

  • We can store expensive calculations in memcache and retrieve it next time if expensive calculation expected to return the same result else recalculate and store again.
  • Rails provides helpers like Rails.cache.read to read cache, Rails.cache.write to write in cache and Rails.cache.fetch to return result if present in cache else write in cache and return the result
  • Code Snippet to pass a block to evaluate if key not present in cache, else return the value of key

      # File: application_controller.rb
    
      # Always Calculate if caching is disabled
      # Calculate the result if key not present and store in Memcache
      # Return calculated result from Memcache if key is present
    
      def data_cache(key, time=2.minutes)
        return yield if caching_disabled?
        output = Rails.cache.fetch(key, {expires_in: time}) do
          yield
        end 
        return output
      rescue
         # Execute the block if any error with Memcache
         
         return yield
      end
    
      def caching_disabled?
        ActionController::Base.perform_caching.blank?
      end
    
  • Using data_cache helper created in last step in application_controller.rb

      # File: posts_controller.rb
    
      respond_to :json
    
      def index
          # Create cache to expire after 3 minutes
          all_posts_for_a_category = data_cache("#{@category.name}", 3.minutes) do
              @category.posts.all
          end
          respond_with(posts: all_posts_for_a_category)
      end
    
      # Post#index - Before Filter
      def find_category
          @category = Category.where(id: params[:category_id]).first
          respond_with({message: 'Category Not Found'}, status: 404) if @category.blank? 
      end
    

Clearing Cache

Auto-Expire after a specified time

  • Memcache accepts an expiration time 3 option with the key to write and only returns the stored result if key has not expired yet, else returns nothing.
    • Rails.cache.write(key, value, {expires_in: time})
    • Rails.cache.fetch(key, {expires_in: time}) { # Block having expensive calculations }

Faking Regex based Expiry

  • Unfortunately, Memcache does not allow listing of all keys so, apparently, there is no way to partially expire a subset of keys. Memcache only provides a delete method for the specified key restricting us to, beforehand, know the key to delete.
  • But, there is a nice trick to partially expire a subset of keys Faking Regex Based Cache keys in Rails 4.
    • To achieve it, we have to focus more on keyword subset and defining subset is the Nirvana to crack the problem.
    • Introduce a dynamic component in all the keys which we want to treat as subset
    • Have a way to control the change of dynamic component
    • When dynamic component changes, a new key is created and stored in Memcache which would be referred for data from now.
    • The old key still remains in memcache and has still not expired but it stores the stale data and fresh data is hold by new key which we are referring in all of our interactions.
    • Memcache would eventually kick the old key with stale data out (uses LRU algorithm to allocate space for new data)
    • In the snippet below, we have added dynamic component last_cache_refreshed_at in Category which can be selectively changed to expire cache of particular categories instead of all

        # File: posts_controller.rb
      
        def index
            # Update Category#last_cache_refreshed_at anytime to force the block evaulation
            # again and storing the new key, hence expiring the last key by effectively not
            # refering it for data and consulting new key for fresh data
            # Time converted to integer to avoid sanitization hassle
      
            all_posts_for_a_category = data_cache("#{@category.name}-#{@category.last_cache_refreshed_at.to_i}", 3.minutes) do
                @category.posts.all
            end
            respond_with(posts: all_posts_for_a_category)
        end
      

Writing Test Cases

  • Enable Caching with Rspec metadata

      # File: spec/spec_helper.rb
    
      # describe "Action", caching: true {}
      # Above blocks would toggle the caching behaviour
      # default caching behavior is OFF
      # Use `bundle exec rspec -t caching:true spec` to run only caching examples
    
      config.around(:each, :caching) do |example|
        caching = ActionController::Base.perform_caching
        ActionController::Base.perform_caching = example.metadata[:caching]
        example.run
        ActionController::Base.perform_caching = caching
      end
    
      # Using `bundle exec rspec spec` would exclude caching:true examples
      # to run from test suite
    
      config.filter_run_excluding :caching => true
    
  • Caching Test Example (Dependency: Memcache should be running)

      # File: spec/controllers/posts_controller_spec.rb
    
      # Use `bundle exec rspec -t caching:true spec` to run only caching examples
    
      context 'Caching Enabled', caching: true do
        before(:each) do
          # last_cache_refreshed_at would ideally be handled through before_create callback
          # by setting current time as value to it
          # Assumption: Current Time in seconds = 1271325600
    
          @category = Category.new(name: 'Ruby', last_cache_refreshed_at: Time.current)
          @category.save.should be_true
          @post = @categroy.posts.build(content: 'Expiring Cache is tough !!!')
          @post.save.should be_true
        end
    
        after(:each) do
          @post.delete
          @category.delete
        end
    
        it "should return posts" do
          @category.last_cache_refreshed_at.should eq(1271325600)
    
          # Check Memcache doesnot have key
          Rails.cache.fetch("Ruby-1271325600").should be_nil
          get :index, {category_id: 1}
          response.should be_ok
          response.body.should == {success: true, posts: @all_posts}.to_json
    
          # As caching is enabled, key should be created in memcache
          Rails.cache.fetch("Ruby-1271325600").should_not be_nil
    
          # Invoke an action to refer a different key in memcache for same action
          # Assumption: Current Time in seconds = 1456782340
          @category.update_attributes(last_cache_refreshed_at: Time.current).should be_true
          @category.last_cache_refreshed_at.should_not eq(1271325600)
    
          # Old key is still present in memcache as still not expired
          Rails.cache.fetch("Ruby-1271325600").should_not be_nil
          get :index, {category_id: 1}
          response.should be_ok
    
          # New key is generated even though old key has still not expired
          # after the specified time, old key would expire
          Rails.cache.fetch("Ruby-1456782340").should_not be_nil
        end
      end
    

Gotchas

  • Using touch command to update expiry cache time (Fixed in Memcache 1.4.14)
  • Check Memcache Version using telnet client
    • Execute stats
    • Look for STAT version 1.4.13

  1. Caching Expensive Api Requests Results

  2. If Object is saved in Memcache, Cache.get(‘key’) might raise

    Dalli::UnmarshalError: Unable to unmarshal value: undefined class/module <model_name>

    Use require_dependency "app/models/.rb"

  3. Expiry Time of 0 makes the key stays for indefinite time only limited by Memcache clearing it out in case of cleaning up

  4. Scoped Expiration AND Reload Namespace using a Proc

 

Let your code speak – I

I want to make an attempt at extending the excellent review of Confident Ruby by Avdi Grimm from Viget Labs here which is best described by the below excerpt.

Confident Ruby makes the case that writing code is like telling a story, and reading code littered with error handling, edge cases, and nil checks is like listening to a bad story. The book presents techniques and patterns to write more expressive code with less noise—to tell a better story.

And, My favorite in the review list is BRE GTFO LOL where “BRE” stands for begin/rescue/end

In our day to day Rails coding routine, we come across lot of methods which use Rails arel methods directly like save, update_attributes, update_all etc. and sometimes the code story telling gets a back step in logic of arel chaining.

Here is a way which I came across to surface it up right in front and that too without loosing the coolness of arel chaining.

Before:
class Post
  # update callback
  def refresh_cache
    if publishability_changed?
      refresh_categories_cache_timestamp
    end
  end

  def refresh_categories_cache_timestamp
    categories.update_all(last_cache_refreshed_at: Time.current)
  end
end

Here, reading code littered with update_all breaks the story telling flow, yet again, and could be better expressed with below snippet.

After:
class Post
  # update callback
  def refresh_cache
    if publishability_changed?
      refresh_categories_cache_timestamp
    end
  end

  def refresh_categories_cache_timestamp
    categories.refresh_cache_timestamp!
  end
end
class Category
  def self.refresh_cache_timestamp!
    update_all(last_cache_refreshed_at: Time.current)
  end
end

Comparing the two snippets, After scores extra points on story telling as compared to Before.

We would be happy to respond to queries/questions in comments.

Tried on: Rails 3.2.16 with Ruby 1.9.3

 

[Press Release] VinSol Releases Four Spree Commerce Extensions

The following is a press release announcing launch of open source Spree commerce extensions from our eCommerce team.

New Delhi, October 10, 2013 – VinSol, a New Delhi, India based premier Ruby on Rails studio and Spree Commerce premier partner, today announced the release of four useful extensions for the Spree Commerce community. The extensions include Spree Wallet, Spree Favorite Products, Spree Bank Transfer and Spree Admin Roles. VinSol believe that the extensions would provide substantial return of investment to Spree Commerce Developers as well as Store Owners.

When contacted, Manik Juneja from VinSol said, “The open source model of Spree Commerce allows VinSol to offer tools and methodologies that have proven successful for us while also encouraging feedback and contributions from the Spree Commerce community.”

Spree Wallet extension would enable the option of digital wallet. Using the same, the customers are able to make a purchase using the money stored on the website for their account.

Spree Bank Transfer extension creates an additional payment method for the stores that allows customers to pay via bank transfers.

The Spree Favorite Products extension allows users to tag their favorite products. Customers can create a list of their favorite products which motivates them to come back to your website and place more orders.

The Spree Admin Roles extension will be particularly useful for stores that need to allow various store admins with restricted permissions.

VinSol confirmed that they tested the extensions before releasing it for the open source community. In addition, these extensions are compatible with 2.0.x version of Spree commerce, easy to use and can be further customized in accordance to ones requirements and preferences.

Akhil Bansal, Rails business unit head of the company added, “In more than eight years of building eCommerce application with the Ruby on Rails framework, we have learnt the ins and outs of the required development patterns and platform. Our goal is to spend our time on high-value features for our client’s stores, and our team has evolved several frameworks and utilities in Spree Commerce that allow us to be the utmost efficient with our development process.”

About VinSol

Based in New Delhi, India, VinSol is a Ruby on Rails development studio specializing in e-commerce, native mobile application and web development.  The company is also recognized as a Premier Spree Commerce Partner.

Contact Number: +1-415-839-0057

Email:  info at vinsol dot com

Website: http://vinsol.com/spree-commerce  

 

 

Drawing tool in iOS ( openGLES or UIBezierPath )

New to the problem of making a drawing/painting tool for an iOS application many developers get confused on using either OpenGLES or UIBeizerPath. Sometimes sample code on apples developer website GLPAINT  points many developers to use OpenGL Views for making paint layers for an application. A major issue with this that the developers do not understand is that OpenGL Views leave very heavy memory footprints and on devices like ipad1 having 24mb of memory to use per view , this can be a pain.

Trying to make a transparent openGL view which allows the user to paint on a transparent canvas with the background views visible is a problem I faced. Often crashes start occuring once you add multiple openGL views on a single view i.e adding multiple transparent paint canvases on a single view. These crashes are shown to be occuring because of the application receiving memory warning and the delegate “didReceiveMemoryWarning” being called.

After spending a lot of time with OpenGL , trying to figure out  a way to reduce the memory footprint (using instruments in Xcode), one gives up. The solution thus thought turns out that ipad1 cannot support multiple paint layers and the functionality has to be restricted for user to be able to add only a single layer per view, which indeed is not true.

Now comes the boon of UIBeizerPath class. This class introduced in iOS 4 SDK  makes it a lot easier for a developer to make multiple transparent paint canvases and add it to a single view without having a high memory footprint.

Steps on how to make use of UIBezierPath :

-       Add a new UIView class to the project , name it paintCanvasView.

-       Add two objects  in header file,

UIBezierPath *bPath;

UIColor *bColor;

-       Initialize these objects in the init method by overridding it.

self.backgroundColor=[UIColor clearColor]; //Any color

bPath=[[UIBezierPath alloc]init];

bPath.lineWidth=10;

bColor=[UIColor redColor]; //Any color

-       Override drawRect

[bColor setStroke];

[bPath strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];

-       Implement Touches Began

UITouch *bTouch=[[touches allObjects] objectAtIndex:0];

[bPath moveToPoint:[ bTouch locationInView:self]];

-       Implement Touches Moved

UITouch *bTouch=[[touches allObjects] objectAtIndex:0];

[bPath addLineToPoint:[bTouch locationInView:self]];

//We need to reset the display at each finger movement

[self setNeedsDisplay];

That is it.

You can use this PaintCanvasView Object in your code like any other UIView Object.  I hope this post would help some developers who are unaware of UIBeizerPath class and its uses. A further implementation of this is adding pattern to the rendered strokes. This pattern can be rendered on the strokes using pattern image , assuming pattern.png. Replacing the bColor with a pattern image in init method would do this trick.


bColor=[[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"pattern.png"]];

 

Update 16May’12

Adding infinite undo and Redo managers:

-   Add two arrays to paintCanvasView.h

NSMutableArray *pathArray;

NSMutableArray *bufferArray;

-   Add two methods to paintCanvasView.h


-(void)undoButtonClicked;

-(void)redoButtonClicked;

-   Allocate the arrays in init method


pathArray=[[NSMutableArray alloc]init];

bufferArray=[[NSMutableArray alloc]init];

-   Modify drawRect in paintCanvasView.m to draw from pathArray


- (void)drawRect:(CGRect)rect

{

[[UIColor redColor] setStroke];

for (UIBezierPath *_path in pathArray)

[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];

}

-   Add bPath to pathArray  in touchesBegan


UITouch *btouch=[[touches allObjects] objectAtIndex:0];

[bPath moveToPoint:[btouch locationInView:self]];

[pathArray addObject:bPath];

-   Define undoButtonClicked and redoButtonClicked to modify pathArray as desired.


-(void)undoButtonClicked

{

if([pathArray count]>0){

UIBezierPath *_path=[pathArray lastObject];

[bufferArray addObject:_path];

[pathArray removeLastObject];

[self setNeedsDisplay];

}

}

-(void)redoButtonClicked

{

if([bufferArray count]>0){

UIBezierPath *_path=[bufferArray lastObject];

[pathArray addObject:_path];

[bufferArray removeLastObject];

[self setNeedsDisplay];

}

}

That is it.

There is no rocket science to make an infinite undo manager for paint or sketch. One can simply maintain two arrays, buffer and path. By easily maintaining all items removed from path array in buffer array, redo functionality is achieved.