Dec 16
EventMachine Asynchronous HTTP Client – Custom Headers (User-Agent)
If you have a need to set custom request headers like User-Agent or Host, here is how you do so via the EM client
http = EventMachine::HttpRequest.new(url) .get(:head => {"User-Agent" => "Custom Agent"})
Dec 9
iPhone 3g Jailbreak 4.2.1 SpringBoard crash and Linux mount
After updating to 4.2.1 and untethered jailbreak via redsn0w on my iPhone 3g, I had two major issues. The first issue has to do with multitasking. The springboard would crash when using the fast switching. This was fixed by changing the following lines in /System/Library/CoreServices/SpringBoard.app/N82AP.plist
<key>opengles-1</key>
to
<key>opengles-2</key>
The next problem was mounting my iPhone in Ubuntu Linux. The error message will contain something about a timeout. If this is happening you probably need to re-pair the device by doing the following via the libimobledevice utils:
idevicepair unpair idevicepair pair idevicepair validate
Dec 6
Apache Phusion Passenger: Apache 2 not found
This may be pretty basic, but figured it may be useful to others. According to the passenger docs, it will look for Apache in the $PATH environment variable. So to fix the Apache 2 not found error, you first need to find the install location. A very helpful command is “whereis” that comes standard on most *NIX systems. If you have whereis installed copy/paste the following into the command line
APACHE_PATH=`whereis apache | awk '{ print $2 }'`
That will set APACHE_PATH to the path returned from whereis. Before you continue, please make sure the path was set properly.
echo $APACHE_PATH
If everything looks good, update the $PATH environment variable.
export PATH=$APACHE_PATH/bin:$PATH
Then check path to ensure it was updated
echo $PATH
Nov 12
Ruby 1.9 CSV undefined method map for String
I’m in the process of upgrading an app running Ruby EE 1.8.7 to Ruby 1.9.2. Since FasterCSV is no longer available, I had to convert the code to use the internal CSV lib. In doing so, I ran into the above error. Looking at the source for FasterCSV <<, there was a catchall else statement that would handle passing a string and convert it to an array to become a row.
def <<(arg) if arg.is_a?(Array) and arg.size == 2 # appending a header and name @row << arg elsif arg.is_a?(Hash) # append header and name pairs arg.each { |pair| @row << pair } else # append field value @row << [nil, arg] end self # for chaining end
In Ruby 1.9 the CSV << method is expecting an Array or CSV::Row. Easiest fix for me as to just make my string an Array. Hope this helps!
1 commentNov 5
Ubuntu 10.10 Thunderbird 3.1.6 LastPass addon disables password manager
In my quest to find a good password solution, I tried LastPass. This was a very intrusive password manager on both Firefox and Thunderbird. I promptly removed it after about a day of use. However, removal of the addon left traces of itself throughout my settings. It completely disabled Thunderbird’s integrated password manager. I was lucky enough to find an article at mozillaZine with details on how to re-enable this feature.
Here are the details from their site:
No checkbox to remember passwords
It can happen that you will find no checkbox in Thunderbird to remember passwords. To change this, you will need to edit the prefs.js file, located in the Thunderbird profile folder.
1. Close Thunderbird and open the prefs.js file in Notepad or another editor (make a backup copy of prefs.js first, as a precaution).
2. Find the following line: user_pref(“signon.rememberSignons”, false);
3. Change the value from false to true.
4. Close the Notepad or editor window and save changes.
5. On the next startup of Thunderbird you should find the checkbox for remembering the password in the password manager.Instead of editing prefs.js, you can change the same setting via about:config.
While editing prefs.js, I found lots of settings that LastPass left behind. Also, in Firefox “about:config” shows the same situation. All in all, LastPass was a horrible solution. I changed to using FF and Thunderbirds built in password manager with a master password.
1 commentAug 3
Prototype JS default function arguments
$H() is just one more reason to use Prototype. Coming from a Ruby background, I’ve become very fond of using hashes. I often use them in handling optional arguments to methods, and setting default values for those arguments. I was creating a function in JS, and realized using such methodology would allow for a much more descriptive function.
function handle_notice(options) { var default_options = $H({show_notice: false, show_ignore: false}) options = default_options.merge($H(options)) ... }
The above sets up a hash of default options, then merges or updates the default_options with the options hash passed to the function. This allows me to use any combination of arguments, or pass none to use the default.
1 commentApr 23
Handy ActiveRecord Migration Methods
We are undergoing a massive DB schema redesign. Much of the work is just tightening up the schema through optimizing indexes, setting default boolean and integer fields, and updating NULL allowed fields. Here is a little module I wrote to save massive amounts of code.
module MigrationHelper def index_exists?(table, lookup) lookup = Hash[:columns, Array(lookup)] unless lookup.is_a?(Hash) lookup.symbolize_keys! lookup.each{|key,value|lookup[key]=(value.is_a?(Array))?(value.collect{|v|v.to_s}):(value.to_s)} indexes(table).collect(&lookup.keys.first).include?(lookup.values.first) end def change_column_nulls(table_name, nullable, *column_names) column_names.each do |column_name| table_columns = columns(table_name) column_def = table_columns.select{|c|c.name == column_name.to_s} raise "Unknown column name #{column_name} for #{table_name}\nAvailable columns: #{table_columns.collect(&:name).to_sentence}" if column_def.empty? change_column table_name, column_name, column_def.first.type, :null => nullable end end def change_column_defaults(table_name, default, *column_names) column_names.each do |column_name| change_column_default table_name, column_name, default end end end
I fond it necessary to have the index_exists? method mainly for my development purposes. When I’m optimizing tables by doing complex indexes, I often do them right on the DB first before throwing them into a migration. By having this check I can easily skip over it if it already exists. It takes the same options as add_index. You can pass table and column names, or just table and index name. Here are some usage examples:
add_index :table, :column unless index_exists?(:table, :column) add_index :table, [:column1, :column2] unless index_exists?(:table, [:column1, :column2]) add_index :table, [:column1, :column2, :column3], :name => "some_index_name" unless index_exists?(:table, :name => "some_index_name")
The method change_column_nulls is used to mass change the NULL allowed columns for a given table. Really not much to it, but saves a lot of code over doing change_table or change_column. Here is the usage:
change_column_nulls :table, false, :column1, :column2
And lastly change_column_defaults is just a wrapper around change_column_default for mass assignment. Usage is the same as change_column_nulls passing the default values as the second argument. I thought about combining the two, but it didn’t offer very much savings.
These were tested using MySql 5. I’m not sure about the compatibility with other servers.
No commentsMar 26
Rails ActiveRecord MySql varbinary
Although ActiveRecord has the following warning about database specific column types: “You may use a type not in this list as long as it is supported by your database (for example, “polygon” in MySQL), but this will not be database agnostic and should usually be avoided. ActiveRecord” You may have optimizations specific to a database server like MySql’s varbinary. Here is how to create the a table with a varbinary(1000) column.
create_table :page_error_sources do |t| t.column :source, 'varbinary(1000)', :null => false t.timestamps end
Mar 3
Solr 1.4 Upgrade P2 – Out with Rsync CollectionDistribution in with JavaReplication
Solr 1.4 made replication from Master to Slave servers a whole lot easier. Before solr1.4 we were using rsync via the snapshooter and snappuller scripts As seen here. This method worked OK, but intermittently we would see the snapshooter or puller fail for various Java reasons (Memory usually).
Please see Solr Java-Based Replication for setup overview. I will cover specific modification I had to make compared to what is in their documentation. In my solrconfig.xml on my Master server, I have the following:
<requestHandler name="/replication" class="solr.ReplicationHandler" > <lst name="master"> <!--Replicate on 'startup' and 'commit'. 'optimize' is also a valid value for replicateAfter. --> <str name="replicateAfter">startup</str> <str name="replicateAfter">commit</str> </lst> </requestHandler>
Then on the slave servers, I have:
<requestHandler name="/replication" class="solr.ReplicationHandler" > <lst name="slave"> <!--fully qualified url for the replication handler of master . It is possible to pass on this as a request param for the fetchindex command--> <str name="masterUrl">http://{solr_host}:{solr_port}/solr/${solr.core.name}/replication</str> <!--Interval in which the slave should poll master .Format is HH:mm:ss . If this is absent slave does not poll automatically. But a fetchindex can be triggered from the admin or the http API --> <str name="pollInterval">00:00:30</str> <str name="httpReadTimeout">10000</str>--> </lst> </requestHandler>
Substitute {solr_host} and {solr_port} with your specific settings. IMPORTANT: Note the ${solr.core.name} variable. This makes it so the slaves will poll from the correct MultiCore path on the Master server.
3 commentsFeb 1
Solr 1.4 Upgrade – Out with Faceting, In with MultiCore
I finally found some time, though it was a bit forced, to look into the new CoreAdmin functionality released in Solr 1.4. Our app was using the same index for multiple apps distinguished through Faceting. This worked fine for a while, but the larger our indexed data got, the slower the queries were returned. The responsiveness of every app was now dependent on the total indexed size. This was not ideal, so we upgraded to 1.4 to see how using multiple cores could help.
Upgrading was quite easy. See http://wiki.apache.org/solr/Solr1.4 for upgrading notes. What I will focus on are the details of using and automating the MultiCore functionality. To enable the dynamic SolrCore functionality, you just need to put the following XML in solr.xml inside your solr_home directory.
<solr persistent="true" sharedLib="lib"> <cores adminPath="/admin/cores"> </cores> </solr>
Don’t worry about creating any cores at this time. The next thing I did was create a directory called “default” in my solr_home directory to store all of my shared configs for each core. I then copied the conf/ directory from my solr_home into the newly created default dir.
The final step is to create the cores needed. You can automate this by posting the following request and checking the XML response, or by just pasting this into your browser.
http://{host}:{port}/{solr_home}/admin/cores?action=CREATE&name={core_name}&instanceDir=default&dataDir={/full/path/to/solr/home}/{core_name}
Here is how you automate the request using xml-simple and ruby
#set the url string equal to the above command response = Net::HTTP.get_response(URI.parse(url)).body xml = XmlSimple.xml_in(response, {'VarAttr' => 'name', 'ContentKey' => '-content', 'KeyAttr' => 'name'}) raise "Failed to create solr core" if xml["lst"]["responseHeader"]["int"]["status"].to_i != 0
No comments

