Tuesday, December 23, 2008

Ubuntu: Reset Gnome Panels

I've been customizing my gnome panels, and I happened to mess them up pretty bad. However, I found an awesome way to reset the gnome panels back to the default here.

gconftool --recursive-unset /apps/panel
rm -rf ~/.gconf/apps/panel
pkill gnome-panel


W

Thursday, November 20, 2008

Ubuntu 7.10 + Git

I got curious and wanted to start playing with Git after hearing about it in the community for a while now. This is how I did it:

sudo apt-get install git

This will get the version 1.5.* from the Gutsy repos. This is old, so I decided to upgrade it.

git clone git://git.kernel.org/pub/scm/git/git.git

This will create a git folder. But first, we need to install some dependencies:

sudo apt-get install zlib1 zlib1-dev openssl libcurl3 libcurl3-dev libexpat1 libexpat1-dev asciidoc xmlto

Next, it's time to install Git. You can install Git either for the local user or for the global system. I decided to install it globally:

cd git
make configure
./configure
make all doc
sudo make install install-doc install-html

This should run for a while. You can sit back and pretend you understand all the output, or you can now go grab a coffee. After it completes, you can do a

git --version

to check if Git was updated. Now, time to play!


W

Sunday, November 16, 2008

|| and && operators may not be doing what you expect

When you use || and &&, you may think that you are playing with true/false values. For instance, a condition that uses || or && will give you back true or false.

I found out recently that this is sometimes true (and sometimes not)! Now, what am I talking about? I always thought that if you evaluate (true || true), the expression evaluates to true because at least one of them is true. Well, apparently, it does evaluate to true, but not for the reason I had thought.

In Ruby, when you evaluate (true || true), what it is actually doing is evaluating the first condition. If it is truthy (ie. not false or nil) you get the first condition back. If it is falsy (ie. false or nil), you get the second condition back. So the following occurs:

('blah' || true) #=> 'blah' - not true!
(false || 'blah') #=> 'blah' again!

For &&, if the first condition is falsy, you get the first condition back. If it is truthy, you get the second condition back. Check it out:

(true && 'blah') #=> 'blah'
(nil && true) #=> nil - not false!

Using || and && still work in 'if' statements as expected, but it doesn't work the way as first thought. With this new insight, you can use || and && for shortcuts.

Instead of:

if options[:product].nil?
product = Product.new
else
product = options[:product]
end

You could do:

product = options[:product] || Product.new

And instead of:

unless product.nil?
name = product.name
end

You coud do:

name = product && product.name

Obviously, use these shorthands with caution, as it can convolute readability for other readers. On another note, JavaScript also follows this evaluation. Have fun!


W

Tuesday, October 28, 2008

Thursday, October 23, 2008

Named Routes: Anchor

If you're using named routes and want to add an anchor to your automatically generated URL, there's a very simple way to do it:

products_path(:anchor => 'my_anchor')

It's that simple!


W

Tuesday, October 21, 2008

Being Lean

Here's an interesting article I'd like to share. It's about keeping your company fast and light:

http://venturehacks.com/articles/lean-startups


W

Monday, October 20, 2008

Interesting Ideas

Check out this talk by Jason Fried from 37signals. Definitely some very good ideas and insight.

http://www.balsamiq.com/blog/?p=375


W

Sunday, October 19, 2008

Textarea: Preserving Whitespace

A lot of the times when you let users post things using textareas, it becomes frustrating to lose whitespace when you display their posts (especially carriage returns).

Well, enter <pre>. This nifty little tag preserves any whitespace within the tags. However, there is one caveat. It preserves whitespace so well that it doesn't know how to word wrap. This is troublesome when your user continues to type in the textarea without hitting the carriage return. When displayed with the pre tags, the words are all on one long line.

Well, here's a nice little hack:

http://www.longren.org/2006/09/27/wrapping-text-inside-pre-tags/


W

Saturday, October 18, 2008

Ruby: Time made easy

Here's another example of how Ruby just makes things simple. Imagine you're working with time and you have to figure out the difference between 2 times and whether they fall within a certain range. In most languages, you have to figure out how many seconds exist in your time range. For example, 1 minute would have 60 seconds and 1 day would have 86,400 seconds. That's not too hard to figure out, but imagine the readability!

t2 - t1 < 86400

That just begs the question, "Where does 86400 come from?". Imagine you had to explicitly put down the number for 1 week?

Well, Ruby is awesome in that it concentrates on readability. Since everything in Ruby is an object, numbers are just Fixnum (or Bignum). Either way, that means we can use certain methods associated with the object. Check this out:

t2 - t1 < 1.second
t2 - t1 < 1.minute
t2 - t1 < 1.hour
t2 - t1 < 1.day
t2 - t1 < 1.week
t2 - t1 < 1.month
t2 - t1 < 1.year

Now how readable is that?


W

Friday, October 17, 2008

VMware Server: Adding a USB

Ever wondered how to add USB capability to your VMware server? Well, I had a little bit of a problem trying to get my USB connected.

I had gone to the settings for my VM and added the USB controller. Then, when I booted up my VM, I went to

VM > Removable Devices > USB Devices > ...

To my surpise, it was empty! I knew my device was plugged in because my Ubuntu detected it, but I couldn't see it. After searching around, I found a solution:

1. power off your VM
2. unplug your USB
3. >sudo gvim /etc/init.d/mountdevsubfs.sh
4. uncomment lines 42-45 (starts off with #mkdir -p /dev/bus/usb/.usbfs...)
5. >sudo /etc/init.d/mountdevsubfs.sh start
6. start your VM
7. plug in your USB
8. add your USB to the VM

Good luck!


W

Tuesday, September 30, 2008

initialize + super

Here's a word of caution to those using inheritance and calling super in the initialize method. Consider this:

def initialize(name, price)
super
@name = name
@price = price
end

Which parent method does it call? I was surprised to find out that without () after super, it automatically calls the initialize in the parent that has the parameters (name, price), rather than the one without parameters. If your intention was to call the parent's initialize without parameters, than you must do:

super()


W

Monday, September 29, 2008

TinyMCE: enforce maxlength

TinyMce doesn't have support for maxlength, and putting maxlength in the textfield tag won't do anything either.

If you try to google for a solution, you might come across this site

Don't waste your time on it, because the solution is built with the old tinymce api, it wouldn't work. Instead, use the solution from this post.


J

RoR: attr_accessible with attachment_fu

If you try to use attr_accessible on any model with attachment_fu plugin,
you'll get an error.

This article explains why


J

Sunday, September 28, 2008

RoR: attr_accessible

In a previous post, I talked about mass assignment. Well, there's something I discovered recently. If you have a polymorphic relationship, your model will have two columns: taggable_type and taggable_id. If you want to make these available for mass assignment, you cannot do:

attr_accessible taggable_type, taggable_id

Instead, RoR treats them like one attribute like so:

attr_accessible taggable


W

Saturday, September 27, 2008

RoR Generate + SVN

We all know about RoR's ability to generate controllers, models, migrations, etc. However, if you're using a repository, you have to manually add these newly created files. This could be a pain in the ass!

Here's a tip. If you're using SVN, you'll love this. Simply add the flag --svn and the generator will automatically add the newly created files to SVN. Simple!


W

Thursday, September 25, 2008

RoR: Mass Assignment Security

In RoR, it is possible to do something called mass assignments. For instance, when submitting a form, all the parameters are put into a params hash so you can do the following:

Product.create(params[:product])
product.update_attributes(params[:product])

Very simple, but by default, there is a security flaw. That flaw is covered in this post. If you are concerned about this, the easiest way would be to make it so that all your models will require attr_accessible on any attributes that you want mass assignment for. This then protects any attributes not listed by default.

In your config files, preferably in your initializers folder, add the following to protect all attributes:

ActiveRecord::Base.send(:attr_accessible, nil)

Then go through each model and think about which attributes should be exposed to mass assignments. For those that are not accessible, you must do the following to assign values:

product.store_id = store.id

This makes the assignment explicit and cannot be manipulated by the users.

Now that you know, go secure your applications!


W

Tuesday, September 23, 2008

Stack and Queue Implementation

Array in Ruby already has built in push and pop function you can use, but if you want to make it more strict and idiot proof, here's how you can implement it.

class Stack

def initialize
@stack = []
end

def push(x)
@stack.push(x)
end

def pop
@stack.pop unless is_empty?
end

def peek
@stack.last
end

def is_empty?
@stack.empty?
end

end

class Queue

def initialize
@queue = []
end

def enqueue(x)
@queue << x
end

def dequeue(x)
@queue.shift
end

def peek
@queue.first
end

def is_empty?
@queue.empty?
end

end


J

Fun with String

This is why Ruby is amazing :D

1. converting strings to numbers

"123".to_i => 123
Duh, everyone knows that

but how bout
"123stfu".to_i => 123

or

" 123stfu ".to_i => 123

you can even indicate the base of your conversion

"111".to_i(2) => 7 # treat it as a binary number
"111".to_i(8) => 73 # treat it as an octal

split a string and convert it to an interger

"123 456 789".split.map {|m| m.to_i} => [123, 456, 789]

2. Replacing text

we can implement the lame rot13 encryption scheme in one line :)

class String; def rot13; self.tr("A-Ma-mN-Zn-z", "N-Zn-zA-Ma-m");end;end

"Please hide this line".rot13 => "Cyrnfr uvqr guvf yvar"

3. Counting Characters

s1 = "abcabcabcde"
s1.count("c") => 3
s1.count("abc") => 9
s1.count(s1) => 11

count can handle negation

s1.count("^abc") => 2
s1.count("^a") => 8

and range of chars

s1.count("a-c") => 9
s1.count("^a-z") => 0

4. Reversing a String

Microsoft loves to ask interviewee to reverse the word order of a String during an interview, it takes around 15 - 20 lines to implement the function in Java or C++, but we can do it in one :)

phrase = "This is a joke"
phrase.split.reverse.join(" ") => "joke a is This"

so next time you goto an interview, asks if they'll let you do it in Ruby ;)

5. Removing Duplicate Characters

string = "aaaaaaaaaaaaaaaaaaa".squeeze => "a"
string = "aaaaaaaaaaaaaaaaaaB".squeeze => "aB"
string = "hehe....".squeeze(".") => "hehe."


J

List of reflective methods

I find the following commands very useful from time to time, but I kept forgetting their names. So I'm creating this post to help remind myself.

a.class
# returns the class of an object a

a.superclass
# returns the superclass of an object a

a.instance_of? A
# determines if a.class == A

a.is_a? A
#determines whether a is an instance of c, or of any of its subclass, or of any modules.

a.respond_to? :something
#determines if a has a public or protected method with the specified name.


J

Shuffling an Array

I just found a very interesting article about shuffling an array correctly!

http://adrianquark.blogspot.com/2008/09/how-to-shuffle-array-correctly.html

Enjoy!


W

Monday, September 22, 2008

Duck Typing and Type Checking

Consider the following example:

class A
attr_accessor :x

def initialize
@x = 0
end

def +(other)
a = A.new
a.x = @x + other.x
return a
end
end

class B
attr_accessor :x

def initialize
@x = 0
end
end

a = A.new
a.x = 10
b = B.new
b.x = 5
puts (a+b).x # this will return 15

Ruby is a very dynamic language, the addition function doesn't care if the argument passed in is of type A, as long as it looks and behaves like A. This is called duck typing, name after the phase "if it walks like a duck and quacks like a duck, it must be a duck!"

if you want to ensure the object passed into the + function has to have an x accessor, you can add this to def +(other)

raise "error" unless other.respond_to? :x

or if you want to ensure object passed into the + function has to be of class A, you can add this instead:

raise "error" unless other.is_a? A


J

Instance Variable

Java and C++ programmers are used to declaring their variables in a class, and they think they should do the same in Ruby. WRONG!

For example:

class Animal
@age = 0
@name = ""

def initialize(age, name)
@age = age
@name = name
end
end

In this example, two sets of @age, @name are created. When the initialize method is called, self holds an instance of the Animal class. But the code outside of that function are executed as part of the definition of the Animal class. When @age and @name are executed, it refers to the Animal class, not the object instance. Hence @age, @name inside the initialize function are different from the @age, @name on the outside.


J

Sunday, September 21, 2008

Variable Parameters

Sometimes we want a method that can take any number of parameters.
One way to do it is to pass in a hash, but this can be annoying. Another method is to put an * before the method's parameter. Within the body of the method, list will be treated as an array with 0 or more elements.

For example:

def average(*list)
x = 0
list.each {|l| x+= l}
l/list.size
end

irb>average 1,2,3,4,5,6,7,8,9
=> 5

J

Copying Objects

When you use =, clone, or dup to copy an object, only the object reference is copied,
not the referenced object itself (Shallow Copy).

In order to do a deep object copy, we can use the marshaling trick by dumping and
loading the object.

For example:

def deepcopy(something)
Marshal.load(Marshal.dump(something))
end

irb>b = "abcd"
=> "abcd"
irb>a = b
=> "abcd"
irb>a.upcase!
=>"ABCD"
irb>b
=>"ABCD" # see how b changes too
irb>b = deepcopy(a)
=>"ABCD"
irb>b.downcase!
=>"abcd"
irb>a
=>"ABCD" # a stayed the same this time

J

Saturday, September 20, 2008

More on enumerable

In ruby, I use .each alot to visit every elements in the array.
Did you know there's a .step(x) function that allows you to visit
every x th element in the array?

For example:

r = 0..3
r.each {|l| prints l.to_s + ' ' } # Prints 0 1 2 3

r.step(2) {|l| prints l.to_s + ' '} # Prints 0 2


J

Thousands Seperator

In ruby, underscore can be inserted into integer literals as thousands separator.

For example:

1_000 will be interpreted as 1000
1_000 + 1_000 will equal 2000
1_000_000_000 will be interpreted as 1 billion

the same technique works for float number as well

For example:

1_000.1 will be interpreted as 1000.1


J

Friday, September 19, 2008

Prototype: $A is not defined

Ever get this annoying error? Well... I do. Odd thing is, everything still works like a charm. So what's happening.

Unfortunately, no one seems to really know! I did some digging and found this bug. If you go through the comments, Prototype has some problems when loading/unloading a page on Firefox 2. Or maybe it's Firebug. People can't seem to entirely agree, and the bug has been reopened several times.

However, if you want a patch and forget about finding out what the problem really is, check out this fix.

I've used it and forgot about it now. Would be nice to know why though...


W

Thursday, September 18, 2008

Dropbox

Recently, there has been a lot of buzz around Dropbox. It is now open to beta testing, and many people say it's awesome.

In short, Dropbox can be thought of as storage that you can access from anywhere you have an internet connection. It'll automatically sync your local and remote files, and also work on PCs, Macs, and *nix machines.

For those of you that move around a lot and need your files reliably without the hassle, check out Dropbox.


W

Wednesday, September 17, 2008

Database Visualization

Keeping documentation up-to-date is always a pain in the ass. I was recently working on updating our database diagrams and thought that there may be a way to automate the process.

I found 2 solutions:

1. XMI
2. RailRoad

For solution (1), it worked, but I had to tweak it slightly. Because we are using PostgreSQL, I had a problem when UmlDumper tried to execute current_database for the adapter. This works fine for the MySQL adapter, but no such function exists for the PostgreSQL adapter. I quickly hacked it and just replaced it with a general name for our database, as we didn't have to be dead-on here.

I was quite disappointed when Dia did not know how to open up the XMI file. So, searching around, I found a program called Umbrello. It works great. Unfortunately, I had all my UML classes, but no diagram! I had to drag and drop each one individually (I couldn't figure out how to drag them all at the same time T.T). I then manually added in all the lines and made it pretty. Not too bad, but it was partly automated and partly manual.

For solution (2), it worked great. I used a rake task to generate the svg files. I had several issues with this, which was the fact that RailRoad is used to diagram models in RoR, not the database. Hence, I ended up with a lot of relations that didn't exist in the database. This meant TONS of lines. The lines are also quite hard to follow as they constantly overlap and cross each other.

2 major issues I had was that there is a 1-to-1 relationship (for efficiency purposes). However, the diagram did not reflect this. For example, we have class A and B that are in a 1-to-1 relationship. A will have has_many relationships and so will B. However, the diagram showed that all of B's has_many relationships were related to A, not B. I couldn't figure out why.

The other issue was a logged bug. If the model ends in an 's', the diagram gets messed up. The diagram will automatically drop the trailing 's'. This created incorrect relationships.

For these 2 major issues, I was unable to use solution (2) in the end. However, if more improvements are made, I may give it another chance as the whole process was completely automated. If your interested, it also does Controller diagrams.

If anyone else has a better way of producing automated diagrams of their database or models, give me a shout. I'd love to hear other solutions.


W

Monday, September 15, 2008

Google: AdWords Algorithm

Sorry, this isn't a post about Google's algorithm :P

But, there is news that they're planning to modify it! That's big news to people using AdWords. Go and check it out.

Quick summary:

- dynamic calculations of Quality Score at search time
- keywords are no longer labeled as "inactive for search"
- no more "minimum bids"... in comes "first page bid estimates"

In other words, Google wants more money ;)


W

Sunday, September 14, 2008

Saturday, September 13, 2008

Y Combinator

Y Combinator is a venture firm that specializes in funding startups in their early stages. I recently discovered their news section, which, as a technical person, I find very interesting. It is a Digg type site that gives links to interesting articles. Every so often, I will also see RoR articles on there. Check it out:

http://news.ycombinator.com/


W

Friday, September 12, 2008

Ubuntu: Volume Problems

Recently, my audio has been much softer than it has been when I first installed Ubuntu. Even if I turn my volume up completely, the audio was only at a normal volume. I found this odd because before, when I turned it up, it would blast my ears off.

I managed to find out why! If you go to your Volume Control, Edit > Preferences, and select PCM. Then turn the PCM volume up to the desired level. Mine, for some reason, was set at a very low volume.

I'm not quite sure what happened, as I never played with my settings. My only guess is that some particular update fooled with the settings.


W

Tuesday, September 9, 2008

BackgrounDrb.destroy

So we've been noticing some pretty odd things with BackgrounDrb lately. In spite of our previous fixes to BackgrounDrb, we've decided to give up on it. Why? Simply put: It's not working properly.

We've been checking the logs recently, and we've noticed way too many calls to our scheduled tasks. On the odd days, we'll get 3 or 4 extra calls when only 1 was scheduled. I don't know how to explain this, nor do I wish to find out, because frankly, I'm fed up with this.

I admit, it really was my fault for trying to use an overly complicated program to run something very simple. KISS - I know. I'm kicking myself in the ass for this now! Anyways, simple solution: cron. It's the most basic of basic schedulers. You can't go wrong here.

Luckily, all our functions were encapsulated in the models, so the logic didn't need to be changed. We ripped out the stuff in the BackgrounDrb worker and placed them in a rake file. We then called the rake tasks from the cron.

Very simple. Very clean.

Bye Bye BackgrounDrb!


W

Tuesday, September 2, 2008

Sitemap

It's nice to have a sitemap that adheres to the Sitemap 0.90 protocol. In rails, this can be automatically generated. Unfortunately, you have to do some work.

I found 2 different ways:

1. using controllers
2. using rake

If your site is small, (1) works really well. It's as dynamic as it can be as the sitemap is generated on the fly. However, every time anyone visits that URL, you end up hitting the database for a fairly large call, memory-wise. If it's just legitimate people accessing it, they will access the URL when they need it, or on a periodic time frame. However, if you encounter malicious users (which there are many out there), they could easily overload your server.

(2) is not as up-to-date, but from my point of view, that's ok, especially if you update the files daily. The solution posted works well, but since out site takes advantage of BackgrounDrb, I thought I would modify it to work with BackgrounDrb instead of rake.

I created some self functions to do the database queries and handle the tasks in the rake. Also, in sitemap.rb, I added the lines:

include ActionController::UrlWriter
default_url_options[:host] = 'www.twoblindfish.com'

This allows you to use named routes and url_for. Now we don't need to hardcode our URLs! Another plus! The rest is pretty straight forward. A few of the tasks were redundant, so I refactored them into multiple functions for reuse.

The only thing really different would be to place your sitemaps in public/system/. so that the sitemaps don't get removed when you do a cap:deploy. This works because the public/system folder is symlinked to shared/system.

Hope this helps those in need of generating sitemaps!


W

Tuesday, August 26, 2008

Geokit: Oddities

1. When using Geokit + Google, sometimes, giving a valid postal code will fail. It's a very random thing. I'm not sure if it's just Google, but sometimes, it fails, even with a valid postal code. I'm guessing it has something to do with the network or perhaps they limit how many you can ask for in a period of time so you don't overload their server.

2. If you add :within to your find, Geokit doesn't recognize that :within => nil means not to add :within. Sometimes, you have a variable that may or may not be nil, and this controls whether you want to search using a distance. The :origin key works fine with nil, but :within does not. It blindly adds the distance calculations to the find. I had to hack acts_as_mappable.rb a little bit in order to get it to work.

In the apply_distance_scope(options) function, I have:

distance_condition = "#{distance_column_name} <= #{options[:within]}" if options.has_key?(:within) && !options[:within].nil?
distance_condition = "#{distance_column_name} > #{options[:beyond]}" if options.has_key?(:beyond) && !options[:beyond].nil?

and

[:within, :beyond, :range].each { |option| options.delete(option) }

This will take the :within => nil into account and skip the adding of the distance calculations out of the find and remove the useless keys.

3. In the Geokit README, there is a section about using :includes. However, there isn't a section on using :joins. Apparently, when you use :joins, things can screw up. For instance, if I have

Shop.find(:joins => "INNER JOIN products where products.shop_id = shops.id", :conditions => ..., :origin => ..., :within => ...)

You would expect a Shop object to be returned. This is true, but I found a small error. The Product id replaced the Shop id, leaving me with a Shop object with an id of the Product id.

I traced this down to the function add_distance_to_select(...). In this function, it blindly sets the :select option in the find to "*" if it isn't already defined. I'm guessing, because both Shop and Product have ids, they get mixed up somehow.

In order to fix this, I needed to add :select => "shops.*".

Hopefully, this info helps those that are having the same problems. If you have a better solution, feel free to share!


W

Saturday, July 19, 2008

TwoBlindFish

So J and I have been absent recently because we've been super busy with launching our website. After many months of exploring RoR, we have finally come out with something that we're both proud to present to the world.

It's a dating website! We've called it TwoBlindFish. We've taken the following URLs:

www.twoblindfish.com
www.twoblindfish.ca
www.twoblindfish.net
www.twoblindfish.org

If you're single and looking, feel free to drop by and try it out. There's no long forms to fill out, so sign up is quick and easy. For your profile, we use tags, so it's really fast to build your profile. We've also added something entirely new, which is a rating system - get to know someone and we allow you to rate them! ^^

If you're in the Vancouver, B.C. area, we're having a free $5 Waves Coffee card giveaway. Check the website for details!

Have fun, enjoy, and good luck!


W

Thursday, July 17, 2008

Gedit

As promised, here is a list of the plugins that I have been using for gedit:

- change case
- code comment
- document statistics
- embedded terminal
- file browser pane
- indent lines
- insert date/time
- join/split lines
- line tools
- modelines
- rails hot commands
- rails hotkeys
- regex search (files)
- reopen tabs
- session saver
- snap open
- snippets
- spell checker
- split view 2
- todo list
- word completion

Wow! That's a long list. I've also enhanced my snippets for my personal use. I suggest you do the same. They do wonders in saving time ;)

If you got any gedit setups, leave a comment. It would be nice to see the variety of setups!


W

Tuesday, July 15, 2008

Gentoo + Vim

To my dismay, when I was using Gentoo, Vim was not installed. Sad as I was, I attempted to rectify this problem. No worries... a simple 1-liner:

emerge -av vim

and I'm happy once again ^^


W

Saturday, July 12, 2008

Uploading large file to nginx server

If you upload a file over 1M in size to a nginx server, you might get a "Request Entity Too Large" (413) error.
We can overcome this problem by specifying the client_max_body_size in nginx.conf

nano /etc/nginx/nginx.conf

under "server {"
add the following line

client_max_body_size 5M

this will change the max file size to 5M, you can change that number to whatever you like.


J

Tuesday, July 1, 2008

VMWare Server Fix

I managed to find a solution to my previous problem after updating my Ubuntu. It's quick and it also retains all the states of the virtual machines ^^

https://answers.launchpad.net/ubuntu/+question/36849

And just in case the link ever dies:

sudo apt-get install vmware-server-kernel-source
cd <temp dir>
tar xvjf /usr/src/vmware-server.tar.bz2
cd modules/vmware-server-kernel/
export KPKG_DEST_DIR=<where the deb package should go> # otherwise fakeroot won't work
export KVERS=`uname -r`
fakeroot debian/rules binary-modules
sudo dpkg -i $KPKG_DEST_DIR/vmware-server-kernel-modules-`uname -r`*.deb
cd -
rm -r modules
sudo /etc/init.d/vmware-server restart

Enjoy!


W

Tuesday, June 24, 2008

Ubuntu Gutsy Update + VMware Server

Sorry for not posting anything for quite a while now. Been super busy with some other stuff.

Just wanted to vent a little. I believe yesterday, or the day before, there was an update to Ubuntu Gutsy. All is well, except when I tried to run VMware Server today, it wouldn't start! I checked the logs and said there was something to do with /dev/vmmon. After a quick Google search, I discovered that the new update had broken VMware Server! NOOOOOOOOOOOO!!!!!! This sucks!

A solution I found was to not use the repository version of VMware Server, as it is old anyways. I'm not sure if I want to go through the trouble of reinstalling it manually on a 64-bit machine though... I guess I'll wait and see how long it takes them to fix it T.T


W

Saturday, June 7, 2008

OpenOffice Spellchecker

OpenOffice is a little biased when including language dictionaries for spellchecking. For instance, the Canadian English dictionary is not included by default. However, this can easily be remedied by doing the following:

1. File > Wizard > Install new dictionaries...
2. follow the wizard and install the appropriate languages you want
3. Close all OpenOffice programs
4. Restart OpenOffice

Now, when you go to:

Tools > Options... > Language Settings > Languages > Default languages for documents > Western

you should be able to select "English (Canada)" and it should have an "ABC" with a checkmark icon. This means you can now spellcheck in Canadian English!


W

Wednesday, June 4, 2008

Ubuntu + AMD64 + Flash

Well, apparently, this combination just doesn't go well together. I'm running Gutsy right now, and having a horrible time with Flash. I've already tried using the install script given in the Ubuntu forums, only to have it half working. Sometimes, everything plays, sometimes, nothing plays. I can usually get YouTube working, but there are some Flash sites that just don't work.

I was recently trying to play a .swf file by simply dragging it into FireFox. To my dismay, I ended up with a gray screen. Sucks!

I finally found a workaround... at least for .swf files. I downloaded the Windows Flash Player 9 Projector content debugger (standalone player) from the Adobe site. I then created a launcher using the command:

wine /path/to/standalone_player

BAM! It works wonderfully. However, still no hope for the stuff that is online T.T


W

Tuesday, May 27, 2008

Comma Separated Numbers

I found a neat little function that will separate large numbers by thousands using a comma or any specified delimiter:

http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#M000997

Gotta love RoR... they simplify everything!


W

Monday, May 26, 2008

Ubuntu: .docx files

OpenOffice is amazing when it comes to opening up .doc files created from Microsoft Word. However, there's a slight problem when it comes to opening .docx. Simply put, OpenOffice doesn't recognize it!

Don't worry though... there's always a solution! Check this out and follow the instructions posted by stuporglue.

Enjoy!


W

Thursday, May 22, 2008

Remote Host Identification has Changed

I just reinstalled our main server. When I try to ssh into it I got an error:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.

Please contact your system administrator.
Add correct host key in /home/user/.ssh/known_hosts to get rid of this message.
Offending key in /home/user/.ssh/known_hosts:1
RSA host key for ras.mydomain.com has changed and you have requested strict checking.
Host key verification failed.

-----------------------------------------------------------

The reason behind this is because your local computer still has the old RSA host key stored in /home/your_account/.ssh/known_hosts.

The easiest way to solve this problem is simply delete that file or you can delete the host entry in the file.


Joseph

Saturday, May 17, 2008

Time Ago

Ever wanted to show the user that something happened so many minutes/hours/days/etc ago? Apparently, RoR makes it super simple to do this. There is a method called:

time_ago_in_words

Simply include the time (from now) that you want to calculate - perhaps a created_at/updated_at field.

Easy!


W

Friday, May 16, 2008

Software Freedom Day

September 20th, 2008 is Software Freedom Day! If your interested in promoting and celebrating software freedom, check this out:

http://www.softwarefreedomday.org/


W

Wednesday, May 14, 2008

Alternating Table Row Colours

When listing data out in a table, it's always nice to have alternating row colours. This makes it infinitely easier to scan the table and much more enjoyable.

RoR makes it really simple to alternate row colours. A cycle function is given to aid in this task, and it simply cycles between the values given. By using this, you can specify your alternating class names here.

If you have more than one table, remember to call the reset_cycle function to reset the cycle.

Easy!


W

Saturday, May 10, 2008

VMware Server: Adding a new HDD

I'm running WinXP through VMware Server (as it comes free and is in the Ubuntu repos!!!). It runs really, really well and am completely satisified with it. However, I wanted to add a new HDD to my VM.

Well, I did the obvious, which was to power down my VM and edit the settings. I went to go add a new vitual HDD and pre-allocated it (all the defaults).

I then powered on my VM and lo-and-behold, no new disk! What?!?!?! Well, I found a very nice little tutorial on YouTube that teaches you how to do it properly. Apparently, there's a few extra steps required inside of WinXP to detect and setup the newly added disk:

http://www.youtube.com/watch?v=z3GciNMYLlo

Hopefully, this'll help anyone that is stuck.


W

Friday, May 9, 2008

Ubuntu + Compiz Fusion plugins

Gutsy Gibbon already has Compiz Fusion packaged with it, but apparently, there are numerous plugins that can be added on as well!

This guy has written a lovely script to get you started:

http://ubuntuforums.org/showthread.php?t=620000

Enjoy!


W

Thursday, May 8, 2008

Support ODF

I've recently been reading more and more material about open formats. Apparently, there's been a ripple in the pond, as Microsoft is trying to push through their own format, which is obviously inferior and not much of a standard at all (again, the usual Microsoft bullying antics).

I found an interesting link I'd like to share if anyone is passionate about this fight. It's to get your government to support the OpenDocument Format. I'd just like to share this with you guys:

http://www.fsf.org/campaigns/odf-letter-template


W

Favicon

You know those websites that are able to have a little icon in the address bar? That's pretty cool huh? I thought so too, so I decided to add one.

Apparently, IE seems to have managed to screw it up... surprise surprise.

According to W3C, it's very simple to add one:

http://www.w3.org/2005/10/howto-favicon

Works like a charm in better browsers. However, in IE, they seem to mess everything up. Funny how IE is the one that first introduced this too! Anyways, to get around the IE problem, just create a favicon.ico in your root directory. This will definitely not look as nice as the PNG... but for compatibility, too bad! :P

IE is really screwing their users over... sigh...


W

Wednesday, May 7, 2008

Ubuntu + Ekiga

Ubuntu comes bundled with Ekiga, which is a VoIP program. It is something like Skype. I wanted to test this out and see how well it worked. I had a little bit of a problem configuring it though and would like to share my solution.

When using the configuration assistant, I was stuck at step 5, which told me that I had a symmetric NAT. If you don't run into this problem, then the configuration should go smoothly and you should have no problems. Anyways, back to my problem. Ekiga cannot run with a symmetric NAT. If you find any scripts to run in order to get Ekiga working, DO NOT run it. I tried one that I found on a wiki, and I lost my internet connection. It basically changed my iptables. No worries though if you did... just reboot your machine and everything will be reset back to a working state.

The script was made for older versions of Ekiga (much older) and is now of no use. The easiest way to get Ekiga working is to use port triggering on your router:

Service Name: STUN (or anything you like)
Triggering Port: 3478 (UDP)
Inbound Ports: 5000-5100 (UDP)

This should do it. Rerun step 5, and it should not report a Cone NAT. This is now acceptable and you can continue with the configuration.

Enjoy!


W

Tuesday, May 6, 2008

CSS: z-index

I ran into this problem with stacking order. It seems pretty simple to me, but Internet Explorer has managed to screw it up... again! I don't blame them if IE6 has problems, but for goodness sakes, fix it in IE7!! But alas, that's not to be and I'm stuck here with some crappy options. Actually, I don't mind... my users will though.

Basically, I have a few divs, and they're going to overlap. With proper z-index, everything is fine. However, without it, I can't implement what I want to do. So in the end, it's the users who suffer... that is if they use IE. I ended up using conditional comments (awesome stuff!) to do what I want to do if the user is not on IE.

Apparently, they say that IE8 fixes this and that it will be completely standards compliant, but my question is when will that be released and when will all the users no longer be using anything earlier than IE8... it's definitely going to be a long wait...

Damn IE sucks!


W

Saturday, May 3, 2008

Deployment: Part 3

We finally have everything up and running... at least the basics. However, we needed something more, such as starting/stopping/restarting our other servers. This was easily achieved using our own custom tasks in deploy.rb.

However, there was one odd one, which was backgrounDRb. To start the server, you must use:

./script/backgroundrb start -e production

The first problem we encountered was that after Capistrano had finished executing, the backgrounDRb daemon would disappear. After some research, an easy fix was found, which was to run the script through the nohup function:

nohup ./script/backgroundrb start -e production

This enabled backgroundrb to exist after Capistrano was complete. There was also another oddity that I found through research which I also implemented, which was to cd to the root directory before executing the script:

cd path/to/root && nohup ./script/backgroundrb start -e production

I never tested whether or not I could run the script without cd-ing... but the above command works for me without a problem, so why fix something that's not broken?

Next came environment problems. Backgroundrb was, for some odd reason, accessing the database in the development environment. However, I was clearly running the script in production!

Looking through the code, I realized that in bdrb_config.rb, it was setting the ENV["RAIL_ENV"] using the -e flag (which I stated production). However, when the master and meta workers were initialized, they were loading the rails environment without checking the ENV["RAILS_ENV"]. They were using the config file instead!

To fix this problem, simply change line 262 of master_worker.rb and line 350 of meta_worker.rb from:

run_env = CONFIG_FILE[:backgroundrb][:environment] || 'development'

to:

run_env = ENV["RAILS_ENV"] || CONFIG_FILE[:backgroundrb][:environment] || 'development'

This should check all the possible places that the environment could have been set and now everything should be running in the production environment!

Hope this helps anyone that was just as stumped as I was!


W

Friday, May 2, 2008

VMware on Hardy

There is currently no vmware package for hardy (DAMNIT!!). So we gotta do it the hard way.

1. apt-get the following

sudo apt-get install build-essential linux-headers-`uname -r`
sudo apt-get install xinetd

2. download the vmware tarball

just goto the website, it's constantly changing so I wouldn't bother posting it.

3. Get your FREE registration number (this used to cost a fortune, lucky us)

http://register.vmware.com/content/registration.html

4. Extract the tarball somewhere and run it by doing

tar -zxvf xxx.tar.gz
go into the directory
sudo ./vmware-install.pl

5. Now it'll ask you bunch of questions, just keep pressing enter. After awhile, it'll start compiling and fail :)

6. This has something to do with hardy's kernel, but don't worry, there's a patch for it.

wget http://uruz.org/files/vmware-any-any-update-116.tgz
tar -xvzf vmware-any-any-update116.tgz
cd vmware-any-any-update116
sudo ./runme.pl

7. VMware should start compiling and asks you more questions after (just keep pressing enter)

8. Once you've configured your vmware server, you need to link up some libraries

sudo ln -sf /lib/libgcc_s.so.1 /usr/lib/vmware/lib/libgcc_s.so.1/libgcc_s.so.1
sudo ln -sf /usr/lib/libpng12.so.0 /usr/lib/vmware/lib/libpng12.so.0/libpng12.so.0

9. And that's it, you can launch it by typing vmware on your console


J

Monday, April 28, 2008

Hardy Heron Connection Problem

Just upgraded to Hardy two days ago. Is it nice? Yes. Is there any problems with it? Yes.

Installation was fast as usual, took around 20 mins. Video settings, sound card, network card ... are all setup and ready to go after the system rebooted itself. Firefox 3 looks better than ever, however, I can't seem to get a connection?!?

What's more weird is that I can actually goto google.com, but everything else will time out on me!
After hours of searching, some dude suggested that I should decrease the MTU (maximum transmission unit) from 1500 (standard for ethernet) to 1492 by typing the following command

sudo ifconfig eth0 mtu 1492

amazingly, my connection is back to normal! (if anyone know why that is, can you please educate me on this issue? I really like to know the reason behind this!)


J

Deployment: Part 2

As I mentioned in the last post, we got past SVN.

We finally came to Mongrel Cluster. This was a major headache. Apparently, Capistrano is broken when it comes to handling Mongrel Cluster. Simply following the Capistrano's site tutorial will not work.

The first step around this was to get the Palm Tree gem on the local machine:

>sudo gem install palmtree

This will include some recipes that we can use with our deploy.rb that you need to run Capistrano.

Next, add this to the top:

require 'palmtree/recipes/mongrel_cluster'

This will include the recipe needed to fix the deployment scripts. Basically, it rewrites the deploy script that comes with Capistrano. All you really need to know is that it works ;)

Next, generate a mongrel_cluster.yml by following the "Mongrel Cluster Setup" in this wiki. Check this into your repository as we'll need it.

Add this line to your deploy.rb:

set :mongrel_conf, "root_of_the_app/config/mongrel_cluster.yml"

Last thing we need to add is to tell Capistrano not to use sudo:

set :use_sudo, false

When all this is finally done, make sure that everything is in your repository. We can now attemtp a deploy:

cap deploy:cold

Make sure you use cold, as this should be the first time you're deploying. A deploy:cold is different than a simple deploy because it assumes that your servers are not running yet. Hopefully everything went right here. This should get you past Mongrel Cluster.

The next would be take a look at how to customize your deploy, such as starting other servers that you would potentially need.

We found the "after_stop", "after_start", and "after_restart" helpful for handling our other servers. Make sure that you put them in the deploy namespace ;)

Good luck!


W

Saturday, April 26, 2008

Deployment: Part 1

So we're nearing the stage of our deployment and decided to perform a dry run on J's spare computer. We installed the Ubuntu server on his machine, along with all the stuff we needed (SSH, Ruby, Rails, gems, etc.)

We then decided to go with Ubuntu server + Apache + Mongrel Cluster + Capistrano for an action-packed deployment. We decided on Ubuntu since we have had such a good impression with them and have had experience with troubleshooting on an Ubuntu machine. Apache + Mongrel Cluster seems to be a fast-growing standard, although there are many configurations to choose from. We had been doing research and found that this configuration would be the most painless. As well, this configuration is supposed to handle very well. We used Capistrano to help with our deployment and to make maintenance much easier when deploying on a remote server.

Basically, the whole setup revolved around Capistrano. So... off we went to figure out how to use it. This took us a very long time as we had to troubleshoot some problems.

The first problem that was not even mentioned on the Capistrano site was logging into the remote server with a particular username. In the examples, they simply say to just use:

role :app, my.server.com

However, this will log you into the remote server with the username you have with the local machine. This is not what we wanted, so we ended up having to attach the username in front:

role :app, username@my.server.com

Next, when the server was trying to checkout our repository from SVN, it crapped out. We added this to our deploy.rb to get around this:

default_run_options[:pty] => true

Now, our deploy ran fine, until we got to Mongrel Cluster T.T

Hopefully this will get you out of the rough, unless you're using Mongrel Cluster, which I'll cover in the next post.


W

Friday, April 25, 2008

IE Address Bar

This is really starting to annoy me. In FF, if you type in a URL in the address bar without the http:// and no www, it is smart enough to put them in for you.

However, in IE, without the www, it doesn't know how to prepend the http:// to your address. This gets really annoying when you're constantly trying to go to localhost or a specific IP address for testing.

Sorry for the rant...


W

Thursday, April 17, 2008

Responds_to_parent loc error

If the rjs inside your responds_to_parent block ended up removing the iframe from your html page, the loc variable will no longer be defined.

Besides having an ugly error message on your firebug console, it can actually cause problems for the javascripts on that page as well.

In order the get around this problem, you'll need to do the following patches:

in parent_selector_assertion.rb and responds_to_parent.rb

replace all occurrence of
(3 in parent_selector_assertion, 1 in responds_to_parent)
loc.replace('about:blank');

with
if (window.loc) { loc.replace('about:blank'); }
and that's it!


J

Pluralize

Have you ever had to write some sort of if/else condition to display a sentence involving an object count? Something like 1 person, 2 people, etc.

Well, RoR has a nifty little method called pluralize. All you do is feed it the number and a string, and it will attempt to figure out exactly what you want.

For example:

pluralize(1, 'person') # '1 person'
pluralize(2, 'person') # '2 people'

I thought this was pretty neat and wanted to share with you guys. There are a lot of little methods tucked away in the RoR API, and I encourage you to look through them to help minimize your development time on mundane things like this. Enjoy!


W

Wednesday, April 16, 2008

respond_to + render :partial

RoR has a very quick way to turn your web application into a web service that supports API hooks into your application. It does this using the respond_to method. It's as simple as doing something like:

respond_to do |format|
format.html # automatically calls the corresponding view
format.js #automatically calls the corresponding rjs
format.xml { render :xml => @user.to_xml # or other XML stuff }
end

It's that simple!

Well, there's one odd thing that got me for a little bit. I'm not sure if it's a bug, but when I tried to render a partial in the format.js block, I got an error that it could not find the corresponding template:

respond_to do |format|
format.js { render :partial => 'my_partial' }
end

I found that very odd, but not fixable... I tried adding '.html.erb' to the end of my_partial:

format.js { render :partial => 'my_partial.html.erb' }

And magic! It worked! I'm almost sure this isn't the way RoR is suppose to handle this, but in the meantime, it works! Small hack, but I'm happy :D If any one else runs into this problem, drop a comment, or even better, if you know why or how to solve this, let me know!


W

Tuesday, April 8, 2008

Relatively Absolute Positioning

So I came across a bug in our layout that was driving me nuts. I was trying to lay a div ontop of another div, so I was using relative positioning. Seems reasonable. However, when using relative positioning, it leaves a white gap where the div used to be.

I finally came across this nice little CSS tutorial about positioning and I learned something new. Apparently, you can have an outer div with relative positioning, and have the inner div absolutely positioned inside: a relatively absolute positioned div! Amazing! Since absolute positioning removes the div from the flow completely, no white gap is left behind!

One problem in IE though (as usual), is that anything with relative positioning inside the absolute div is covered up (doesn't show). FF is perfectly fine though (go figure...). I got around this problem by using margins instead.

You may probably know this, but for those that didn't... enjoy!


W

Friday, April 4, 2008

Gedit

So after playing around with Gedit for a while, I'm loving it. It's super fast and there are so many nice plugins to make it very similar to an IDE. There are some things that aren't present, such as refactoring, but that never worked properly in RadRails anyways!

Before, I mentioned that there was no SVN or debugging support. As I continue to develop using Gedit, I have not encountered any problems with this. I'm currently using SVN from the terminal and it's perfectly fine. Lucky I've had experience with using CVS in the terminal ;) Also, I installed a graphical diff program called Meld so that I don't have to look through the classic diff. I haven't had to do too much diffing, so I can't say too much about it.

As for debugging, I realized that for RadRails, I was already using ruby-debug, which runs straight off the terminal! So far, for what little debugging that I have had to do, I found the terminal easier to work with. It requires a bit more typing though (compared to the mouse clicking in RadRails). However, it works... unlike RadRails. The debugger in RadRails was very unpredictable and I could never access the variables without some sort of error popping up. It was so annoying! I'm quite happy with the terminal, so for now, I'm sticking with it.

Apparently, there are new plugins still being developed for Gedit as it gets more popular. Perhaps someone, in time, will come out with an SVN plugin or a debugger plugin. We'll just have to wait and see ;)

In the meantime, I'm super happy with my current setup. There are little things here and there that are bugging me, such as when I hit the home button, it jumps to the beginning of the line, rather than the beginning of the words. I'm hoping there's a configuration that I just haven't found yet.

After playing with it some more, I'll post up the plugins I have installed.


W

Thursday, April 3, 2008

Eager Loading + Order By

So I was trying to cut down on the number of queries that I was making on a particular page and ran into a slight problem.

Basically, I had a relationship where a User has many Notifications:

class User
has_many :notifications, :order => 'created_at DESC'
end

In my controller, I wanted to cut down on the queries, so I did some eager loading:

@user = User.find(user_id, :include => :notifications)

However, when I went to go view my page, the notifications were not in the order as I specified. I went to go take a look at the query, and lo-and-behold, there was no ORDER BY stated in the query.

After some thought, it became apparent why no ORDER BY was included. This makes sense because if you eager load many tables, each with its own ORDER BY, it would be difficult, if not impossible, to have everything returned properly.

I would assume, without much thought, that one would assume that this would work. With further thought though, this becomes the correct thing to do.

Just a heads up ;)


W

Tuesday, April 1, 2008

BackgrounDRb

There are often times when you want to perform scheduled tasks, such as email reminders. These tasks are usually triggered at a specific time, and not necessarily by a user action.

On a unix machine, cron jobs do exactly this. They are triggered at a particular time, do their work, then go away. I looked around for a bit to see if there was a rails plugin to handle jobs like these.

Behold: backgrounDRb. This is a rails plugin that runs its own server to do a multitude of jobs. It supports cron jobs, but at the same time, it handles jobs in the background. For instance, if you are generating a large document, you don't want the user to wait for a long time. Instead, it will spawn a job in the background, allow the user to continue doing his/her stuff, and periodically check when the job is done.

For my purposes, I only needed the simple ability to create cron jobs, so I have yet to experiment with the background tasks. However, I found it to be super easy to use and everything is very straightforward.

If you're looking for a scheduler type plugin, look no further. This baby is amazing!


W

Monday, March 31, 2008

Textmate: Ubuntu style!

If you've ever watched any railscasts, most of them use something called Textmate to edit their files on a Mac. Apparently, it's suppose to be really good.

Well, recently, I've been getting really fed up with Aptana and RadRails. There are lots of things that bug me, like the wait time to save a file and especially the wait time to copy/paste things. It's just horrible. Furthermore, RadRails decides to crap out on me every so often. There are so many errors in the background that I run out of memory. So far, there doesn't seem to be a fix.

Enough of that... I'm moving on to better things, like a Textmate clone: a revved up version of Gedit! Apparently, you can easily make Gedit behave very similarly to Textmate! I followed this guide and so far, everything is smooth.

I haven't tried developing yet. I just installed everything. I'll let you guys know how it goes... but I'm anticipating I'll like this more than RadRails. Only downside is the loss of the SVN plugin and a debugger... I wonder...


W

Ruby Exception Hiearchy

For those who wants a better understand of the exception hiearchy, here it is!

Exception
Errno
NoMemoryError
ScriptError
LoadError
NotImplementedError
SyntaxError
SignalException
Interrupt
StandardError
ArgumentError
IOError
EOFError
IndexError
LocalJumpError
NameError
NoMethodError
RangeError
FloatDomainError
RegexpError
RuntimeError
SecurityError
SystemCallError
SystemStackError
ThreadError
TypeError
ZeroDivisionError
SystemExit
SystemStackError

Cheers,

Joseph

Sunday, March 30, 2008

Ubuntu beats out Mac and Vista

The results are final from the 3-day-long hack-fest and guess who came out on top? Yup, that would be Ubuntu!

A hacking contest was held in Vancouver recently which featured 3 laptops, 1 was a MacBook Air, the other a Vista, and the 3rd was an Ubuntu.

The first to be compromised was the MacBook Air. Amazingly, Vista held its ground until the 3rd day, where it was finally pwned.

More details can be found here:

http://dvlabs.tippingpoint.com/blog/2008/03/28/pwn-to-own-final-day-and-wrap-up


W

Friday, March 28, 2008

Named Routes: url vs path

So I spent a good 30 minutes trying to figure out why my links were missing the host part of the URL.

What I was trying to do was send emails using ActionMailer and generating urls inside the ActionMailer instead of the ActionController. The documentation says that you can use url_for and named routes if you do what it says.

Well, for a while there, I was completely stumped as to why my named routes were missing the host part, until I realized I was using the path method for named routes instead of the url method:

users_path #/users
users_url #http://www.mysite.com/users

The difference is obvious. However, if you're used to using path instead of url, you may be stumped as well. Hopefully, you guys won't have to go through the trouble I did ;)


W

Friday, March 21, 2008

Ubuntu + Postfix

So I researched a little bit about setting up an email server. I at least got something going, as I could send email out. However, I am still using my ISP's server as a relay host, as they block port 25.

On Ubuntu, I set up Postfix by following the documentation.

Then, to use a relay host, I simply went into /etc/postfix/main.cf and entered the server's address into the relayhost variable.

A quick reload of the Postfix server:

>sudo /etc/init.d/postfix reload

and all was right with the world.

To set up POP3 and IMAP, take a look at the following documentation.

Enjoy!


W

Wednesday, March 19, 2008

Bugzilla: Round 2 (continued)

So what happens when your ISP blocks port 80 and 25. Well... Bugzilla cannot be accessed and emails cannot be sent... kinda useless then huh?

Changing the apache listening port from 80 to something else is quite easy:

>sudo gvim /etc/apache2/ports.conf
Change the 'Listen' port to your own preference
>sudo /etc/init.d/apache2 stop
>sudo /etc/init.d/apache2 start

That should fix the port 80 problem.

Now for the port 25 problem. I originally tried to get sendmail to use an alternate port for sending emails. However, this attempt was unsuccessful. I also tried installing postfix, but nothing worked. I then tried to connect to an external smtp server like smtp.gmail.com:587. However, this required TSL to be enabled, and I couldn't find any settings in Bugzilla that would support it. Interestingly enough though, I found a patch to add username/password to the SMTP configurations that will be included in the next Bugzilla:

https://bugs.launchpad.net/ubuntu/+source/bugzilla/+bug/133903

I then found out that my own ISP, Shaw, had an email server. I hope I'm not using it illegally, but there is no authentication required for mine. I ended up setting configuration to use SMTP rather than sendmail, and added the SMTP server from Shaw. I then restarted apache2 for safe measures, and VOILA! Bugzilla with emails!

Obviously, this is a workaround which uses an external SMTP server, but it works! Maybe if I have more time, I will play with sendmail and see if I can get it to work. In the meantime... I'm happy!


W

Bugzilla: Round 2

With the previous installations of Bugzilla, there were several configurations that were missing. Firstly, after logging in as an adminstrator, it was not possible to change any of the parameters using the website. Secondly, emails were not working properly. There were several other configuration mistakes as well, but I will not list them here.

So, I present to you Round 2:

Follow the previous instructions in installing the version from the Ubuntu repos.

If you get an error about not being able to log into database, do the following:

>sudo /etc/bugzilla/localconfig
change $db_pass to the correct password, then save
>sudo apt-get remove bugzilla
>sudo apt-get install bugzilla

This should reinstall bugzilla with the correct password to access the database.

Next, we will upgrade to the latest version (3.1.3 at this time):
1. somehow get the 3.1.3 tarball and store it in /var/www/ (wget or straight from Bugzilla's website)
2. >su
3. >tar -zxvf bugzilla-3.1.3.tar.gz (this will create a folder called bugzilla-3.1.3)
4. >cd bugzilla-3.1.3
5. >./checksetup.pl --check-modules (install anything that it tells you to)
6. >gvim localconfig (or use any editor that you prefer)
6.1 change the $webservergroup from 'apache' to 'www-data' (debian linux uses www-data)
6.2 fill in the $db_pass for the 'bugs' user
6.3 save and quit
7. >./checksetup.pl (this should reconfigure a bunch of templates and set everything up)
8. chmod -R 755 . (not sure if we really need to do this)
9. chmod -R 755 /var/lib/bugzilla/data (not sure if we really need to do this)

Now it's time to replace the originally installed Bugzilla from the Ubuntu repos:
1. cd .. (so now we are back in /var/www/)
2. rm -rf bugzilla/*
3. cp -pr bugzilla-3.1.3/* bugzilla/ (not sure if the p is needed)
4. chown www-data:www-data -R bugzilla

Configure apache:
1. >gvim /etc/apache2/httpd.conf
1.1 add to the bottom if not already there:

<Directory /var/www/bugzilla>
AddHandler cgi-script .cgi
Options +Indexes +ExecCGI
DirectoryIndex index.cgi
AllowOverride Limit
</Directory>
2. >/etc/init.d/apache2 stop

3. >/etc/init.d/apache2 start (perhaps restart will work here too, but this is safer

Now go to your Bugzilla using your browser and login as the administrator. As a hint, you know it worked if you can get to the home page, DON'T see version '2.22.1 Debian' somewhere (the default look is Dusk, so it should look a little dark - not a white background), and you can login.

After logging in, go to the parameters page (.../bugzilla/editparams.cgi). Set the maintainer, then save. If this works, the installation should be working fine. These were all the parts that were originally giving me problems (page not found, could not write, etc, etc, etc!!!).

If you expect emails to work, try creating a new user account and see if you get any emails in the inbox. However, if you are like me and port 25 is blocked, there's more fun to come ahead ;)

Next post, I will go over how to setup Bugzilla when port 80 and 25 are blocked by your ISP.


W

Tuesday, March 18, 2008

Bugzilla Installation on Ubuntu: extra comments

So I was giving Bugzilla a try on my Ubuntu, following the steps in the previous post. All went well, except for one little hiccup.

The bugzilla page would show, except when you tried to log in, it gave you a page not found. Apparently, there is a bug with the default setup in Ubuntu:

https://bugs.launchpad.net/ubuntu/+source/bugzilla/+bug/133903

To fix it, simply go to the params file and modify the 'urlbase' to the correct path (without the '.'). Remember to use sudo!


W

Monday, March 17, 2008

Bugzilla Installation on Ubuntu

the installation guide on bugzilla's website scares me, you can easily spend over a day in order to get it up and running. Fortunately, that's not the case for ubuntu.

with the help of apt-get, we can easily cut it down to 15 mins

1. apt-get install mysql-server (if it's not already there)
2. then follow on screen instructions
3. mysql -u - root -p (we need to create a new user called bugzilla)
4. GRANT ALL PRIVILEGES ON *.* TO 'bugzilla'@'localhost' IDENTIFIED BY 'password';
5. \q
6. apt-get install bugzilla (we are half way done already lol)
7. follow on screen instructions

and you are done! goto http://yourserver/bugzilla and start using it.

the package we just installed is version 2.2, for those who want the latest and greatest, please keep reading, I need another 15 minutes of your time.

1. goto /var/www/ and wget the latest tarball from bugzilla
2. tar -zxvf the_file_you_just_downloaded.tar.gz
3. log back into mysql and create a 'bugs' account (step 3 and 4 from previous section)
4. cd into the newly extracted bugzilla folder
5. cp -pr ../bugzilla/data .
6. sudo ./checksetup.pl
7. sudo chmod -R 755 .
8. sudo chomd -R 755 /var/lib/bugzilla/data
9. open /etc/apache2/httpd.conf

add the following line to the bottom (if it's not there)

<Directory /var/www/bugzilla>
AddHandler cgi-script .cgi
Options +Indexes +ExecCGI
DirectoryIndex index.cgi
AllowOverride Limit
</Directory>
10. restart the server : sudo /etc/init.d/apache2 restart
11. rename the newly extracted folder to bugzilla
12. enjoy


J

Saturday, March 15, 2008

Postgres + Rails + Ubuntu Troubleshooting

Problem 1 - forgotten password for postgres

Solution - TOUGH! you gotta re-install, that's what happened to me

Problem 2 - sudo apt-get remove postgresql did not remove any of the configuration files

Solution - use apt-get purge postgresql instead, this applies to all other packages

Problem 3 - sudo apt-get purge postgresql did not remove all the associated files

Solution - use sudo apt-get purge postgresql* instead or you can run apt-get autoclean after

Problem 4 - postgres refuses connection, but I swear I entered the password correctly!!!

Solution - postgres is very protective, the account you are logging in must match your current linux account .

Problem 5 - But what if I want postgres to manage its own account?

Solution - edit /etc/postgresql/8.1/main/pg_hba.conf, look near the bottom of the file, modify "Unix domain Socket" to local all all md5, "IPv4 local connections" to host all all 127.0.0.1/32 md5

and don't forget to restart the server by doing /etc/init.d/postgres-8.2 restart

Problem 6 - I installed postgres-pr but rails can't connect to postgres and I tried installing the
regular postgres gem but it failed!

Solution - in order to install the postgres gem, make sure you have the libpq-dev gem installed first. (gem install libpq-dev). Try installing the postgres gem again, it should work!

Problem 7 - I want postgres to run on some other port, what can I do?

Solution - first edit the /etc/postgresql/8.2/main/postgresql.conf, change the port number there first (don't forget to restart the server) then you have to goto your rails directly and edit config/database.yml, add ":port [portnumber]" to all your environments.


J

Monday, March 10, 2008

RoR: each

So I was needing to do some eager loading in a very particular way. I had an array of users, and I needed to eager load some tables:

users.each { |user| user.reload(:include => :country) }
# use user.country somewhere down below

Reading the API, it says that it will pass on any options passed into reload to the find. I thought, "Great! It'll eager load things". Well, I was wrong. When I got down to using country, it did another SQL find! I thought that maybe the reload doesn't do eager loading, so I tried to force it:

users.each { |user| user = User.find(user.id, :include => :country) }

This should definitely work, except when I accessed my individual users, they were the same as if I hadn't executed the above line. It seems that the assignment to the user object doesn't change the one in the users array! However, you can change the attributes of the user object. My guess is that when assignment is involved, a new user object is created in the scope of the each block.

I ended up doing a very crude, brute force way:

i = 0
users.each do |user|
users[i] = User.find(user.id, :include => :country)
i = i + 1
end

This has solved my problem, albeit ugly.


W

Sunday, March 2, 2008

Mcolumn reference "id" is ambiguous

Today I tried to improve the performance of my action by doing just one db call through eager loading. For those who have no idea what it is, please read our previous post

http://twoblinddevs.blogspot.com/search?q=eager+loading

This is what I wanted to do

Person.find(:first, :include=>[ :person_info, :messages], :conditions=>["id = :user_id", { :user_id => session[:id]}] )

when I refreshed the browser, it shows me this error message - Mcolumn reference "id" is ambiguous.

The reason rails complain is because all three tables have an id column. In order to work around this problem, you simply have to change id = :user_id to people.id = :user_id


J

Thursday, February 28, 2008

Ubuntu Brainstorm

For those looking to improve Ubuntu further, take a look at this recently created site:

http://brainstorm.ubuntu.com/


W

Wednesday, February 27, 2008

Ubuntu Freeze Ups

In case anyone is running a dual core 64-bit machine with a nVidia graphics card, check out this bug:

https://bugs.launchpad.net/ubuntu/+source/linux-restricted-modules-2.6.22/+bug/145112

You just might end up with system freezes... T.T


W

Sunday, February 24, 2008

Eclipse: To Upper/Lower case

Ever wanted to highlight a word and change everything to upper/lower case in eclipse?

Upper: CTRL + SHIFT + x
Lower: CTRL + SHIRT + y

Enjoy!


W

Saturday, February 16, 2008

Ubuntu: Find and remove files

In certain cases, you want to remove some files, which all have the same name, but perhaps in different folders. And if you're lazy like me, you don't want to go through all the directories and delete it manually. Well, here's a neat little command I found:

>find . -name file_name -print0 | xargs -0 rm

This will find all the files and remove them recursively. If you want to use a regular expression instead of a file name directly, you can use the -regex option instead of the -name option.


W

Ubuntu + No-Ip

If you're running no-ip to update your IP address, you can get it on Ubuntu as well. Use this very helpful tutorial:

http://ubuntulinuxhowto.blogspot.com/2006/06/dynamic-dns-no-ip.html


W

Friday, February 15, 2008

Ubuntu Java Applets

When surfing websites, there are often times when you come across Java Applets. In Firefox, it will ask you to download a plugin. This downloads something called IcedTea.

Well, apparently, it doesn't quite work with a 64-bit machine. I'm not sure about 32-bit machines, but at least on my machine (a 64-bit), it doesn't work. I finally came across a bug that was reported on Ubuntu... and luckily, a fix!

>sudo apt-get build-dep icedtea-java7-plugin
> sudo apt-get -b source icedtea-java7-plugin icedtea-java7-bin icedtea-java7-jre icedtea-java7-jdk
> sudo dpkg -i icedtea-java7-*deb

Word of warning though, this takes a very long time. And by very, I really do mean VERY. After you execute the second line, go for lunch or take a nap. Hopefully it'll be done by the time you get back ;)

After executing the last line, I got a software update message from Ubuntu for the IcedTea plugin. I hit install, and it updated everything for me, and everything works.

To test if it worked, try this:

www.java.com/en/download/help/testvm.xml


W

Ubuntu Screensavers

It's usually very normal to use a screensaver... they're pretty! Well... don't try with Ubuntu's pre-installed screensavers. There may be incompatibility with my computer which caused this, but I'm not sure.

What happened was that when I set my screensaver to braid (I was browsing the screensavers), my Ubuntu froze. I couldn't do anything. Not even Ctrl + Alt + F1 would bring me to a console. I ended up having to press the Shutdown button on my computer! Then when I got back in and tried to change the screensaver back to blank, it would freeze because it was generating the preview for braid... ARGH!!! Also, whenever the screensaver would come on, it would also freeze Ubuntu!

I spent a while trying to figure out how to change the screensaver back to blank... with no luck, but at least I found many people were having the same problems. I then decided to just look around myself and BINGO!

> gedit ~/.gconf/apps/gnome-screensaver/%gconf.xml

Change the screensaver property back to:

screensaver-none

This changes the screensaver back to blank... which I had no problems with to begin with... never touching this thing again unless I know it's ok.


W

Wednesday, February 13, 2008

Ubuntu + Eclipse: Round 2

Ok... so apparently, I was having all sorts of problems with my first installation of Eclipse 3.3. I was getting a whole crap load of exceptions in the logs. Also, every so often, my Eclipse would freeze, then shut down on me without notice, sometimes bringing down Ubuntu as well. Not to mention it didn't save any unsaved data (ARGH!!!).

So... I scrapped it! I removed Eclipse from my system... which took FOREVER. I did:

>sudo apt-get remove --purge eclipse
>sudo apt-get autoremove
>sudo apt-get autoclean

Then I went into /usr/lib and /usr/share to make sure the eclipse folder was gone. I then removed my workspace .eclipse folder. After this, I went into Synaptic package manager and completely removed all Eclipse packages and Sun Java 6 packages. And by all, I mean EVERYTHING!

I then reinstalled Eclipse and Sun Java 6 about 5 or 6 times using Synaptic, with no luck. Eclipse 3.2 wouldn't even start up. It kept complaining about a BundleException. No idea what that was. I finally gave up with Synaptic and went back to apt-get.

>sudo apt-get update
>sudo apt-get dist-upgrade
>sudo apt-get eclipse
>sudo apt-get sun-java6-jdk

Then I added /usr/lib/jvm/java-6-sun to the beginning of the lists in:

>sudo -b gedit /etc/jvm
>sudo -b gedit /etc/eclipse/java_home

I then ran eclipse using the following:

>eclipse -clean

which gave me an error:

searching for compatible vm...
testing /usr/lib/jvm/java-6-sun...found
Could not create /usr/local/lib/eclipse/.eclipseextension. Please run as root:
touch /usr/local/lib/eclipse/.eclipseextension
chmod 2775 /usr/local/lib/eclipse/.eclipseextension
chown root:staff /usr/local/lib/eclipse/.eclipseextension

So I did:

>sudo touch /usr/local/lib/eclipse/.eclipseextension
>sudo chmod 2775 /usr/local/lib/eclipse/.eclipseextension
>sudo chown root:staff /usr/local/lib/eclipse/.eclipseextension

Then ran again:

>eclipse -clean

This time, Eclipse 3.2 started up with no exceptions in the logs! YAY!

Not done yet... will try to install Aptana + RadRails + SubClipse now... wish me luck!

UPDATE:
After installing Aptana, everything seems to be running fine. Eclipse did not shut down on me... so I continued to install RadRails.

After installing RadRails, I checked the logs, and I got several exceptions. As I continued to use Eclipse, I continued to get a whole load of errors. However, Everything continued to work fine. I'm not sure what the error messages are, but they weren't bothering me, so I decided not to bother them!

Next came SubClipse. This installed without problems as well! And now I'm happily coding away again! Yay! Nightmare over! ...for now...


W

Ubuntu Firefox Fonts

After moving to Ubuntu, our website was completely out of alignment when using Firefox. We had set our default the usual:

font-family: Arial, Helvetica, sans-serif;

Of course, Arial is a MS font. We decided that as a linux user, you would be expected to know how to tweak your computer, and hence it is reasonable to expect a linux user to know how to change their fonts.

To use Arial in your Firefox, do the following:

>sudo apt-get install msttcorefonts

and wait for a while. Maybe go have a coffee ;)

Afterwards, log out and log back in so that the new fonts can be loaded.

Next, you have to let Firefox know you want to use Arial. Go to:

Edit > Preferences > Content > Fonts & Colors > Advanced

Then change what you want to Arial. I set my serif and sans-serif to Arial. This seemed to do the trick, at least for our website.


W

Tuesday, February 12, 2008

attachment_fu - Controller and View

Upload Image - after all the hard work trying configuring the damn thing, this is where it pays dividends. To create an upload form, all we need are three lines:

<% form_for(:photo, @photo, :url => some_path,
:html => { :multipart => true }) do |f| %>

<%= f.file_field :uploaded_data %> <%= submit_tag "Upload" %>

<% end %>

make sure multipart is set to true, or else it won't work.
Over to the controller side, you just do what you normally do with other create actions

def create

@photo = Photo.new params[:photo]
if @photo.save ... yayaya

and the rest will be handled by attachment_fu

Listing Images - once again, three lines

<% for pic in @photo %>
<%= link_to image_tag(pic.public_filename(:thumb)), pic.public_filename %>
<% end %>

sticking in the :thumb will grab all the thumbnails, leaving it out will grab the bigger version

example:

photo.public_filename #=> /photo/2/file.jpg
photo.public_filename(:thumb) #=> /photo/2/file_thumb.jpg

Delete Image - it's just like any other objects

@photo = Photo.find(id)
@photo.destroy


J

attachment_fu - configurations

In our model, we'll use the has_attachment command to hook into attachment_fu.

example:

has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 500.kilobytes,
:resize_to => '320x200>',
:thumbnails => { :thumb => '100x100>' }
:processor => 'Rmagick'

validates_as_attachment

Let's look at each option in detail

for storage, you have three options, :db_system (default), :file_system, or :S3. If you are using :db_system, attachment_fu will convert and save the image to your db as a BLOB (binary large object). If :file_system is used, the file will be saved to your hard disk. If :S3 is used, image will be saved to Amazon's S3 server.

:max_size lets you specific the maximum size of the photo, and there's also a :min_size which works the other way

:resize_to - resize your image to an acceptable width and height like facebook :) It takes a string called the Geometry String, which has the format:

< width > x < height > + - < x > + - < y > { % @ ! < > }

where any of the field can be omitted.

By default, width and height are the maximum value. If you enter something like '300x500' the image will expand or contract to fit the width and height value while maintaining the aspect ratio of the image.

If you want to enforce the image size to be exactly the size you specify, you can append an exclamation mark in the end like so: '300x500!'

You can also specify either the width '300' or the height 'x500' where the missing parameter will be chosen to maintain the aspect ratio

You can append % to specify percentage width and height ('110%' - increase, '90%' - decrease, '110%x90%' = increase width, decrease, height)

You can use @ to specify the maximum area in pixels of an image (I don't see how this is gonna be useful)

You can use < or > to change the dimensions of the image only if its width or height exceeds the geometry specification. < resizes the image only if both of its dimensions are less than the geometry specification. For example, if you specify '300x500>' and the image size is '250x250', the image size will not change. However if the image is '1000x1000', the it'll be resized to '300x300' and vice versa.

Finally x and y are offsets for width and height. + causes x and y to be measured from the left or top edges and - measures from the right or bottom edges. And they are always measured in pixels.

:thumbnails - a set of thumbnails to generate, specified by a has of filename suffixes and resizing options. You can omitted it if you don't want thumbnails. Generating multiple thumbnails will look something like this

:thumbnails => { :thumb_big => '500x500', :thumb_small => '100x100' }

:thumbnail_class - set what class to use for thumbnails (defaulted to whatever model you are in) However, you can generate a seperate model with seperate set of validations

:processor - 'ImageScience', 'Rmagick', or 'MiniMagick'. I like Rmagick cause it has the most features, but MiniMagick is less of a memory hog.

:path_prefix - Path to store the uploaded files, which defaults to public/your_table_name
If you are using S3 backend, it defaults to just your_table_name

validates_as_attachment does all the validations for you, so you have nothing to worry about :)


J