‘Professional Ruby Collection’ Review

Ξ April 16th, 2008 | → 0 Comments | ∇ Uncategorized |

So I’m at the Ruby meetup a month ago in San Francisco, and Bosco, the organizer does a drawing to win a copy of “Professional Ruby Collection”. I noticed there was a CD inside, and thought perhaps they were screencasts? if they were, that’d be sweet! Well what do ya know, I win it, and excited as hell.

The CD included contain 5 PDF ebooks, not screencasts : T, but were they worth it! I wouldn’t recommend this for anyone trying to get into Rails, but definitely for those that want to relieve from the headache of tackling and clarifying the many areas of Rails, that all seem to be included in this collection.

Mongrel : Surviving, Deploying, and Extending Your Ruby Application by the creator of Mongrel Zed Shaw, and also includes Matt Pelletier.

Rails Plugins: Extending Rails Beyond the Core by James Adam

Rails Routing by David A Black. Also included is a zipped up example of a RESTful auction app. D Black seems to be good with giving us the app which he writes about ( his music site in Ruby for Rails ).

Rails Refactoring to Reources: Using CRUD and REST in Your Rails Application by Trotter Cashion.

and Rubyism in Rails by Jacob Harris.

The ‘Bonus Publication’ is an approximately 200 page book with extracts from various other ruby books. I already own some of these books, including The Rails Way by Obie Fernandez, but having his section in this other book helps when I wanna grab something kinda thin to read because, say, I know I’m going to wait in the DMV line forever.

This whole collection thing reminds me of either a music CD compilation or a conference. It’s kind of the best of the best, and I don’t think I’ve ever seen any other publication done like this out there (bare in mind I am a newbie). When reading, you may feel like you’ve just gone to Ruby Conference, with such a diversified array of topics on the world of RoR and Ruby. Great for folks with ADD - great for me. All for about $40 bucks, It’s an essential for intermediate or advanced coder that what’s to tighten up their knowledge, but an essential reference for those things like REST and late night, back aching stress from deployment.

 

Scriptaculous Slider for Rails 2.0

Ξ April 15th, 2008 | → 0 Comments | ∇ programming |

This will be your new slider js file: (slider.js v1.8.1)

// script.aculo.us slider.js v1.8.1, Thu Jan 03 22:07:12 -0500 2008

// Copyright (c) 2005-2007 Marty Haught, Thomas Fuchs
//
// See http://script.aculo.us for more info
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// “Software”), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

if (!Control) var Control = { };

// options:
//  axis: ‘vertical’, or ‘horizontal’ (default)
//
// callbacks:
//  onChange(value)
//  onSlide(value)
Control.Slider = Class.create({
initialize: function(handle, track, options) {
var slider = this;

if (Object.isArray(handle)) {
this.handles = handle.collect( function(e) { return $(e) });
} else {
this.handles = [$(handle)];
}

this.track   = $(track);
this.options = options || { };

this.axis      = this.options.axis || ‘horizontal’;
this.increment = this.options.increment || 1;
this.step      = parseInt(this.options.step || ‘1′);
this.range     = this.options.range || $R(0,1);

this.value     = 0; // assure backwards compat
this.values    = this.handles.map( function() { return 0 });
this.spans     = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
this.options.startSpan = $(this.options.startSpan || null);
this.options.endSpan   = $(this.options.endSpan || null);

this.restricted = this.options.restricted || false;

this.maximum   = this.options.maximum || this.range.end;
this.minimum   = this.options.minimum || this.range.start;

// Will be used to align the handle onto the track, if necessary
this.alignX = parseInt(this.options.alignX || ‘0′);
this.alignY = parseInt(this.options.alignY || ‘0′);

this.trackLength = this.maximumOffset() - this.minimumOffset();

this.handleLength = this.isVertical() ? (this.handles[0].offsetHeight != 0 ? this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,”")) : (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth : this.handles[0].style.width.replace(/px$/,”"));

this.active   = false;
this.dragging = false;
this.disabled = false;

if (this.options.disabled) this.setDisabled();

// Allowed values array
this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
if (this.allowedValues) {
this.minimum = this.allowedValues.min();
this.maximum = this.allowedValues.max();
}

this.eventMouseDown = this.startDrag.bindAsEventListener(this);
this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
this.eventMouseMove = this.update.bindAsEventListener(this);

// Initialize handles in reverse (make sure first handle is active)
this.handles.each( function(h,i) {
i = slider.handles.length-1-i;
slider.setValue(parseFloat(
(Object.isArray(slider.options.sliderValue) ?
slider.options.sliderValue[i] : slider.options.sliderValue) ||
slider.range.start), i);
h.makePositioned().observe(”mousedown”, slider.eventMouseDown);
});

this.track.observe(”mousedown”, this.eventMouseDown);
document.observe(”mouseup”, this.eventMouseUp);
document.observe(”mousemove”, this.eventMouseMove);

this.initialized = true;
},
dispose: function() {
var slider = this;
Event.stopObserving(this.track, “mousedown”, this.eventMouseDown);
Event.stopObserving(document, “mouseup”, this.eventMouseUp);
Event.stopObserving(document, “mousemove”, this.eventMouseMove);
this.handles.each( function(h) {
Event.stopObserving(h, “mousedown”, slider.eventMouseDown);
});
},
setDisabled: function(){
this.disabled = true;
},
setEnabled: function(){
this.disabled = false;
},
getNearestValue: function(value){
if (this.allowedValues){
if (value >= this.allowedValues.max()) return(this.allowedValues.max());
if (value <= this.allowedValues.min()) return(this.allowedValues.min());

var offset = Math.abs(this.allowedValues[0] - value);
var newValue = this.allowedValues[0];
this.allowedValues.each( function(v) {
var currentOffset = Math.abs(v - value);
if (currentOffset <= offset){
newValue = v;
offset = currentOffset;
}
});
return newValue;
}
if (value > this.range.end) return this.range.end;
if (value < this.range.start) return this.range.start;
return value;
},
setValue: function(sliderValue, handleIdx){
if (!this.active) {
this.activeHandleIdx = handleIdx || 0;
this.activeHandle    = this.handles[this.activeHandleIdx];
this.updateStyles();
}
handleIdx = handleIdx || this.activeHandleIdx || 0;
if (this.initialized && this.restricted) {
if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
sliderValue = this.values[handleIdx-1];
if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
sliderValue = this.values[handleIdx+1];
}
sliderValue = this.getNearestValue(sliderValue);
this.values[handleIdx] = sliderValue;
this.value = this.values[0]; // assure backwards compat

this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
this.translateToPx(sliderValue);

this.drawSpans();
if (!this.dragging || !this.event) this.updateFinished();
},
setValueBy: function(delta, handleIdx) {
this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
handleIdx || this.activeHandleIdx || 0);
},
translateToPx: function(value) {
return Math.round(
((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
(value - this.range.start)) + “px”;
},
translateToValue: function(offset) {
return ((offset/(this.trackLength-this.handleLength) *
(this.range.end-this.range.start)) + this.range.start);
},
getRange: function(range) {
var v = this.values.sortBy(Prototype.K);
range = range || 0;
return $R(v[range],v[range+1]);
},
minimumOffset: function(){
return(this.isVertical() ? this.alignY : this.alignX);
},
maximumOffset: function(){
return(this.isVertical() ? (this.track.offsetHeight != 0 ? this.track.offsetHeight : this.track.style.height.replace(/px$/,”")) - this.alignY : (this.track.offsetWidth != 0 ? this.track.offsetWidth : this.track.style.width.replace(/px$/,”")) - this.alignX);
},
isVertical:  function(){
return (this.axis == ‘vertical’);
},
drawSpans: function() {
var slider = this;
if (this.spans)
$R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
if (this.options.startSpan)
this.setSpan(this.options.startSpan,
$R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
if (this.options.endSpan)
this.setSpan(this.options.endSpan,
$R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
},
setSpan: function(span, range) {
if (this.isVertical()) {
span.style.top = this.translateToPx(range.start);
span.style.height = this.translateToPx(range.end - range.start + this.range.start);
} else {
span.style.left = this.translateToPx(range.start);
span.style.width = this.translateToPx(range.end - range.start + this.range.start);
}
},
updateStyles: function() {
this.handles.each( function(h){ Element.removeClassName(h, ’selected’) });
Element.addClassName(this.activeHandle, ’selected’);
},
startDrag: function(event) {
if (Event.isLeftClick(event)) {
if (!this.disabled){
this.active = true;

var handle = Event.element(event);
var pointer  = [Event.pointerX(event), Event.pointerY(event)];
var track = handle;
if (handle==this.track) {
var offsets  = Position.cumulativeOffset(this.track);
this.event = event;
this.setValue(this.translateToValue(
(this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
));
var offsets  = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
} else {
// find the handle (prevents issues with Safari)
while((this.handles.indexOf(handle) == -1) && handle.parentNode)
handle = handle.parentNode;

if (this.handles.indexOf(handle)!=-1) {
this.activeHandle    = handle;
this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
this.updateStyles();

var offsets  = Position.cumulativeOffset(this.activeHandle);
this.offsetX = (pointer[0] - offsets[0]);
this.offsetY = (pointer[1] - offsets[1]);
}
}
}
Event.stop(event);
}
},
update: function(event) {
if (this.active) {
if (!this.dragging) this.dragging = true;
this.draw(event);
if (Prototype.Browser.WebKit) window.scrollBy(0,0);
Event.stop(event);
}
},
draw: function(event) {
var pointer = [Event.pointerX(event), Event.pointerY(event)];
var offsets = Position.cumulativeOffset(this.track);
pointer[0] -= this.offsetX + offsets[0];
pointer[1] -= this.offsetY + offsets[1];
this.event = event;
this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
if (this.initialized && this.options.onSlide)
this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
},
endDrag: function(event) {
if (this.active && this.dragging) {
this.finishDrag(event, true);
Event.stop(event);
}
this.active = false;
this.dragging = false;
},
finishDrag: function(event, success) {
this.active = false;
this.dragging = false;
this.updateFinished();
},
updateFinished: function() {
if (this.initialized && this.options.onChange)
this.options.onChange(this.values.length>1 ? this.values : this.value, this);
this.event = null;
}
});

Then this will be your new init.rb file found in scriptaculous_slider folder in your vendor/plugins:

require ‘helpers/slider_helper’
ActionView::Helpers::AssetTagHelper::register_javascript_include_default “slider”
ActionView::Base.send :include, ActionView::Helpers::SliderHelper

And finally, update in your helpers folder the slider_helper.rb folder:

# Copyright (c) 2005 Thomas Fuchs
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# “Software”), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

module ActionView
module Helpers
module SliderHelper

# Creates a slider control out of an element.
def slider_element(element_id, options={})
prepare = “Element.cleanWhitespace(’#{element_id}’);”

[:change, :slide].each do |k|
if options.include?(k)
name = ‘on’ + k.to_s.capitalize
options[name] = “function(value){#{options[k]}}”
options.delete k
end
end

[:handles, :spans, :axis].each do |k|
options[k] = array_or_string_for_javascript(options[k]) if options[k]
end

if options[:slider_value]
options[:sliderValue] = array_or_numeric_for_javascript(options[:slider_value])
options.delete :slider_value
end

options[:range] = “$R(#{options[:range].min},#{options[:range].max})” if options[:range]

handle = options[:handles] || “$(’#{element_id}’).firstChild”
options.delete :handles

javascript_tag(”#{prepare}new Control.Slider(#{handle},’#{element_id}’, #{options_for_javascript(options)})”)
end

# Creates a simple slider control and associates it with a hidden text field
def slider_field(object, method, options={})
options.merge!({
:change => “$(’#{object}_#{method}’).value = value”,
:slider_value  => instance_variable_get(”@#{object}”).send(method)
})
hidden_field(object, method) <<
content_tag(’div’,content_tag(’div’, ”),
:class => ’slider’, :id => “#{object}_#{method}_slider”) <<
slider_element(”#{object}_#{method}_slider”, options)
end

def slider_stylesheet
content_tag(”style”, <<-EOT
div.slider {
width: 500px;
height: 5px;
margin-top:5px;
margin-bottom:5px;
background: #ddd;
position: relative;
}
div.slider div {
position:absolute;
width:8px;
height:15px;
margin-top:-5px;
background: #999;
border:1px outset white;
}
EOT
)
end

private

def array_or_numeric_for_javascript(option)
js_option = if option.kind_of?(Array)
“[#{option.join(',')}]”
elsif !option.nil?
“#{option}”
end
js_option
end

end
end
end

Reset your Server and your set to go…

<script type=”text/javascript” src=”/javascripts/slider.js”></script>
<%= slider_stylesheet %>
<%= slider_field :business_card, :rating_count, :range => 1..10 %>

 

Woz interviewed on Yahoo Finance

Ξ April 14th, 2008 | → 0 Comments | ∇ personal |

So I’m checking stocks, and what da ya know, Woz is featured in an interview (click here to check out).

The interviewer asks what Woz thinks of widgets and the facebook API, and if the energy is as much there as it was in his time. I think that’s a really hard question for him to answer, because if Woz was in this generation and did what he did, he would’ve created the internet, scaled out his servers, would’ve written his own API for his own social network, and then write his own apps to connect to that API! (He would’ve written the apps in a week). Then he’d share with everyone all the code.

 

10 Realistic Tips for Programming

Ξ April 14th, 2008 | → 0 Comments | ∇ programming |

Programmers! Turn off that computer for a second! (umm..after you read this blog) 10 things to prep yourself for work..

1. Clip your nails often. You’ll ruin your keyboard..especially the S for control Save, the N, the A… (somehow the Enter key is quite durable). It’s also annoying typing with long fingernails. And if you’re programming in a library or a quite space, people around you will hate you.

2. Take showers. When you’re on a role, your brain releases the same methanphtamines found in crack. People on crack are stiky and smell.

3. Code with LCD monitors only! This is easy, as it’s the standard nowadays. Otherwise, you may burn your renta, or get dizzy.

4. Don’t forget to stand. once in a while, stand up while coding! That LCD monitor comes in handy now, as you can just lay it down and look down while standing. Sitting on your bum is back for your anus.

5. Stop learning new things! If you don’t, you’ll never finish your damn project! If you’ve got all the tools needed to write your app, DO IT NOW!

6. Talk about your abstractions out loud. Scientists say this is why children are so smart. by talking out loud, it helps you crystalize those abstract ideas…

7. Pencil and paper. Or get a classic white board in your room like they have at every startup. With new ajax methods comes multiplied granual steps, and it’s just not wise to do without..make sure you have a huge eraser too.

8. No alcohol/ drugs. i know, it’s tempting. you’re stumped, a new technolgy, framework, methodology etc just isn’t kicking in your head. you need a new perspective on the problem or concept. but your code will be filled with syntax errors. you’ll wake up the next morning to find your application won’t start because you just dont know what happened.

9. No adult sites. Yep, I said it. It’s just not worth it! It’s the internet and it’s all over the place. Do not be tempted!

10. Save your eyes, buy real books. Real books give you a chance to take your eyes off of the screen. You can read them relaxed on your bed, read them while standing in the DMV line, etc, etc, etc

 

Street Fighter!

Ξ April 12th, 2008 | → 0 Comments | ∇ personal |

Man I just found street fighter vs SNK for PS2, and I’ve been playing again with my girlfriend. She’s a fast learner. Have you seen Street Fighter 4? It looks as if it’s going to be the same feeling, and controls, just better graphics.



I can’t get over the ingenuousness of the game, I don’t think anyone can. There’s nothing like a good fight at D&B, or with good ol’ friends. I’m a street fighter player for life. Perhaps there should be a group for this on meetup.com?