Sunday, February 20, 2011

Developing mobile apps using ROR

There are two ways of deploying an mobile app. Do you want it running completely on the phone or can it be a web app disguised as an iphone/android app?

For the native app solution we can use the Rhodes.Rhodes is an open source Ruby-based framework to rapidly build native apps for all major smartphone operating systems (iPhone, Windows Mobile, RIM, Symbian and Android). These are true native device applications (NOT mobile web apps) which work with synchronized local data and take advantage of device capabilities such as GPS, PIM contacts and calendar, camera, native mapping, push, barcode, signature capture, and Bluetooth.

Rhodes is the ONLY framework with: support for Model View Controller (other frameworks force you to put all business logic into the view as JavaScript), synchronized data (the price of entry for enterprise apps), support for ALL devices (Android and iPhone is not “crossplatform”), and a hosted build service (RhoHub – which changes the game for mobile app development entirely). Rhodes has many other major advantages over every other framework and underlying SDK, which can be summarized as modern development goodness for mobile apps.

For the 2nd option, web app disguised as a mobile app, I'd recommend Sencha Touch. Sencha has done an amazing job mimicking the look and feel of native iphone/android apps with their Javascript library. With this solution it would be just like any other web app though it's targeted for android and iphone via it's UI.

Monday, January 17, 2011

JCrop with Paper Clip Plugin

This posts will help you to integrate JCrop plugin along with the paper clip. (Suitable for Rails 3 migration)

In our application we have a create a user model that is set to use paper clip plugin.

User Model:

class User < ActiveRecord::Base has_attached_file :avatar, :styles => { :small => "100x100#", :large => "500x500>" }, :processors => [:cropper]



after_update :reprocess_avatar, :if => :cropping?

attr_accessor :crop_x, :crop_y, :crop_w, :crop_h

def cropping?
!crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
end


#To restore the original image after it is cropped. The size can vary.
def avatar_geometry(style = :original)
@geometry ||= {}
@geometry[style] ||= Paperclip::Geometry.from_file avatar.path(style)
end


# To reprocess the attached file if we’re cropping it.
private

def reprocess_avatar

avatar.reprocess!

end
end



User Controller:

def create

@user = User.new(params[:user])

if @user.save
flash[:notice] = 'User was successfully created.'
if params[:user][:avatar].blank?

redirect_to(@user)
else
render :action => 'cropping'
end
else
render :action => 'new'
end
end

# PUT /users/1
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
flash[:notice] = 'User was successfully updated.'

if params[:user][:avatar].blank?
redirect_to(@user)
else

render :action => 'cropping'
end
else
render :action => "edit"
end
end


Cropping.html file should have the following set


function update_crop(coords) {

var ratio = <%= @user.avatar_geometry(:original).width %> /
<%= @user.avatar_geometry(:large).width %>;
$('#crop_x').val(Math.floor(coords.x * ratio));
$('#crop_y').val(Math.floor(coords.y * ratio));

$('#crop_w').val(Math.floor(coords.w * ratio));
$('#crop_h').val(Math.floor(coords.h * ratio));
}





Avatar:
<%= image_tag @user.avatar.url(:large), :id => "cropbox" %>


<% form_for @user do |f| %>
<%= f.text_field :crop_x, :id => 'crop_x' %>

<%= f.text_field :crop_y, :id => 'crop_y' %>

<%= f.text_field :crop_w, :id => 'crop_w' %>

<%= f.text_field :crop_h, :id => 'crop_h' %>

<%= f.submit "Crop!" %>
<% end %>

<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>


Show.erb file can contain

Name:
<%=h @user.name %>


Avatar:
<%= image_tag @user.avatar.url(:large) %>
<%= image_tag @user.avatar.url(:small) %>


<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>


lib\paperclip_processors should have cropper.rb with the following code

module Paperclip
class Cropper < Thumbnail def transformation_command if crop_command crop_command + super.join(' ').sub(/ -crop \S+/, '').split(' ') # super returns an array like this: ["-resize", "100x", "-crop", "100x100+0+0", "+repage"] else super end end def crop_command target = @attachment.instance if target.cropping? ["-crop", "#{target.crop_w}x#{target.crop_h}+#{target.crop_x}+#{target.crop_y}"] end end end end Important steps to remember:

Move cropper.rb to the folder config\initializers
Remember to add crop_x, crop_y, Crop_w and crop_h to the list of your accessible attributes IF you have such a list:
attr_accessible :avatar, :crop_x, :crop_y, :crop_w, :crop_h

5. Added this line to my gemfile:
gem 'paperclip'

6. bundle install
Added jquery.Jcrop.min.js, jquery-1.4.3.min.js in public\javascripts folder

9. added Jcrop.gif and jquery.Jcrop.css in public\stylesheets folder

10. Added <%= yield(:head) %> in the head section in the application.html.erb file (needed for sample above)


http://asciicasts.com/episodes/182-cropping-images - This post helps you to understand in detail for Rails 2.3.8.

Wednesday, January 12, 2011