Posted by Ben Reubenstein
Sun, 13 Jan 2008 20:00:00 GMT
My nephew has been saving his money to purchase a new laptop. He enjoys playing flashed based games, and is known to play RuneScape. Just recently he managed to scrap together $350.00 for the purchase. I found a laptop for exactly $350, but after closer examination found it did not include wireless. For $50 more I found a Lenovo 3000 N200 with wireless so with a little help from his Grandpa to make up the difference, we were off to the store.
Here are the specs for the box:
15.4" widescreen WXGA TFT LCD display
Intel Celeron M 1.73GHz Processor
512MB DDR2 Memory and 80GB Hard Drive
Windows Vista Home Basic
CD-RW / DVD-ROM Combo Drive
I found an employee at MicroCenter and requested to purchase the machine. He enquired if I had been told about it and I replied no, I would like to buy that machine. He informed me that it was only good for Internet and "wouldn't do pictures" since it was not very fast. I told him I was planning to ditch the Vista Home Basic for Linux. He was convinced that wouldn't work, so at that point I gave up, and told him flat out, please just get me the box. On our way out I think he told his supervisor that I was crazy, but oh well I was out the door.
Now I know this is a Windows world, so the plan is to setup a dual boot. Just starting the machine for the first time however took 20 minutes. Windows Vista had to check out the performance of the box, and slowly allow me in. Once in my nephew and I were greeted with 6 shortcuts on the desktop to products we could purchase and a ton of tiny icons already running in the task bar for various media programs and other crap.
We installed Ubuntu on the box next. This process took about 20 minutes, and it handled resizing the existing windows partition and putting the necessary GRUB entries in. It started up quickly and the only time consuming issue I had was getting the wireless card to work. After that however, we were cooking. The machine was extremely responsive compared to Windows Vista. It also included all the productivity software my nephew would need.
It is criminal that this machine is sold with Windows Vista. It is in no way capable of running it with out a significant bump in RAM. I can now understand the hesitance with which it was sold to me.
Posted by Ben Reubenstein
Fri, 04 Jan 2008 17:50:00 GMT
In the beginning there was file_column. It was an excellent plugin for handling file uploads and image processing with the added bonus of being able to simply pass a file to it and have it work without a file upload via a form. One thing that file_column didn't do was fill in your db with file attribute goodness that could be used to create logic around a particular file. attachment_fu handled this along with the ability to use multiple image processors. For detailed info on attachment_fu, check out Mike Clark's article.
In order to add some local_file_fu to attachment_fu so you can pass a local file directly to it, you have to take your local file and turn it into a temporary file that you can pass to attachment_fu's uploaded_data method. I altered the solution outlined here for my solution.
1. Create a class in your models directory in a file called local_file.rb.
require 'tempfile'
class LocalFile
# The filename, *not* including the path, of the "uploaded" file
attr_reader :original_filename
# The content type of the "uploaded" file
attr_reader :content_type
def initialize(path)
raise "#{path} file does not exist" unless File.exist?(path)
content_type ||= @@image_mime_types[File.extname(path)]
raise "Unrecognized MIME type for #{path}" unless content_type
@content_type = content_type
@original_filename = File.basename(path)
@tempfile = Tempfile.new(@original_filename)
FileUtils.copy_file(path, @tempfile.path)
end
def path #:nodoc:
@tempfile.path
end
alias local_path path
def method_missing(method_name, *args, &block) #:nodoc:
@tempfile.send(method_name, *args, &block)
end
end
2. In order for attachment_fu to pass validations, you need to set the mime type of the file. This would usually come from the form when it is uploaded, but since we are using a local file, we'll set our mime types in environment.rb. At the end of the file add the various mime types you will need:
Posted by Ben Reubenstein
Mon, 24 Dec 2007 15:11:00 GMT
This past week I needed to implement a small webservice that needed to be fast and work well under a heavy load. I had part of the service implemented in Rails, but it was not as fast as I thought it could be so I decided to check out Merb. Merb is a lightweight MVC framework much like Rails. Merb however doesn't try to put a lot of "magic" at its core, so overall less time is spent in the framework and more time is spent in your code.
When I jumped into Merb, there were a lot of good articles but not much on how to productionize Merb, so I hope I can fill in the gap with this article.
NOTE: I am explaining a lot here, so if you run into spots that are confusing or you think could be done more efficiently, comment and I will get those adjustments into the doc.
Setting up Capistrano (Using 2.0)
Install Capistrano:
gem install capistrano
Like Rails apps there are certain files that will change in the production environment so they should not be in your repo. The ones I chose to exclude:
config/merb.yml
config/database.yml
Your excluded files may differ depending on the ORM you chose. I setup DataMapper for this particular application, though you could install the merb_activerecord gem and plug right into ActiveRecord.
Just like in a rails app run the capify command to get rolling:
Edit your config/deploy.rb to match your settings here is my example with some notes:
set :application, "YOUR_APPLICATION_NAME"
# Set the path to your version control system (Subversion assumed)
set :repository, "http://something.com/svn/yourapplication/trunk"
# Set your SVN and SSH User
set :user, "your_ssh_user"
set :svn_user, "your_svn_user"
#Set the full path to your application on the server
set :deploy_to, "/PATH/TO/YOUR/#{application}"
#Define your servers
role :app, "your.appserver.com"
role :web, "your.webserver.com"
role :db, "your.databaseserver.com", :primary => true
desc "Link in the production extras and Migrate the Database ;)"
task :after_update_code do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
run "ln -nfs #{shared_path}/config/merb.yml #{release_path}/config/merb.yml"
run "ln -nfs #{shared_path}/log #{release_path}/log"
#if you use ActiveRecord, migrate the DB
#deploy.migrate
end
desc "Merb it up with"
deploy.task :restart do
run "cd #{current_path};./script/stop_merb"
run "cd #{current_path};env EVENT=1 merb -c 4"
# If you want to run standard mongrel use this:
# run "cd #{current_path};merb -c 4"
end
#Overwrite the default deploy.migrate as it calls:
#rake RAILS_ENV=production db:migrate
#desc "MIGRATE THE DB! ActiveRecord"
#deploy.task :migrate do
# run "cd #{release_path}; rake db:migrate MERB_ENV=production"
#end
Use Capistrano to initiate the environment, setting up the necessary directories on the server.
$ cap deploy:setup
Next, install the Gems you need on the Production server.
Note: if you are on the gem 0.9.4 run this upgrade, 0.9.5 is super nice ;). the -y / --include-dependencies option is on by default.
sudo gem update --system
sudo gem install merb
sudo gem install rspec
# For ActiveRecord
sudo gem install merb_activerecord
# For DataMapper
sudo gem install datamapper
sudo gem install do_mysql
# For Evented Mongrel
sudo gem install swiftiply
Create the directories and files that will be linked in.
Edit the .yml files to your liking and then be sure to create your database in MySQL! There is probably some neat deploy tricks you can do here with Capistrano, comment if you know it and I will update this section.
Deploy your app:
cap deploy
Now if you are amazing, it works the first time. If not check the errors. Most of them will likely be paths or a gem you missed.
Recap: We should now have our app deployed to the server and if you used the example config, 4 instances running. Hooray!
Setting up: NGINX
General Tip: If your server is still using Apache and you are just starting to experiment, run NGINX on another port, like 81. Be sure to clear a path through your Firewall ;)
Add the appropriate ip:ports to the upstream section for the merb instances you are running. The port that merb runs on and number of instances started are controlled by the deployment script and the merb.yml file.
upstream YOURUPSTREAMNAME {
server 127.0.0.1:4000;
server 127.0.0.1:4001;
server 127.0.0.1:4002;
server 127.0.0.1:4003;
}
Next lets add in a host section. This is just like a Rails host.
server {
listen 80;
client_max_body_size 50M;
server_name YOURSERVERNAME;
root /YOURPATH/current/public;
#Want to log? include this
#access_log /var/log/nginx/nginx.YOURAPPNAME.access.log main;
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html last;
break;
}
if (-f $request_filename.html) {
rewrite (.*) $1.html break;
}
if (!-f $request_filename) {
proxy_pass http://YOURUPSTREAMNAME;
break;
}
}
error_page 500 502 503 504 /500.html;
location = /500.html {
root /YOURPATH/current/public;
}
}
Restart nginx and enjoy your new Merb application!
Thanks to the folks in #merb and #datamapper for answering questions I had. Special thanks to Ezra for creating Merb and pushing performance in the Ruby web application world.
Posted by Ben Reubenstein
Thu, 23 Aug 2007 13:35:00 GMT
I am sitting at DIA getting ready to fly out to San Francisco for the iPhone tech talk. Should be interesting to meet some other developers and get insight on the platform. I will be live txt'ing right here, so simply tune in every so often to see new pics and messages. Live feed removed now that event has ended.
Posted by Ben Reubenstein
Tue, 31 Jul 2007 13:04:00 GMT
Today I was doing some massive migrations that rocked the very foundations of an app I am working on. Problem was that during the migration I was moving objects around the database and validations were failing for my saves. To get some debugging going, I started out trying to write to the logger, with some good ol' logger.debug, but that does not work within a migration. To output information in a migration, use puts. So for example to see all the errors that prevented object g from being saved:
class MyMigration < ActiveRecord::Migration
def self.up
g = G.new(:name => "name" )
if g.save
#More object manipulation here
else
g.errors.each do |x|
puts x
end
end
end