Aug 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
Oct 15
iPhone 3g 3.1.2 jailbreak update PwnageTool
I updated my jailbroken iPhone to 3.1 when it first came out and had some major issues that required almost a daily hard reboot. I successfully downgraded it to 3.0.1, but still had some baseband issues with the service (phone and sms) not working. I was very excited to see the iPhone Dev Team came out with a 3.1.2 jailbreak using PwnageTool 3.1.4
Since I was already jailbroken, I simply built the custom IPSW, and clicked Option+Restore in iTunes. Everything went as expected, and I finally have a stable phone again.
I’ve been jailbreaking my phone since I first got it over a year ago, and I’m so glad to see the process getting easier and smoother every time. Big thanks to the iPhone Dev Team and all their hard work.
Here are the steps I took in case you are already jailbroken and just want the bug fixes and 3.1 update.
- Requirements
- Mac OS X
- iTunes 9.0.1
- Already jailbroken iPhone 3G on 3.0 firmware
- Backups!
- Steps
- Check for updates in iTunes
- Choose to download only for the update
- Download PwnageTool 3.1.4 Torrent Mirror
- Launch PwnageTool and go walk through the steps to create your custom IPSW
- Answer Yes to already jailbroken and exit the app when prompted
- Launch iTunes and hold the Option key and click Restore
- Select your custom IPSW file (probably on your destop)
- Enjoy your new 3.1.2 jailbreak
Jul 31
Aggregation with MySQL and ActiveRecord
I had some data that I wanted to aggregate by year for a flash graphing app called amCharts. Here was the SQL query I used to gather the data:
SELECT AVG(column1) AS column1, AVG(column2) AS column2 FROM table1 t1 JOIN table2 t2 ON t2.id = t1.tabel2_id GROUP BY YEAR(t2.datetime_field)
Rather than using this sql in ActiveRecord via find_by_sql, I figured I’d make it pretty and use the built in find method. Here is what I came up with:
Table1.find(:all, :select => 't2_id, AVG(column1) as column1, AVG(column2) as column2', :joins => :t2, :group => 'YEAR(t2.datetime_field)')
The :select option allows you to define the attributes you want returned with the AR object. I’m using MySQL to do the averaging of the data via the AVG function. I would normally use the :include option for joins, but I couldn’t get it to work with this query, so the :joins option seemed to work well by passing it the association definition from the model. The :group option simply works the same as the SQL group by. Just pass it a sql fragment, in my case just the year field portion of the datetime field.
No commentsJun 25
RJS redirect_to params contain &
I came across this today when I added a parameter to a RJS page.redirect_to call. It appears that prototype or rails is not properly handling the parameters when there are more than 2. I got around it by using a defined route in the routes.rb that looks like this:
map.route_name 'controller_name/action_name/:foo_id', :controller => 'controller_name', :action => 'action_name'
I had to change the redirect_to in my RJS file from this:
page.redirect_to page_recrawl_path(:foo_id => @foo_id, :bar_id => @bar_id, :bang => true)
To this:
page.redirect_to page_recrawl_path(@foo_id, {:bar_id => @bar_id, :bang => true})
Jun 20
Jailbroken iPhone 3g 3.0 firmware
Thanks to the iPhone Dev-Team for releasing the Pwnage Tool 3.0, I was able to upgrade to the jailbroken 3.0 firmware. The install process went very smoothly. I followed a similar procedure to what they demo’d on their youtube video. Some of my favorite jailbroken apps don’t work with the new firmware. Here are my findings:
Apps
- Cycorder: Yes
- OpenSSH: Yes
- SBS Settings: Yes
- Icy: Yes
- Cydia: Stability issues
- PdaNet: Yes, but possible stability issues
- Winterboard: Mostly, some themes weren’t stable
- Pwnplayer: no
- Snapture: no
- NES: no
Overall the new 3.0 features were well worth upgrading. The only app I will really miss is Pwn player and I hope there will be a similar replacement (it’s no longer maintained). As for the other apps, I’m sure they’ll be getting updates soon. Please let me know what apps you have working.
1 commentJun 2
Ruby on Rails background process: MySQL server has gone away
Using workling and starling to handle background tasks is very nice. Check out this link for info on setting it up. However, I encountered the error: “Mysql::Error: MySQL server has gone away” when accessing an external DB tables like users and roles. I found that someone recommended using verify_active_connections!, however the table the connection error occurred on was a HABTM table ‘user_roles’. I found that verify_active_connections will use the scope of the model/object you invoke it on. So the final solution was to do the following:
user.roles.verify_active_connections!
This will make sure users, user_roles, and roles all have valid connections. This error occurred using rails 2.0.1. It may be fixed in newer versions of ActiveRecord.
No comments
