A video explains better than words!
Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts
Sunday, May 31, 2015
Lexical Scoping in Ruby
Labels:
lexical,
programming,
ruby,
scoping
Location:
Bergmannstraße, Berlin, Germany
Sunday, March 1, 2015
No Deployment Friday Grunt Plugin
My First Grunt Plugin which just a simple thing! Stops a deployment if the day is a Friday (any day you define as a No Deployment day actually).
Have a look at https://github.com/dinks/grunt-warn-friday.
Have a look at https://github.com/dinks/grunt-warn-friday.
Labels:
grunt,
node,
programming,
task
Location:
Bergmannstraße, Berlin, Germany
Tuesday, February 24, 2015
Nodejs on Heroku
After hours of effort and suffering, I was able to deploy a Node.js application to Heroku. This post reveals the effort that one has to make in deploying Node.js apps to Heroku.
I had been not using Heroku for some time now and wanted to host a test application on Heroku. This test application has a DB connection to MongoDb, uses the excellent Express Framework in the server side and React with Flux in the Frontend.
The first thing that one immediately notices is that its not that easy to add add-ons in Heroku anymore. They have a policy now with specifying a Credit Card / Payment Details even though I would only like to avail one Dyno. Previously I remember when I could add small add-ons to any Cedar Instance. That was so much cooler. I went on to look at OpenShift from RedHat, but that was a much bigger pain than I expected.
So back to Heroku. The first thing that I tried was to look at MongoLab for a simple Db hosting. They have a nice free developer plan and thats what I went for. The url for the DB went onto the ENV Config for the new Heroku App created. All fine until now.
Now came the actual building process. By default, if one does not specify the node and npm versions in the package.json file, it take the latest versions from semver.io. So for node it took 0.12.0 (https://semver.io/node/stable) and for npm 2.6.0 (https://semver.io/npm/stable).
I have many packages in my test application and it failed compiling for a package called node-sass@1.2.3. This was because of a known issue (https://github.com/sass/node-sass/issues/550) and was fixed with an upgrade of node-sass. But my dependency came from another package and could not upgrade it myself. So I had to tie the version for npm and node.
Once could do this using the engines option inside the package.json file.
I use wiredep to manage the bower dependencies for me. It injects the dependencies very gracefully and in a fully configurable way. I use font-awesome too in the test app, but it never could add fonts to the dist folder after build. I only way I could do this was via a copy grunt task.
The dependencies are added to the html file (according to the bower:css, bower:js comments) after the build. One normally would like to have the built version served on Heroku. My builds all go to the dist folder and therefore my script start looked like this
I had been not using Heroku for some time now and wanted to host a test application on Heroku. This test application has a DB connection to MongoDb, uses the excellent Express Framework in the server side and React with Flux in the Frontend.
The first thing that one immediately notices is that its not that easy to add add-ons in Heroku anymore. They have a policy now with specifying a Credit Card / Payment Details even though I would only like to avail one Dyno. Previously I remember when I could add small add-ons to any Cedar Instance. That was so much cooler. I went on to look at OpenShift from RedHat, but that was a much bigger pain than I expected.
So back to Heroku. The first thing that I tried was to look at MongoLab for a simple Db hosting. They have a nice free developer plan and thats what I went for. The url for the DB went onto the ENV Config for the new Heroku App created. All fine until now.
Now came the actual building process. By default, if one does not specify the node and npm versions in the package.json file, it take the latest versions from semver.io. So for node it took 0.12.0 (https://semver.io/node/stable) and for npm 2.6.0 (https://semver.io/npm/stable).
I have many packages in my test application and it failed compiling for a package called node-sass@1.2.3. This was because of a known issue (https://github.com/sass/node-sass/issues/550) and was fixed with an upgrade of node-sass. But my dependency came from another package and could not upgrade it myself. So I had to tie the version for npm and node.
Once could do this using the engines option inside the package.json file.
"engines": {
"node": "0.10.x",
"npm": "2.3.0"
}
The next problem was with the actual building via grunt.I use wiredep to manage the bower dependencies for me. It injects the dependencies very gracefully and in a fully configurable way. I use font-awesome too in the test app, but it never could add fonts to the dist folder after build. I only way I could do this was via a copy grunt task.
The dependencies are added to the html file (according to the bower:css, bower:js comments) after the build. One normally would like to have the built version served on Heroku. My builds all go to the dist folder and therefore my script start looked like this
"scripts": {
"start": "NODE_ENV=production node dist/server.js"
}
Once the fonts got copied over successfully, the pending issue was to execute the bower install and grunt build task. This could be done via a post-install hook available with npm. One has just to write something similar to the line below
"scripts": {
"start": "NODE_ENV=production node dist/server.js",
"test": "grunt test",
"postinstall": "bower install && grunt build"
}
The next problem that I faced was that bower and grunt were not a part of the dependencies list. Heroku by default has the setting NPM_CONFIG_PRODUCTION set to true. This means that the npm install only installs the items in the dependencies list and not the devDependencies list (logically). This meant that I either had to move all the grunt tasks and their deps to the dependencies list or set the variable to false. I preferred the latterheroku config:set NPM_CONFIG_PRODUCTION=false
Now the postinstall was failing. It was not able to find the commands bower and grunt. This was because the commands never got installed globally. To go around this I made a shell file called post_install.sh which has these commands with the expanded paths (according to http://gregtrowbridge.com/deploying-a-node-app-to-heroku-with-grunt-and-bower/)
#!/bin/bash
./node_modules/bower/bin/bower install
./node_modules/grunt-cli/bin/grunt build
and the call from the scripts look like
"scripts": {
"start": "NODE_ENV=production node dist/server.js",
"test": "grunt test",
"postinstall": "bash ./post_install.sh"
}
The grunt-cli was not a part of my original devDependencies list and it had to be added for the command to execute properly.Now the application ran fine! Phew!
Labels:
bower,
development,
express,
flux,
grunt,
heroku,
mongodb,
mongolab,
node,
node-sass,
npm,
programming,
react
Location:
Bergmannstraße 26, 10961 Berlin, Germany
Friday, December 19, 2014
A Developer Playlist
Labels:
development,
music,
playlist,
programming
Location:
Bergmannstraße, Berlin, Germany
Sunday, October 13, 2013
Fibonacci - Golden Ratio
In mathematics, the Fibonacci numbers or Fibonacci series or Fibonacci sequence are the numbers in the following integer sequence: 0, 1, 1,2, 3, 5, 8, 13, 21, 34, 55, 89, 144 ...
I have always done the one with recursion (or iteration). But mathematics says we could do it with the Golden Ratio ..
I have always done the one with recursion (or iteration). But mathematics says we could do it with the Golden Ratio ..
Labels:
fibonacci,
javascript,
programming
Location:
Bergmannstraße 26, 10961 Berlin, Germany
Saturday, September 21, 2013
Experimenting with Rails 4
I had some time this week and I had to try out the Rails 4 and Ruby 2. That's exactly what I did !
I did not try out Key based Cache Expirations or Etag stuff. But I did try out some Server Sent Events stuff. And it went pretty well.
I started out installing Ruby 2 with rvm (I use rvm and don't use to rbenv for some reason). I got through installing 2.0, but when I tried to use a specific gem_set for a test application, I got an error from Rubinius for some odd reason. It said that rbx was to be installed. Somehow it messed up the whole setup and I had to do away with gem_sets. I also had to remove the rbx* installation directory because it was bursting warnings to the console every time the rvm was set.
You must upgrade RVM :)
This benchmark is a great read for 2.0
I wrote the version to the .ruby-version file and that was the start of the project.
I wanted to do something which had some real time communication. Tic Tac Toe seemed to be a nice choice.
There was then this weird problem with sqlite3. It, for some odd reason, could not find the native binding of sqlite3. The path was correctly set but it just could not find the path. I had to spend some hours of debugging to find this out and a lot of googling !
The error was
This post saved me at last. Seems like we have to change the actual file of the gem to get this thing running.
In the case of rvm, the file would be under
and you will have to change the loading locations relative like
Server Side Events came next. I went through this excellent post on how to get started with SSE. I managed to add Redis pub/sub with SSE after looking through this post. And ultimately used some Thread Processing to get it less Non Blocking as per this post.
Another problem I had was with the servers. I started with Unicorn which was a bad choice. Unicorn kills connections because it is meant for fast processing. For persistent connections, we need to have Puma or Rainbows!
I started using Puma but I did the mistake of not putting
But that did not solve my problems. Puma constantly gave me errors like
which is not good. It never called the ensure block (don't know why) and I seriously doubt the sockets to be open :|
Thats when I tried Rainbows! I added the rainbow.rb file for server config and started the server. It worked great for me !
I also understood that attr_accesible is no more for rails and its all about Strong Parameters.
I tried adding rails-api to the project (this was my first time). It was only after some time that I realized that the stack for rails-api removes the Rack for Session handling because it aims for the Processing to be as less as possible
I was working with an existing Rails application and I did not want this feature. I tried adding
I had to add the particular require for the api for this to work in the Gemfile
I wanted to try my bit with the state machine and I managed to write this inside Concerns.
The POC is still incomplete, but I loved doing this after a long time !
I did not try out Key based Cache Expirations or Etag stuff. But I did try out some Server Sent Events stuff. And it went pretty well.
I started out installing Ruby 2 with rvm (I use rvm and don't use to rbenv for some reason). I got through installing 2.0, but when I tried to use a specific gem_set for a test application, I got an error from Rubinius for some odd reason. It said that rbx was to be installed. Somehow it messed up the whole setup and I had to do away with gem_sets. I also had to remove the rbx* installation directory because it was bursting warnings to the console every time the rvm was set.
You must upgrade RVM :)
This benchmark is a great read for 2.0
I wrote the version to the .ruby-version file and that was the start of the project.
I wanted to do something which had some real time communication. Tic Tac Toe seemed to be a nice choice.
There was then this weird problem with sqlite3. It, for some odd reason, could not find the native binding of sqlite3. The path was correctly set but it just could not find the path. I had to spend some hours of debugging to find this out and a lot of googling !
The error was
/usr/local/share/gems/gems/sqlite3-1.3.7/lib/sqlite3.rb:6:in `require': cannot load such file -- sqlite3/sqlite3_ruby (LoadError)This post saved me at last. Seems like we have to change the actual file of the gem to get this thing running.
In the case of rvm, the file would be under
~/.rvm/gems/ruby-2.0.0-p247/gems/sqlite3-1.3.8/lib/sqlite3.rb
and you will have to change the loading locations relative like
~/.rvm/gems/ruby-2.0.0-p247/gems/sqlite3-X-X-X/ext/sqlite3/sqlite3_native
Once this is done, rails finds it and loads it. This, I think, is NOT good for a Continous Integration Server.Server Side Events came next. I went through this excellent post on how to get started with SSE. I managed to add Redis pub/sub with SSE after looking through this post. And ultimately used some Thread Processing to get it less Non Blocking as per this post.
Another problem I had was with the servers. I started with Unicorn which was a bad choice. Unicorn kills connections because it is meant for fast processing. For persistent connections, we need to have Puma or Rainbows!
I started using Puma but I did the mistake of not putting
config.preload_frameworks = true config.allow_concurrency = true
in the application.rb file. Only one request was permitted because of this flaw. This is to be removed later (I have no idea why this is not default ?).But that did not solve my problems. Puma constantly gave me errors like
ThreadError: Attempt to unlock a mutex which is locked by another thread
which is not good. It never called the ensure block (don't know why) and I seriously doubt the sockets to be open :|
Thats when I tried Rainbows! I added the rainbow.rb file for server config and started the server. It worked great for me !
I also understood that attr_accesible is no more for rails and its all about Strong Parameters.
I tried adding rails-api to the project (this was my first time). It was only after some time that I realized that the stack for rails-api removes the Rack for Session handling because it aims for the Processing to be as less as possible
Rack::Session::Cookie
I was working with an existing Rails application and I did not want this feature. I tried adding
config.api_only = false
to the application.rb file. But that did not help me.I had to add the particular require for the api for this to work in the Gemfile
gem 'rails-api', require: 'rails-api/action_controller/api' I wanted to try my bit with the state machine and I managed to write this inside Concerns.
The POC is still incomplete, but I loved doing this after a long time !
Wednesday, April 24, 2013
Content Security Policy
I had not heard of this before a couple of days. I was trying to run something from the firebug console on github and it gave me an error of this kind.
For Chrome,
The header is
And the value looks like
For Firefox,
The header is
And the value looks like
Error: call to eval() blocked by CSP
Nothing ran. And even more confusingly, similar errors were thrown on page load.
It seems like CSP is a great advancement in reducing the number of XSS (Cross Side Scripting) attacks. By adding a header to the response, we add a list of white listed sites where the scripts are allowed to run and the rest encounter errors similar to the one seen before. Naice
The header is
X-WebKit-CSPAnd the value looks like
"default-src 'self'; img-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; report-uri /Home/Report"For Firefox,
The header is
X-Content-Security-PolicyAnd the value looks like
"default-src 'self'; img-src *; script-src 'self'; style-src 'self' 'unsafe-inline'; report-uri /Home/Report"
Labels:
csp,
headers,
programming,
web
Location:
Bergmannstraße 26, 10961 Berlin, Germany
Friday, March 15, 2013
Less Caching
We came across this unusual problem when developing. So for starters, there is a Gem that we use and a test application reside in the test folder of the Gem. The Gem uses only Javascript in the app/assets folder and has a minimal Ruby code.
The Gem uses Bootstrap's less version to set the CSS. We use the mixins by Bootstrap and overwrite variables and stuff. The Gem still used SASS and we felt a little odd with writing mixed CSS. Therefore we moved all the stuff to less files and put it all in assets/stylesheets. Nice and organized.
Now we had the problem. We made a change to the less files and the application did not load them. We had put all our imports in a main file and any change to the main file reflected in the test app. but not if the change were done inside the individual imports.
We wanted to analyze if the problem was with Sprockets or with less-rails. After some probe and hunt we concluded that the problem indeed was with less-rails. The Gem caches the imports which prevent any compilation after the import to the base file (first level).
I tried adding options like
inside the environment files, but alas! no change what so ever.
So we had to do the inevitable. Look at files and trigger a restart and cache clear.
The process was to be something like :
2 Guard plugins were used for this :
guard-process => To run the rake process
guard-pow => To restart Pow
The file looked something like this
The guard command needed to run with
-w because we were looking at a change from another directory
-p for polling
-i for no interactions
phew..
The Gem uses Bootstrap's less version to set the CSS. We use the mixins by Bootstrap and overwrite variables and stuff. The Gem still used SASS and we felt a little odd with writing mixed CSS. Therefore we moved all the stuff to less files and put it all in assets/stylesheets. Nice and organized.
Now we had the problem. We made a change to the less files and the application did not load them. We had put all our imports in a main file and any change to the main file reflected in the test app. but not if the change were done inside the individual imports.
We wanted to analyze if the problem was with Sprockets or with less-rails. After some probe and hunt we concluded that the problem indeed was with less-rails. The Gem caches the imports which prevent any compilation after the import to the base file (first level).
I tried adding options like
config.consider_all_requests_local = true
config.action_controller.perform_caching = false inside the environment files, but alas! no change what so ever.
So we had to do the inevitable. Look at files and trigger a restart and cache clear.
The process was to be something like :
if Change? rake tmp:clear powder restart (or touch tmp/restart) [we use pow]Guard was perfect for this.2 Guard plugins were used for this :
guard-process => To run the rake process
guard-pow => To restart Pow
The file looked something like this
# RUN bundle exec guard -p -i -w ../../ guard 'pow' do watch(%r{app/assets/stylesheets/**/.*\.less$}) end
guard 'process', :name => 'ClearCache', :command => 'rake tmp:clear' do watch(%r{app/assets/stylesheets/**/.*\.less$}) end The guard command needed to run with
-w because we were looking at a change from another directory
-p for polling
-i for no interactions
phew..
Labels:
assets,
css,
javascript,
less,
programming,
rails,
ruby,
sass
Location:
Bergmannstraße 58, 10961 Berlin, Germany
Monday, November 12, 2012
Simply Complex
Well .. I was reading through the Pragmatic Programmer's Guide and saw this piece of code.
Essentially the problem is to check if the value exists for the a variable. If not then do some calculations and set the instance variable. Then return that variable for all further calls to the instance method.
This variation does something unique.
First it makes an alias for the method which checks the if .. else. It redefines the name of the method to be __278626__ . The number signifies the identification number assigned for the symbol. This is done inside the module eval which adds stuff to the class which calls the once method like so.
The method is first declared with args and blocks. Then if you notice there is a self method declared too. The first fact is that we dont care whats in the instance method code block unless it is executed. For it to be executed, it should be called from an instance. Therefore when the method does get called, it is redefined in the scope of the object, ie the same method is redefined to return an instance variable. The call continues then to set the instance variable which is to be returned by the redefined method.
phew.
def ExampleDate.once(*ids) for id in ids module_eval <<-"end_eval" alias_method :__#{id.to_i}__, #{id.inspect} def #{id.id2name}(*args, &block) def self.#{id.id2name}(*args, &block) @__#{id.to_i}__ end @__#{id.to_i}__ = __#{id.to_i}__(*args, &block) end end_eval end end
The guide said "Note that
this redefinition uses the fact that methods may contain nested
singleton method definitions, a clever trick." ..Essentially the problem is to check if the value exists for the a variable. If not then do some calculations and set the instance variable. Then return that variable for all further calls to the instance method.
This variation does something unique.
First it makes an alias for the method which checks the if .. else. It redefines the name of the method to be __278626__ . The number signifies the identification number assigned for the symbol. This is done inside the module eval which adds stuff to the class which calls the once method like so.
once :abc, :def
The method is first declared with args and blocks. Then if you notice there is a self method declared too. The first fact is that we dont care whats in the instance method code block unless it is executed. For it to be executed, it should be called from an instance. Therefore when the method does get called, it is redefined in the scope of the object, ie the same method is redefined to return an instance variable. The call continues then to set the instance variable which is to be returned by the redefined method.
phew.
Labels:
programming,
ruby
Location:
Bergmannstraße 26, 10961 Berlin, Germany
Wednesday, August 8, 2012
Compiling Ruby 1.9.2 with OS X 10.7
I had to setup a machine which ran 10.7 with Ruby 1.9.2 because the application ran on this version. It was a rails application of version 3.1.
I tried to get the machine set up with rbenv which went smooth.
I tried to do a
Which did not go well at all.
I got errors like
Which essential means that I needed to update the readline library to this error out of the way. I started out by downloading the readline version 6.1 manually and installing but that failed miserably.
Then I read this which saved me a lot of time. It essentially says to install readline via rvm. rvm was already installed in the system and readline got installed by the command.
Be sure to install the ruby version using the --with-readline-dir option. Like so
Now when you try to install with this line, you might get it installed or you might get some errors like
Well, this means that you might have a wrong dylib file version on the machine.
The first this we need to look at now is whether we have XCode. If you have XCode and the version is 4.2 then you will have to check for this file in
Try to execute a file command on this
Now running the rvm install works great !
Kudos !!!
References:
http://hello.keewooi.com/ruby-1-9-3-preview-1-available-now/
http://forums.pragprog.com/forums/148/topics/9975
http://geekyninja.blogspot.de/2010/12/installing-ruby-192-with-rvm.html
http://stackoverflow.com/questions/5426892/trouble-installing-ruby-1-9-2-with-rvm-mac-os-x
http://stackoverflow.com/questions/3703792/ld-symbols-not-found-when-linking
http://stackoverflow.com/questions/7962550/error-installing-ruby-1-9-3
https://rvm.io/packages/readline/
http://stackoverflow.com/questions/8675194/error-installing-1-9-3-with-rvm-on-lion
I tried to get the machine set up with rbenv which went smooth.
I tried to do a
rbenv install 1.9.2-p180
Which did not go well at all.
I got errors like
/usr/bin/gcc-4.2 -dynamic -bundle -o ../../../.ext/x86_64-darwin11.3.0/racc/cparse.bundle cparse.o -L. -L../../.. -L/Users/jasonvdm/.rvm/usr/lib -L. -L/usr/local/lib -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -Wl,-flat_namespace -lruby.1.9.1 -lpthread -ldl -lobjc
compiling readline/usr/bin/gcc-4.2 -I. -I../../.ext/include/x86_64-darwin11.3.0 -I../.././include -I../.././ext/readline -DRUBY_EXTCONF_H=\"extconf.h\" -I/Users/jasonvdm/.rvm/usr/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -fno-common -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long -fno-common -pipe -o readline.o -c readline.c
readline.c: In function ‘username_completion_proc_call’:
readline.c:1386: error: ‘username_completion_function’ undeclared (first use in this function)
readline.c:1386: error: (Each undeclared identifier is reported only once
readline.c:1386: error: for each function it appears in.)
make[1]: *** [readline.o] Error 1
make: *** [mkmain.sh] Error 1
Which essential means that I needed to update the readline library to this error out of the way. I started out by downloading the readline version 6.1 manually and installing but that failed miserably.
curl -O ftp://ftp.gnu.org/gnu/readline/readline-6.1.tar.gz
tar xzvf readline-6.1.tar.gz
cd readline-6.1
./configure --prefix=/usr/local
make
sudo make install
Then I read this which saved me a lot of time. It essentially says to install readline via rvm. rvm was already installed in the system and readline got installed by the command.
rvm pkg install readline
Be sure to install the ruby version using the --with-readline-dir option. Like so
rvm reinstall 1.9.2 --with-readline-dir=$rvm_path/usr
Now when you try to install with this line, you might get it installed or you might get some errors like
ld: in /usr/local/lib/libiconv.2.dylib, missing required architecture x86_64 in file
collect2: ld returned 1 exit status
make[1]: *** [../../.ext/x86_64-darwin10.5.0/tcltklib.bundle] Error 1
make: *** [mkmain.sh] Error 1
Well, this means that you might have a wrong dylib file version on the machine.
The first this we need to look at now is whether we have XCode. If you have XCode and the version is 4.2 then you will have to check for this file in
/usr/lib/libiconv.2.dylibTry to execute a file command on this
file /usr/lib/libiconv.2.dylib /usr/lib/libiconv.2.dylib: Mach-O universal binary with 3 architectures/usr/lib/libiconv.2.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64 /usr/lib/libiconv.2.dylib (for architecture i386): Mach-O dynamically linked shared library i386 /usr/lib/libiconv.2.dylib (for architecture ppc7400): Mach-O dynamically linked shared library ppc
Find the x68_64 and you are in luck !
Just remove the old dylib and link the new one like so :
rm /usr/local/lib/libiconv.2.dylib
ln -s /usr/lib/libiconv.2.dylib /usr/local/lib/libiconv.2.dylibKudos !!!
References:
http://hello.keewooi.com/ruby-1-9-3-preview-1-available-now/
http://forums.pragprog.com/forums/148/topics/9975
http://geekyninja.blogspot.de/2010/12/installing-ruby-192-with-rvm.html
http://stackoverflow.com/questions/5426892/trouble-installing-ruby-1-9-2-with-rvm-mac-os-x
http://stackoverflow.com/questions/3703792/ld-symbols-not-found-when-linking
http://stackoverflow.com/questions/7962550/error-installing-ruby-1-9-3
https://rvm.io/packages/readline/
http://stackoverflow.com/questions/8675194/error-installing-1-9-3-with-rvm-on-lion
Labels:
1.9.2-p180,
library,
osx,
programming,
rails,
rbenv,
ruby,
rvm
Location:
Bergmannstraße, 10961 Berlin, Germany
Wednesday, December 28, 2011
Image Cropping With Rails 3
I was looking at some options for the Image Cropping functionality with Rails 3 and got many great solutions on the net. This Rails Cast is the best place to start if you have the images stored as local. If you have it as s3 storage there are some changes you need to make.
My main haml file has these contents -
When on calls the popup, one should call the code for the Jcrop method
My aspect ratio setting is with respect to the configurations I did for the has_attached_file :avatar.
The thing you will have to do specifically for s3 is in the avatar_geometry method.
Inside the model.
I'm having issues with the cropper processor and its not cropping fine. Will have to fix that. This is the Cropper
My main haml file has these contents -
#cropperpopup.lpopup.x %a.ccloser %p.large
Image Cropper .cropper = image_tag @user.avatar.url(:medium), :id => :cropbox = form_for @user, :html => {:class => 'edit_user_two'} do |f| - for attrbt in [:crop_x, :crop_y, :crop_w, :crop_h] = f.text_field attrbt, :id => attrbt, :class => :coordinate = f.submit 'Crop'
When on calls the popup, one should call the code for the Jcrop method
$('img#cropbox').Jcrop({ onChange: update_crop, onSelect: update_crop, setSelect: [0, 0, 168, 202], aspectRatio: (168/202) });
My aspect ratio setting is with respect to the configurations I did for the has_attached_file :avatar.
The thing you will have to do specifically for s3 is in the avatar_geometry method.
def cropping? !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
end def avatar_geometry(style = :medium) @geometry ||= {} path = (avatar.options[:storage]==:s3) ? avatar.url(style).split(' ').join('%20') : avatar.path(style) @geometry[style] ||= Paperclip::Geometry.from_file(path) end
Inside the model.
I'm having issues with the cropper processor and its not cropping fine. Will have to fix that. This is the Cropper
module Paperclip class Cropper < Thumbnail def transformation_command if crop_command r = super if r.class == Array r = r.join(' ') end crop_command + r.sub(/ -crop \S+/, '').sub(/-resize \S+/, '') else super end end def crop_command target = @attachment.instance if target.cropping? "-resize \"168x202\" -crop #{target.crop_w}x#{target.crop_h}+#{target.crop_x}+#{target.crop_y} " end end end end
Labels:
crop,
javascript,
paperclip,
programming,
rails,
ruby
Saturday, July 30, 2011
Rails Again
I started digging into Rails again. The stuff I started to do was quite straight forward. The DB access, change routes etc. But the things I want to talk about was Haml and Coffeescript.
Haml :
Wow ! Just Wow !
I always wanted a templating engine which I could use to write easy code. Writing HTML was never so fun. The syntax might seem to be complex but trust me it gets to be fun.
Just add a
config.generators do |g|
g.template_engine :haml
end
in application.rb after adding the haml gem and the haml-rails gem.
Coffeescript :
This is an intermediate compiler which converts a file into javascript. Eliminate your braces and semicolons with coffeescript. The compiled output is readable and pretty-printed, passes through JavaScript Lint without warnings, will work in every JavaScript implementation, and tends to run as fast or faster than the equivalent handwritten JavaScript.
You will have to install barista, bisttro_car, coffeescript and coffeescript-script gems. I found an article which would be useful here.
Have Fun coding !
Haml :
Wow ! Just Wow !
I always wanted a templating engine which I could use to write easy code. Writing HTML was never so fun. The syntax might seem to be complex but trust me it gets to be fun.
Just add a
config.generators do |g|
g.template_engine :haml
end
in application.rb after adding the haml gem and the haml-rails gem.
Coffeescript :
This is an intermediate compiler which converts a file into javascript. Eliminate your braces and semicolons with coffeescript. The compiled output is readable and pretty-printed, passes through JavaScript Lint without warnings, will work in every JavaScript implementation, and tends to run as fast or faster than the equivalent handwritten JavaScript.
You will have to install barista, bisttro_car, coffeescript and coffeescript-script gems. I found an article which would be useful here.
Have Fun coding !
Labels:
coffeescript,
haml,
programming,
rails,
ruby
Tuesday, January 18, 2011
Delegation Drag
Its been some time since I have written something and its simply because there is not much to write about. But now I have something :P
The application that I'm working on currently use a lot of drag and drop features for many objects. The number of these objects in the UI varies from user to user. The code has been written to create a DragDrop object for each of these UI elements. Therefore if you were supposed to have many elements, the page would stall thus making actions damn slow. I was told to improve performance by changing this to a delegation model.
The delegation model would find the event attachments done to the main container and not the individual elements. The event would bubble up to the container which would be handled by the handler written for this. The container would be specified as well as the css selector for the elements which would have the drag and drop feature.
To make this work was pretty easy with YUI3. A delegation class was present which gave me the initial stuff to get started. But then came problems.
The application would have different drop targets at different points of time. An ajax action would change the UI which would then have different drop targets. Now if you were using delegation, you need to specify the drop objects in the constructor. I did not find a way where I could add/remove drop targets dynamically. This is when I saw a post from an author who did a work around for this. He had created the drop targets inside the mouseover action of the drag, thus scoping it :). I put these drop objects inside a scoped variable so that when the UI changed, I reset this variable.
I also required there be different drag objects. Those which went to specific drop targets. I started specifying the 'container' parameter instead of the 'cont' parameter and that solved some issues. To have another set of delegates, I just took the above code and changed the 'container' parameter to get the correct set of draggables. I also change the groups parameter bit that did not seem to make a difference ...
References
http://yuilibrary.com/forum/viewtopic.php?p=17845
http://developer.yahoo.com/yui/3/dd/
http://developer.yahoo.com/yui/3/examples/dd/
The application that I'm working on currently use a lot of drag and drop features for many objects. The number of these objects in the UI varies from user to user. The code has been written to create a DragDrop object for each of these UI elements. Therefore if you were supposed to have many elements, the page would stall thus making actions damn slow. I was told to improve performance by changing this to a delegation model.
The delegation model would find the event attachments done to the main container and not the individual elements. The event would bubble up to the container which would be handled by the handler written for this. The container would be specified as well as the css selector for the elements which would have the drag and drop feature.
To make this work was pretty easy with YUI3. A delegation class was present which gave me the initial stuff to get started. But then came problems.
The application would have different drop targets at different points of time. An ajax action would change the UI which would then have different drop targets. Now if you were using delegation, you need to specify the drop objects in the constructor. I did not find a way where I could add/remove drop targets dynamically. This is when I saw a post from an author who did a work around for this. He had created the drop targets inside the mouseover action of the drag, thus scoping it :). I put these drop objects inside a scoped variable so that when the UI changed, I reset this variable.
YUI().use('dd-delegate', 'dd-constrain', 'dd-proxy', 'dd-drop', function(Y) {
var del = new Y.DD.Delegate({
container: '#container1',
nodes: '.appt',
target: true,
dragConfig: { groups: ['default']}
});
del.dd.plug(Y.Plugin.DDConstrained, {
constrain2node: '#container1'
});
del.dd.plug(Y.Plugin.DDProxy, {
moveOnEnd: false,
cloneNode: false
});
del.on('drag:mouseDown', function(e){
if(_self.createdDrops.length ==0){
var drops = Y.all('td.day');
Y.each(drops, function(v, k) {
var tar = new Y.DD.Drop({
node: v,
groups: ['default']
});
_self.createdDrops.push(tar);
});
}
});
del.on('drag:start', function(e) {
_self.delDragStart(e, Y);
});
del.on('drag:end', function(e) {
_self.delDragStop(e);
});
del.on('drag:drophit', function(e) {
_self.delDragHit(e,Y);
});
del.on('drag:over', function(e){
_self.delDragOver(e);
});
del.on('drag:exit', function(e){
_self.delDragExit(e);
});
_self.del = del;
});
I also required there be different drag objects. Those which went to specific drop targets. I started specifying the 'container' parameter instead of the 'cont' parameter and that solved some issues. To have another set of delegates, I just took the above code and changed the 'container' parameter to get the correct set of draggables. I also change the groups parameter bit that did not seem to make a difference ...
References
http://yuilibrary.com/forum/viewtopic.php?p=17845
http://developer.yahoo.com/yui/3/dd/
http://developer.yahoo.com/yui/3/examples/dd/
Monday, August 30, 2010
Minimum diff between dates of a week
Problem statement:
The UI contains a set of checkboxes. Each signifies a day. The list starts from a Sunday and goes upto a Saturday. The task is to find out the minimum difference between the selected days.
Eg:
If Mon, Thur and Fri were selected, then the minimum days between the selected days would be 1 (Thu and Fri).
Take into consideration that if Sun and Sat were selected, the difference would be 1. :)
The UI contains a set of checkboxes. Each signifies a day. The list starts from a Sunday and goes upto a Saturday. The task is to find out the minimum difference between the selected days.
Eg:
If Mon, Thur and Fri were selected, then the minimum days between the selected days would be 1 (Thu and Fri).
Take into consideration that if Sun and Sat were selected, the difference would be 1. :)
Labels:
javascript,
programming
Thursday, June 10, 2010
Javascript Debug
I started working with Javascript some years back and at those times to get hold of a js issue was hard. Then came firebug. The tool analyzed the js stuff, gave a console where we could assign new Javascript variables, call functions etc. The Dom tab gave the variables currently declared in the DOM so that analyzing a variable got easier. The Net tab gave all the access made by the page. This included the images, css, js files and even XHR ! Debugging a script became easier with the Script tab.
But that was not enough, as for all things. YSlow came along which gave you a precise idea of the stuff that made your web page slow. Page Speed from Google also gave a great idea of the same. Cookies was introduced which let you view a cookie and modify it.
The debugging in IE was also some thing that developers looked forward to. Developer Bar gave many of the options that Firebug gave. Companion JS is a great tool that let you debug Javascript. Fiddler let you act as a proxy between IE and the server so that you could change a request to fetch a file (js/css) from the local disk.
Smush.it is something that I got to know recently which gives you a compressed version of images thus increasing the response time for a web site. Javascript compression and obfuscation are techniques that we use every time for the js response time reduction.
Many stuff to keep in mind and many to implement to create a great web app.
But that was not enough, as for all things. YSlow came along which gave you a precise idea of the stuff that made your web page slow. Page Speed from Google also gave a great idea of the same. Cookies was introduced which let you view a cookie and modify it.
The debugging in IE was also some thing that developers looked forward to. Developer Bar gave many of the options that Firebug gave. Companion JS is a great tool that let you debug Javascript. Fiddler let you act as a proxy between IE and the server so that you could change a request to fetch a file (js/css) from the local disk.
Smush.it is something that I got to know recently which gives you a compressed version of images thus increasing the response time for a web site. Javascript compression and obfuscation are techniques that we use every time for the js response time reduction.
Many stuff to keep in mind and many to implement to create a great web app.
Labels:
javascript,
programming,
yahoo
Wednesday, May 19, 2010
Dependencies
The last two weeks were hectic. Deployment and making the sufficient stuff necessary for deployment is tough. I tend to really appreciate those people who stay the whole night resolving production issues. May it be Garbage Collection issues with the server/java or CPU spikes. These seemed to be problems which took most of the time.
Packaging is also a problem not to be taken lightly. Resolving the dependencies and making sure that no major update goes unnoticed is a tedious job. Just to look into the set of packages is boring and one tends to lose patience quite frequently. I still think that having test packages and using them on a QA machine makes sense only if the QA is not meant to replicate the actual production instance. If they do, then the packages that must be installed must be stable packages. YUM is be given great credit for the fantastic work they do.
Packaging is also a problem not to be taken lightly. Resolving the dependencies and making sure that no major update goes unnoticed is a tedious job. Just to look into the set of packages is boring and one tends to lose patience quite frequently. I still think that having test packages and using them on a QA machine makes sense only if the QA is not meant to replicate the actual production instance. If they do, then the packages that must be installed must be stable packages. YUM is be given great credit for the fantastic work they do.
Labels:
packaging,
programming,
yahoo
Location:
Bengaluru, Karnataka, India
Wednesday, March 3, 2010
JS Snippets
function myFunc(param){
if (!myFunc.cache) {
myFunc.cache = {};
}
if (!myFunc.cache[param]) {
var result = {}; // ...
myFunc.cache[param] = result;
}
return myFunc.cache[param];
}
function lazy() {
var result = 2 + 2;
lazy = function() {
return result;
};
return lazy();
}
lazy(); // 4
lazy(); // 4
Tuesday, February 23, 2010
The VIM
:sp will split the Vim window horizontally. Can be written out entirely as :split .:vsp will split the Vim window vertically. Can be written out as :vsplit .Ctrl-w Ctrl-w moves between Vim viewports.Ctrl-w j moves one viewport down.Ctrl-w k moves one viewport up.Ctrl-w h moves one viewport to the left.Ctrl-w l moves one viewport to the right.Ctrl-w = tells Vim to resize viewports to be of equal size.Ctrl-w - reduce active viewport by one line.Ctrl-w + increase active viewport by one line.Ctrl-w q will close the active window.Ctrl-w r will rotate windows to the right.Ctrl-w R will rotate windows to the left.
Class Path !?
String myResource = .... ;
InputStream is = getClass().getResourceAsStream(myResource);
System.out.println (myResource + " is " + (is==null?"not":"") + " on the classpath");
Thursday, February 18, 2010
Cook me up
This post tries to focus on the topic of Cooking or escaping in Web Applications.
The process of stripping/changing/modifying user input so that it avoids attacks like XSS is cooking. There are many ways to do it. One way is to strip off every input that the user provides. Let it be tags like <script> or <img> . The quotes are also removed so that javascript errors are avoided.
The other way would be to take in what ever input the user provides and store it as it is in the database. The only place you would cook it would be in the UI. Escape/change what ever stuff you feel would cause your app to succumb to XSS and then display. This, I feel, is the right way to do it.
Many applications that you see now may also have a JSON part to it. It might also be the case that the application is accessed by many other applications and these apps use the data. Not cooking this data is kinda buggy and cooking it defeats the purpose if this data is shown in a simple textarea. So I would rather let javascript cook this using the functions available.
update: The buzz has a problem with this. My blog title is << Dinks >> and look how it came up in buzz ..
update: The buzz has a problem with this. My blog title is << Dinks >> and look how it came up in buzz ..
Subscribe to:
Posts (Atom)


