<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7812374370851301442</id><updated>2012-02-16T03:00:59.245-08:00</updated><category term='Downloads'/><category term='Algorithms'/><category term='Ruby'/><category term='Linux'/><category term='Music'/><category term='Rails'/><category term='Networking'/><title type='text'>Sam Staff</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-8622556919032502591</id><published>2010-01-11T20:15:00.000-08:00</published><updated>2010-01-11T20:49:36.704-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Ajax sorting and pagination</title><content type='html'>Basically we need to put a link on every table header in order to make a request to the server passing in the parameters&lt;br /&gt;needed to know by which attribute to order and in which order.&lt;br /&gt;&lt;br /&gt;We need 2 methods:&lt;br /&gt;The first one is a helper method to create the link with the appropiate parameters, the link must send the attribute that &lt;br /&gt;is ordering by and the order(ASC or DESC). &lt;br /&gt;And the second is a controller method that reads the sent parameters, and generate the appropiate order in the sql query.&lt;br /&gt;&lt;br /&gt;So there are a helper and a controller method, I created the following module and put it in the lib directory&lt;br /&gt;with the mentioned methods, to have the whole sorting solution in one file (I could also have added the methods to &lt;br /&gt;application_helper and application_controller respectively)&lt;br /&gt;In this case I created 2 helper methods for generating standard and ajax links.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;module SortingMethods&lt;br /&gt;&lt;br /&gt;  def self.included(base)&lt;br /&gt;    base.class_eval do&lt;br /&gt;      helper_method :remote_sort_link, :sort_link&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def order_or_default(default_attr, default_order = 'ASC')&lt;br /&gt;    if !params[:attr].blank? &amp;&amp; !params[:order].blank? &amp;&amp; &lt;br /&gt;        params[:attr] =~ /\A\w+\z/ &amp;&amp; &lt;br /&gt;       (params[:order] == 'ASC' || params[:order] == 'DESC')&lt;br /&gt;      params[:attr] + ' ' + params[:order]&lt;br /&gt;    else&lt;br /&gt;      default_attr + ' ' + default_order&lt;br /&gt;    end&lt;br /&gt;  end  &lt;br /&gt;&lt;br /&gt;  def remote_sort_link(text, attribute, extra_params = {})&lt;br /&gt;    query_params = params.reject{|key, value| key == 'controller' || key == 'action'}&lt;br /&gt;    if query_params[:attr] == attribute.to_s &lt;br /&gt;      link_text = text + " (-o-)" &lt;br /&gt;      query_params[:order] == 'ASC' ? query_params[:order] = 'DESC' : query_params[:order] = 'ASC'&lt;br /&gt;    else&lt;br /&gt;      link_text = text &lt;br /&gt;      query_params[:order] == 'ASC'&lt;br /&gt;    end&lt;br /&gt;    query_params[:attr] = attribute.to_s    &lt;br /&gt;    @template.link_to_remote link_text, :url =&gt; request.url.split('?')[0] + '?' + &lt;br /&gt;      extra_params.merge(query_params).to_query, :method =&gt; :get&lt;br /&gt;  end  &lt;br /&gt;  &lt;br /&gt;  def sort_link(text, attribute, extra_params = {})&lt;br /&gt;    query_params = params.reject{|key, value| key == 'controller' || key == 'action'}&lt;br /&gt;    if query_params[:attr] == attribute.to_s &lt;br /&gt;      link_text = text + " (-o-)" &lt;br /&gt;      query_params[:order] == 'ASC' ? query_params[:order] = 'DESC' : query_params[:order] = 'ASC'&lt;br /&gt;    else&lt;br /&gt;      link_text = text &lt;br /&gt;      query_params[:order] == 'ASC'&lt;br /&gt;    end&lt;br /&gt;    query_params[:attr] = attribute.to_s    &lt;br /&gt;    @template.link_to link_text, request.url.split('?')[0] + '?' + &lt;br /&gt;      extra_params.merge(query_params).to_query&lt;br /&gt;  end  &lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The helper method check which is the actual ordering attribute and invert it, or just put the default ASC order. And also does a little bit of escaping.&lt;br /&gt;&lt;br /&gt;To get the functionality, you need to include the module in the controller you are ordering by, or in application_controller to get it on every controller.&lt;br /&gt;&lt;br /&gt;Suppose you are listing users with name and age.&lt;br /&gt;If you are doing ajax calls like in this case you will have to update the sorting links in the ajax call, so you can put &lt;br /&gt;the whole table in a partial and then update the partial, like I am showing here:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;div id=&amp;quot;user_update&amp;quot;&amp;gt;&lt;br /&gt;&amp;lt;!-- this goes in _users.html.erb partial --&amp;gt;&lt;br /&gt;  &amp;lt;table&amp;gt;&lt;br /&gt;    &amp;lt;tr&amp;gt;&lt;br /&gt;      &amp;lt;th&amp;gt;&lt;br /&gt;        &amp;lt;%= remote_sort_link('Name', :name) %&amp;gt;&lt;br /&gt;      &amp;lt;/th&amp;gt;&lt;br /&gt;      &amp;lt;th&amp;gt;&lt;br /&gt;        &amp;lt;%= remote_sort_link('Age', :age) %&amp;gt;&lt;br /&gt;      &amp;lt;/th&amp;gt;&lt;br /&gt;    &amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;% for user in @users %&amp;gt;&lt;br /&gt;      &amp;lt;tr&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;%= user.name %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;        &amp;lt;td&amp;gt;&amp;lt;%= user.age %&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;      &amp;lt;/tr&amp;gt;&lt;br /&gt;    &amp;lt;% end %&amp;gt;&lt;br /&gt;  &amp;lt;/table&amp;gt;&lt;br /&gt;&amp;lt;!-- ---------------------------------------   --&amp;gt;&lt;br /&gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and in the controller:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def index&lt;br /&gt;  @users = User.all(:order =&gt; order_or_default('name'))&lt;br /&gt;  respond_to do |format|&lt;br /&gt;    format.html&lt;br /&gt;    format.js &lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In index.rjs you should update the partial:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;page.replace_html 'user_update', :partial =&gt; 'users'&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You can use it with will_paginate because the query string is mantained between requests. So the links will be &lt;br /&gt;generated with the query string that was on the last request. &lt;br /&gt;There is a &lt;a href="http://samstaff.blogspot.com/2009/02/using-willpaginate-rails-plugin-with.html"&gt;previous post&lt;/a&gt; where I explain how I use will_paginate plugin with ajax, you could easily add that here and you get both ajaxified pagination and sorting.&lt;br /&gt;Also note that I added " (-o-)" to the link text of the attribute that is currently being sorted by. You probably want &lt;br /&gt;to change this to add anything you want, also you can easily change the generated link_to or link_to_remote class.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-8622556919032502591?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/8622556919032502591/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=8622556919032502591' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/8622556919032502591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/8622556919032502591'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2010/01/ajax-sorting-and-pagination.html' title='Ajax sorting and pagination'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-6034149275468463181</id><published>2009-12-13T14:31:00.000-08:00</published><updated>2010-01-11T20:49:36.704-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Storing single values in Rails with ActiveRecord</title><content type='html'>Sometimes you want to store a bunch of single values that are not related to anything, and of course they are not constant values, it is better to put it in a constant or in a yaml config file if they are constant values.&lt;br /&gt;&lt;br /&gt;This is what i usually do, maybe there is a better solution out there, but this one is very simple.&lt;br /&gt;It's kind of make an active record object to work like a Hash, or key-value store.&lt;br /&gt;&lt;br /&gt;Create the migration(name it the way you like it):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class CreateSingleValues &lt; ActiveRecord::Migration&lt;br /&gt;  def self.up&lt;br /&gt;    create_table :single_values do |t|&lt;br /&gt;      t.string :key&lt;br /&gt;      t.string :value&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.down&lt;br /&gt;    drop_table :single_values&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And this is the code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class SingleValue &lt; ActiveRecord::Base&lt;br /&gt;&lt;br /&gt;  def self.[](key)&lt;br /&gt;    val = self.find_by_key(key.to_s)&lt;br /&gt;    val.value if val&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.[]=(key, value)&lt;br /&gt;    val = self.find_by_key(key.to_s)&lt;br /&gt;    if val&lt;br /&gt;      value.nil? ? val.delete : val.update_attribute(:value, value)&lt;br /&gt;    else&lt;br /&gt;      self.create(:key =&gt; key.to_s, :value =&gt; value) unless value.nil?&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I add the [] operator methods to the active record class.&lt;br /&gt;&lt;br /&gt;this way I can store values like this: &lt;br /&gt;SingleValue[:foo] = "bar" or SingleValue["foo"] = "bar"&lt;br /&gt;&lt;br /&gt;and then retrieve it with:&lt;br /&gt;SingleValue[:foo] or SingleValue["foo"]&lt;br /&gt;&lt;br /&gt;It returns nil if the key is not found, and delete the record if you assign a nil value.&lt;br /&gt;For example SingleValue[:foo] = nil will delete SingleValue[:foo] if it exists.&lt;br /&gt;Also you can do substitution on the key like SingleValue["foo_#{bar}"] if you are going to get the key at runtime.&lt;br /&gt;&lt;br /&gt;You may find convenient to add an index on the key column for quicker searches if you are storing many values.&lt;br /&gt;&lt;br /&gt;Note that you can only store single string values(or numbers that will be returned as strings).&lt;br /&gt;If you want to store complete objects you can serialize them into the value column with ActiveRecord "serialize" method,&lt;br /&gt;you may have to change the column type to 'text' , the implementation will be the same I think, try it!&lt;br /&gt;&lt;br /&gt;Bye!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-6034149275468463181?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/6034149275468463181/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=6034149275468463181' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/6034149275468463181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/6034149275468463181'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2009/12/storing-single-values-in-rails-with.html' title='Storing single values in Rails with ActiveRecord'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-1361779875387572754</id><published>2009-11-20T16:11:00.000-08:00</published><updated>2010-01-11T20:49:36.704-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Accessing soap web services in Ruby using soap4r.</title><content type='html'>Recently I had to access a soap web service written in .NET with a Rails application, the most "common" way is using the soap4r gem. There are another alternatives, one of them is "handsoap" but i decided to go with soap4r, because it looked simpler and the project is more mature. The bad thing is that is difficult to find examples, that's why I am writing this article to help someone who does not have any prior experience with this library.&lt;br /&gt;&lt;br /&gt;Standard ruby installation comes with soap4r but it's better to use the latest version, so install the gem.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;sudo gem install soap4r&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Then you should know the url of the wsdl of the service you want to consume, we are going to use this which is freely available:&lt;br /&gt;&lt;br /&gt;http://www.webservicex.net/CurrencyConvertor.asmx?WSDL&lt;br /&gt;&lt;br /&gt;once you have the url, there are 2 options:&lt;br /&gt;1. create proxy classes with a utility called wsdl2ruby which resides on the bin directory of your library installation.&lt;br /&gt;2. create the driver and call the methods directly passing a hash in the form of an XML as parameter.&lt;br /&gt;&lt;br /&gt;The first one didn't work for me because the classes were not representing exactly the wsdl. There are possibly some wsdl directives which the utility doesn't recognizes, that depends on the service. So my only choice was the second one which ended to be more intuitive.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Hashes and XML&lt;/span&gt;&lt;br /&gt;It's very easy to transform xml into hashes and viceversa, in Rails if you have a hash instance you can simply call my_hash.to_xml and it returns the xml string with the keys as nodes and the data associated inside.&lt;br /&gt;&lt;br /&gt;these are a couple of examples&lt;br /&gt;&lt;br /&gt;For example, suppose you have this hash:&lt;br /&gt;&lt;pre&gt;&lt;code&gt; &lt;br /&gt;{&lt;br /&gt;  "band" =&gt; {&lt;br /&gt;    "guitars" =&gt; [{"name" =&gt; "Allan Holdsworth"},{"name" =&gt; "Frank Gambale"}],&lt;br /&gt;    "drums" =&gt; "Vinnie Colaiuta",&lt;br /&gt;    "bass" =&gt; "Gary Willis"&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;it will turn into this XML:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&amp;gt;&lt;br /&gt;&amp;lt;hash&amp;gt;&lt;br /&gt; &amp;lt;band&amp;gt;&lt;br /&gt;   &amp;lt;bass&amp;gt;Gary Willis&amp;lt;/bass&amp;gt;&lt;br /&gt;   &amp;lt;drums&amp;gt;Vinnie Colaiuta&amp;lt;/drums&amp;gt;&lt;br /&gt;   &amp;lt;guitars type=\\\"array\\\"&amp;gt;&lt;br /&gt;     &amp;lt;guitar&amp;gt;&lt;br /&gt;       &amp;lt;name&amp;gt;Allan Holdsworth&amp;lt;/name&amp;gt;&lt;br /&gt;     &amp;lt;/guitar&amp;gt;&lt;br /&gt;     &amp;lt;guitar&amp;gt;&lt;br /&gt;       &amp;lt;name&amp;gt;Frank Gambale&amp;lt;/name&amp;gt;&lt;br /&gt;     &amp;lt;/guitar&amp;gt;&lt;br /&gt;   &amp;lt;/guitars&amp;gt;&lt;br /&gt; &amp;lt;/band&amp;gt;&lt;br /&gt;&amp;lt;/hash&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The idea is very simple, xml tags can be nested defining hashes of hashes, and a tag which expects several same tags on the inside has to be defined with an array.&lt;br /&gt;You can go the other way with Hash.from_xml and passing the xml&lt;br /&gt;&lt;br /&gt;So Hash.from_xml(band.to_xml) should return the original hash.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now lets checkout the web service definition&lt;br /&gt;&lt;br /&gt;you can ckeckout the web service methods in:&lt;br /&gt;http://www.webservicex.net/CurrencyConvertor.asmx&lt;br /&gt;&lt;br /&gt;the web service definition is in:&lt;br /&gt;http://www.webservicex.net/CurrencyConvertor.asmx?WSDL&lt;br /&gt;&lt;br /&gt;you can go to the only method available in this service on:&lt;br /&gt;http://www.webservicex.net/CurrencyConvertor.asmx?op=ConversionRate&lt;br /&gt;go to the section which describes the soap protocol and there is the exchanging xml messages format look in the soap protocol part, this is where it describes the method parameters:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;ConversionRate xmlns=\"http://www.webserviceX.NET/\"&amp;gt;&lt;br /&gt;  &amp;lt;FromCurrency&amp;gt;AFA or ALL or DZD ....&amp;lt;/FromCurrency&amp;gt;&lt;br /&gt;  &amp;lt;ToCurrency&amp;gt;AFA or ALL or DZD ...&amp;lt;/ToCurrency&amp;gt;&lt;br /&gt;&amp;lt;/ConversionRate&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So the parameters will be the hash:  &lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;{"FromCurrency" =&gt; "...",  "ToCurrency" =&gt; "..."}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and the response will be in:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;ConversionRateResponse xmlns=\"http://www.webserviceX.NET/\"&amp;gt;&lt;br /&gt; &amp;lt;ConversionRateResult&amp;gt;double&amp;lt;/ConversionRateResult&amp;gt;&lt;br /&gt;&amp;lt;/ConversionRateResponse&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;in this case the response will be only a "double"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now the code:&lt;br /&gt;&lt;br /&gt;In rails  add this to your environment.rb to include the latest library version:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;config.gem 'soap4r', :lib =&gt; 'soap/wsdlDriver', :version =&gt; '1.5.8'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;you should change the version number to the latest you have install&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you are using just Ruby:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;require "rubygems"&lt;br /&gt;gem 'soap4r'&lt;br /&gt;require "soap/wsdlDriver"&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and this is the Ruby code:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;require "rubygems"&lt;br /&gt;gem "soap4r"&lt;br /&gt;require "soap/wsdlDriver"&lt;br /&gt;wsdl = "http://www.webservicex.net/CurrencyConvertor.asmx?WSDL"&lt;br /&gt;&lt;br /&gt;driver = SOAP::WSDLDriverFactory.new(wsdl).create_rpc_driver&lt;br /&gt;&lt;br /&gt;#driver.wiredump_dev = STDOUT&lt;br /&gt;&lt;br /&gt;params = {&lt;br /&gt;"FromCurrency" =&gt; "USD",&lt;br /&gt;"ToCurrency" =&gt; "UYU"&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;puts driver.conversionRate(params).conversionRateResult&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;with &lt;span style="font-style:italic;"&gt;driver.wiredump_dev = STDOUT&lt;/span&gt; all the exchanging messages are going to STDOUT. Uncomment this if you want to know the exchanging xml messages.&lt;br /&gt;The response is everything inside the "&amp;lt;conversionrateresult&amp;gt;" tag, in this case is a simple value which can be parsed easily. Normally it's an xml that can be parsed with any Ruby xml library.&lt;br /&gt;&lt;br /&gt;So, the steps are:&lt;br /&gt;-create the driver from the wsdl&lt;br /&gt;-build a hash based on the web service method parameters, which can be taken from the asmx method description&lt;br /&gt;-call the driver method with the hash as parameter, and call the xxxResult method, to get the string response&lt;br /&gt;&lt;br /&gt;hope it helps somebody&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-1361779875387572754?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/1361779875387572754/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=1361779875387572754' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/1361779875387572754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/1361779875387572754'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2009/11/accessing-soap-web-services-in-ruby.html' title='Accessing soap web services in Ruby using soap4r.'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-689627507328137331</id><published>2009-03-26T15:52:00.000-07:00</published><updated>2009-11-20T18:02:11.883-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Send mails asynchronous from a Rails app</title><content type='html'>&lt;p&gt;&lt;br /&gt;&lt;br /&gt;Dealing with mails is not an easy task, sending mails synchronously is not an option, because maybe a user wants to send invitations to lots of people and this takes time, or even if it is only one, maybe there is another user trying to send another invitation and the smtp will collapse.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I looked for a plugin or something that could handle this but I didn't like most of them.&lt;br /&gt;The option that I liked most was "ar_mailer", the plugin basically saves the mails to the database and provide you with a process for send them later, programming this process with a cron job or running it as a daemon. But it does not manage prioritys!, so for example in a common web app suppose a user wants to send invitations and another user wants to reset his password. If the user sending invitations starts first, the user requesting his password will have to wait for all the invitations to be sent before he could receive the password reset. If you decide to send the urgent mails directly without going thru ar_mailer is the same, because maybe your smtp is busy sending invitations emails and it will refuse to send the urgent ones. So you must have prioritys!, there are some solutions there but they are a little bit complicated. &lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;So I come up with a very easy solution that do what ar_mailer do but in a simpler way, and that could handle prioritys, I am not saying it is better than ar_mailer because is a LOT more "amateurish" but for this problem I could not use ar_mailer.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;What I did was create a model "MailQueue", this is the migration for the model:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class CreateMailQueue &lt; ActiveRecord::Migration&lt;br /&gt;  def self.up&lt;br /&gt;    create_table :mail_queue do |t|&lt;br /&gt;      t.text :mail&lt;br /&gt;      t.integer :priority, :default =&gt; 0&lt;br /&gt;      t.timestamps&lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt; &lt;br /&gt;  def self.down&lt;br /&gt;    drop_table :mail_queue&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;and this is the MailQueue class:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class MailQueue &lt; ActiveRecord::Base&lt;br /&gt;  set_table_name 'mail_queue'&lt;br /&gt;  &lt;br /&gt;  serialize :mail     &lt;br /&gt;        &lt;br /&gt;  #/* the mail object generated with the 'create'  method of the mailer&lt;br /&gt;  # * the priority of the email, the highest, the most&lt;br /&gt;  # */&lt;br /&gt;  def self.enqueue(mail, priority = 0)&lt;br /&gt;    MailQueue.create(:mail =&gt; mail, :priority =&gt; priority)&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  #/* max: max amount of mails to send per method call&lt;br /&gt;  #  * time: the maximum amount of time the method should run(in minutes)&lt;br /&gt;  #  * chunks: the amount of mail to send without checking &lt;br /&gt;  #  *   if there are new ones with higher priority&lt;br /&gt;  #  */&lt;br /&gt;  def self.deliver(max, time, chunks = 5)        &lt;br /&gt;    init_time = Time.now&lt;br /&gt;    delivered = 0&lt;br /&gt;    while true&lt;br /&gt;      queued_mails = MailQueue.find(:all, :order =&gt; "priority DESC, created_at", :limit =&gt; chunks)&lt;br /&gt;      return if queued_mails.empty?&lt;br /&gt;      queued_mails.each do |queued_mail| &lt;br /&gt;        return if (delivered == max) || (Time.now - init_time &gt; time * 60)&lt;br /&gt;        begin&lt;br /&gt;          ActionMailer::Base.deliver(queued_mail.mail)&lt;br /&gt;          queued_mail.delete&lt;br /&gt;          delivered += 1          &lt;br /&gt;        rescue&lt;br /&gt;          # wait for the smtp to react&lt;br /&gt;          sleep 10&lt;br /&gt;        end                &lt;br /&gt;      end                      &lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;notice I change the model default table name because "mail_queueS" was not very semantic...&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The model class has 2 class methods: &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The first one creates a MailQueue with a mail attribute, which is the saved mail generated by ActionMailer serialized to the database, and sets a priority for this mail. (Remember that with an ActionMailer class, is possible to use: "deliver_method_name" to send it instantly or "create_method_name" to save it for send it later.)&lt;br /&gt;Serializing is done thru ActiveRecord's serialize method which is called at the beginning of the class. You can call this method in your controller.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The second is supposed to be call with script/runner and automate it with cron to run in a periodical basics. The way in which you decide to run it depends totally on the server environmet you have, for example if you use a shared hosting, most of them limits the amounts of email that can be send per hour. So I add some parameters to customize this behaviour, they are explained at the beginning of the method. Basically this method chechs the MailQueue and retrieves them in "chunks" to send them one by one. Each time it querys the database it orders the queue first by priority and then by the date it was created.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;So in your controller, instead of doing:&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;Notifier.deliver_invite(...) &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;being Notifier the ActionMailer class, you will do something like this: &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger;"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;MailQueue.enqueue(Notifier.create_invite(...), 0) &lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;and sets a priority in the last argument, the default is 0, so in this case you don't need to put it, but the higher the priority number is, first is going to be retrieved in the queue.&lt;br /&gt;So for the non urgent mails I set a priority of 0, and for the urgent ones I set a higher priority, basically I have 0 and 1, but maybe you need extremely urgent mails, you can set a priority of 2 or higher. After the first "chunk"(I don't know if it is the appropriate word, but I like it in this context) of mails is sent, it queries again to see if another mail was created with higer priority. It's possible to set the chunk, but the default is 5.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;So you have to add a cron task for example to run this every hour.&lt;br /&gt;script/runner can be called this way: &lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&gt;path_to_rails_app/script/runner 'MailQueue.deliver(200, 55)'&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;to deliver a max of 200 emails in a maximum period of 55 minutes.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Another detail is that changing this method a little bit, it could be set to run as a daemon(I mean never ending..), but first is an instance of rails that you must have up all the time so it's not very efficient, and second maybe it hungs up and you didn't notice, so I think the safest and efficient way is running it with a cron task, and tell the method to run for a maximum specific period of time.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I think the code speaks for itself, if you have any questions or remarks, please comment or send an email.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;NOTE: Now there are other options like delayed_job which is great, anyway I think the code is interesting.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-689627507328137331?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/689627507328137331/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=689627507328137331' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/689627507328137331'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/689627507328137331'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2009/03/send-mails-asynchronous-from-rails-app.html' title='Send mails asynchronous from a Rails app'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-5717011085589511505</id><published>2009-02-21T07:46:00.000-08:00</published><updated>2009-02-21T09:04:28.369-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Rails'/><title type='text'>Using will_paginate rails plugin with ajax.</title><content type='html'>will_paginate is great, but... it doesnt support ajax, &lt;a href="http://wiki.github.com/mislav/will_paginate/ajax-pagination"&gt;here&lt;/a&gt; the developer explains why.&lt;br /&gt;&lt;br /&gt;But actually, it is very common that we would like to use will_paginate with ajax.&lt;br /&gt;&lt;br /&gt;On &lt;a href="http://weblog.redlinesoftware.com/2008/1/30/willpaginate-and-remote-links"&gt;this&lt;/a&gt; great post, it explains the hack (READ THAT ARTICLE BEFORE). But how can we use it? for example if we want to update a partial using the collection that returns me the "paginate" method added by the plugin in any active record class.&lt;br /&gt;&lt;br /&gt;This is what i did:&lt;br /&gt;&lt;br /&gt;First i added the helper(in the mentioned article explains how):&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;class RemoteLinkRenderer &lt; WillPaginate::LinkRenderer  &lt;br /&gt; def prepare(collection, options, template)    &lt;br /&gt;  #@remote = options.delete(:remote) || {}  #(1)&lt;br /&gt;  options.delete(:remote)  #(2)&lt;br /&gt;  @remote = options || {}    #(3)&lt;br /&gt;  super  &lt;br /&gt; end &lt;br /&gt;&lt;br /&gt; protected  def page_link(page, text, attributes = {})&lt;br /&gt;      @template.link_to_remote(text, {:url =&gt; url_for(page), :method =&gt;:get}.merge(@remote))  &lt;br /&gt; end&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The options parameter of the "prepare" method, is the hash that will be passed to the options parameter of the link_to_remote helper, but i had to change lines (2) and (3) instead of (1), because the ruby Hash delete method returns the associated value of the key instead of the resulting hash.&lt;br /&gt;&lt;br /&gt;So, suppose i want to render a list of users:&lt;br /&gt;&lt;br /&gt;This is my controller method:&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;def index      &lt;br /&gt; @users = User.paginate(...options..., :page =&gt; params[:page], :per_page =&gt; 5)    &lt;br /&gt; respond_to do |format|        &lt;br /&gt;  format.html &lt;br /&gt;  format.js { render :action =&gt; 'show' }    #(4) &lt;br /&gt; end            &lt;br /&gt;end    &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;and this is my view (index.html.erb)&lt;br /&gt;&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;p&amp;gt;  &lt;br /&gt; &amp;lt;div id=&amp;quot;paginate_refresh&amp;quot;&amp;gt;    &lt;br /&gt;  &amp;lt;%= will_paginate (@users, :renderer =&amp;gt; 'RemoteLinkRenderer', &lt;br /&gt;         :loading =&amp;gt; &amp;quot;some_js_function()&amp;quot;, :complete =&amp;gt; &amp;quot;some_other_js_function()&amp;quot;) %&amp;gt;  &lt;br /&gt; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt; &lt;br /&gt;&amp;lt;p&amp;gt;  &lt;br /&gt; &amp;lt;div id=&amp;quot;user_refresh&amp;quot;&amp;gt;    &lt;br /&gt;  &amp;lt;%= render :partial =&amp;gt; &amp;quot;user&amp;quot;, :collection =&amp;gt; @users %&amp;gt;  &lt;br /&gt; &amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I have a _user.html.erb partial with the user information(i will not show it here because it doesn't matter).&lt;br /&gt;&lt;br /&gt;My idea was to use 2 different divs for updating the information and the pagination links.&lt;br /&gt;&lt;br /&gt;As you can see i also pass to the will_paginate helper method, the callbacks of my ajax request, this options will go directly to the couple of link_to_remote helpers that the will_paginate helper method renders, you can use here all the options provided by link_to_remote helpers.&lt;br /&gt;&lt;br /&gt;In the controller method at (4), i render 'show', which is the rjs template(show.js.rjs) that will be rendered when the call is an ajax request.&lt;br /&gt;&lt;br /&gt;And here is this template:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:larger;color:blue;"  &gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;page.replace_html 'user_refresh', :partial =&gt; "user", :collection =&gt; @users&lt;br /&gt;page.replace_html 'paginate_refresh', will_paginate (@users, :renderer =&gt;'RemoteLinkRenderer',&lt;br /&gt;  :loading =&gt; "some_js_function()", :complete =&gt; "some_other_js_function()")&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;And that's it!&lt;br /&gt;&lt;br /&gt;I just refresh the two divs with the new information and the new will_paginate links.&lt;br /&gt;&lt;br /&gt;Any comments or questions, please leave a message.&lt;br /&gt;&lt;br /&gt;Bye&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-5717011085589511505?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/5717011085589511505/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=5717011085589511505' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/5717011085589511505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/5717011085589511505'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2009/02/using-willpaginate-rails-plugin-with.html' title='Using will_paginate rails plugin with ajax.'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-3046940214877556997</id><published>2009-02-17T15:40:00.000-08:00</published><updated>2009-02-21T06:49:19.040-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Algorithms'/><title type='text'>A typical recursion example</title><content type='html'>Suppose you have a tree structure object(i mean an object that holds a collection of himself inside) and you want to copy it to a another tree object.&lt;br /&gt;&lt;br /&gt;If you want to just copy one object to another one of the same class, maybe it is easier to serialize it to memory and get it back. But if they are from different classes this will not work.&lt;br /&gt;&lt;br /&gt;So i post here an example of how to do this. It is a solution to a problem i had, and i thought i can do it on the fly but i have to think it a couple of minutes because i dont use it very often. That's why i decided to post it.&lt;br /&gt;&lt;br /&gt;I will implement it in Ruby which is my prefered language but the idea is the same in any other.&lt;br /&gt;&lt;br /&gt;Suppose you have an Elem class:&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code color="blue"&gt; &lt;br /&gt;class Elem&lt;br /&gt;  &lt;br /&gt;  attr_accessor :sons&lt;br /&gt;  attr_accessor :text&lt;br /&gt; &lt;br /&gt;  def initialize(text = '')&lt;br /&gt;     @text = text&lt;br /&gt;     @sons = []&lt;br /&gt;  end&lt;br /&gt; &lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;this is the class of the object that you want to copy,&lt;br /&gt;and you have a node class:&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class Node&lt;br /&gt;&lt;br /&gt;   attr_accessor :sons&lt;br /&gt;   attr_accessor :text&lt;br /&gt; &lt;br /&gt;   def initialize(text = '')&lt;br /&gt;      @text = text&lt;br /&gt;      @sons = []&lt;br /&gt;   end&lt;br /&gt; &lt;br /&gt;   def add_child(child)&lt;br /&gt;      @sons &lt;&lt; child&lt;br /&gt;   end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;They are basically the same, but the Node class has the interface that we would expect in a kind of "tree" class, with a method "add_child".&lt;br /&gt;&lt;br /&gt;So the recursive method we could call to clone them, is this:&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;def fill_nodes(elem, node)&lt;br /&gt; &lt;br /&gt;  node.text = elem.text #(1)&lt;br /&gt; &lt;br /&gt;  for elem_sons in elem.sons&lt;br /&gt;     child_node = Node.new #(2)&lt;br /&gt;     fill_nodes(elem_sons, child_node) #(3)&lt;br /&gt;     node.add_child(child_node) #(4)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The idea is that you go and copy them on the same level, in (1) this is where the information copy gets done. Then you just go through all the sons of the object you want to get copied, in (2) we create a child node and in (3) start the process for that child, in (4) we add this new child node to the original node. (3) and (4) are interchangeable, it does not matter the order. I could have used Ruby's Array's "each" method which is more Ruby oriented, but this way is more understandable.&lt;br /&gt;&lt;br /&gt;A few important points:&lt;br /&gt;you have to be careful that elem.sons is initialized in an empty collection when it does not contain anything, if not, the "for" will fail if the object you are trying to copy have a null collection inside, you have to add a little logic to handle this, just ask if it is null before doing the "for".&lt;br /&gt;You have to also be sure that you cannot pass null objects (maybe if the collection has null objects or whatever).&lt;br /&gt;We could use "assert" to check this conditions.&lt;br /&gt;&lt;br /&gt;Another remark is that when you pass the "node" to the method, you are actually passing a copy of the pointer to the actual node(and i have seen that many people does not have this clear), so be careful with this, because making a new on this pointer could have undesirable results.&lt;br /&gt;&lt;br /&gt;Lets try this example:&lt;br /&gt;&lt;br /&gt;Lets add a console print method to see if this actually works(this is a typical tree traversal method, which uses ruby's excellent '*' operator with strings to format the output, you may have to do some other trick in other programming language):&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;def print_nodes(node, level)&lt;br /&gt;&lt;br /&gt;  puts "  " * level + node.text&lt;br /&gt;&lt;br /&gt;  for child_node in node.sons&lt;br /&gt;     print_nodes(child_node, level + 1)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;and some sample data:&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;elem1 = Elem.new('obj1')&lt;br /&gt;elem2 = Elem.new('obj2')&lt;br /&gt;elem3 = Elem.new('obj3')&lt;br /&gt;elem4 = Elem.new('obj4')&lt;br /&gt;elem5 = Elem.new('obj5')&lt;br /&gt;elem6 = Elem.new('obj6')&lt;br /&gt;&lt;br /&gt;elem1.sons &lt;&lt; elem2 &lt;&lt; elem3 &lt;&lt; elem4&lt;br /&gt;elem4.sons &lt;&lt; elem5 &lt;&lt; elem6&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Now let's see what it prints if we execute it, notice that you first have to create the first node of the tree object.&lt;br /&gt;&lt;span style="color:blue; font-style: italic; font-size: larger"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;node1 = Node.new('nodo1')&lt;br /&gt;fill_nodes(elem1, node1)&lt;br /&gt;print_nodes(node1, 0)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Try it to see what it prints!!&lt;br /&gt;&lt;br /&gt;Any questions or comments, please write to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-3046940214877556997?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/3046940214877556997/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=3046940214877556997' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/3046940214877556997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/3046940214877556997'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2009/02/typical-recursion-example.html' title='A typical recursion example'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-6485445253174413620</id><published>2008-09-21T20:16:00.000-07:00</published><updated>2009-02-11T17:50:51.264-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='Downloads'/><title type='text'>A simple Ruby rapidshare downloader</title><content type='html'>This is a very simple ruby program that i wrote to automate the process of downloading files from rapidshare, without having a premium account.&lt;br /&gt;The program file is available for download &lt;a href="http://www4.webng.com/paginamorris/archivos/otros/rapidshare_downloader.rb.tar.gz"&gt;here&lt;/a&gt;, to use it you have to install ruby and rubygems (under Linux look them up in your distro package manager, under Windows go &lt;a href="http://www.ruby-lang.org/en/downloads/"&gt;here&lt;/a&gt; to download ruby and &lt;a href="http://rubyforge.org/projects/rubygems/"&gt;here&lt;/a&gt; to download rubygems) if you don't have them installed yet, and once you have rubygems, install a couple of libraries the program needs this way:&lt;br /&gt;&lt;br /&gt;#&gt;gem install mechanize --include-dependencies&lt;br /&gt;&lt;br /&gt;I didn't tried it under windows but it shouldn't have any problem, maybe you have to escape the directory path where you want to store the files, so 'c:\myfolder\somewhere' should be 'c:\\myfolder\\somewhere'.&lt;br /&gt;&lt;br /&gt;Execute the program without any arguments and the help is displayed.&lt;br /&gt;&lt;br /&gt;usage:&lt;br /&gt;$&gt; rapidshare_downloader RAPIDSHARE_URLS...(separated by spaces) DOWNLOAD_DIRECTORY&lt;br /&gt;&lt;br /&gt;Example:&lt;br /&gt;$&gt; rapidshare_downloader http://rapidshare.com/something1 http://rapidshare.com/something2 /home/myname/somedirectorypath&lt;br /&gt;&lt;br /&gt;Or you can also call it this way(which is more practical):&lt;br /&gt;&lt;br /&gt;$&gt; rapidshare_downloader DOWNLOAD_FILE&lt;br /&gt;where DOWNLOADFILE is a text file containing on each line a rapidshare address, and in the last line an existing directory in the filesystem&lt;br /&gt;&lt;br /&gt;Example of a DOWNLOADFILE:&lt;br /&gt;http://rapidshare.com/something1&lt;br /&gt;http://rapidshare.com/something2&lt;br /&gt;...&lt;br /&gt;/home/myname/somedirectorypath&lt;br /&gt;&lt;br /&gt;Empty lines and lines starting with '#' are not read.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;font-size:130%;" &gt;Some comments if you are interested in how it works.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I used a very good http client library called &lt;a href="http://mechanize.rubyforge.org/mechanize/"&gt;Mechanize&lt;/a&gt;, because the one that comes with ruby (Net::HTTP) is a little bit hard to manage, for example cookies are not handled automatically, and to submit a form you need to pass in the parameters one by one, you cannot post the html.&lt;br /&gt;The use of Mechanize is really simple and intuitive, it handles cookies and redirection alone, it's possible to simulate button clicks, submit forms, etc.&lt;br /&gt;The only drawback is that the documentation is not complete, so sometimes you have to guess.&lt;br /&gt;It is available as a gem, so installing it is as simple as doing:&lt;br /&gt;&lt;br /&gt;$&gt;sudo gem install mechanize --include-dependencies&lt;br /&gt;&lt;br /&gt;it will also download &lt;a href="http://code.whytheluckystiff.net/hpricot/"&gt;hpricot&lt;/a&gt;'which is a library that mechanize uses. Hpricot is used to parse html and sometimes you have to create some hpricot objects to interact with mechanize.&lt;br /&gt;&lt;br /&gt;The code is easy to understand, what I do was a little hack to the html. First I make a get request with the url address that rapidshare gives, then I submit the first form in the page which is the one that submits if you click on the "Free user" button, in the response there is a form in a javascript string which will be place into the DOM once a "setTimeout" javascript function executes (this time is also validated in the server, so it's impossible to submit the form before time), so I extract this form and submit it after the time passes. I do this for each file.&lt;br /&gt;&lt;br /&gt;Another important thing to notice, is that the file is saved in memory first and after all the file is downloaded, then it get saved in the hard disk.&lt;br /&gt;That is why I release the reference to the file and call the garbage collector after the file is saved, I take a look and it seems to not be working, but I still had plenty of memory when i tried it, maybe thats why the garbage collector didn't collect it, or the top command was not showing the right things...&lt;br /&gt;So to run the program you will need memory depending on the size of the files, or at least each file (if the gc works).&lt;br /&gt;&lt;br /&gt;Any questions or suggestions, please write to me.&lt;br /&gt;&lt;br /&gt;PD. the file is now posted at &lt;a href="http://github.com"&gt;github&lt;/a&gt; and this will be the latest version, this is the clone url: &lt;code&gt;git://github.com/bsampietro/rapidshare_downloader.git &lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-6485445253174413620?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/6485445253174413620/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=6485445253174413620' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/6485445253174413620'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/6485445253174413620'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2008/09/simple-ruby-rapidshare-downloader.html' title='A simple Ruby rapidshare downloader'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-869458163490176335</id><published>2008-08-24T19:55:00.000-07:00</published><updated>2008-08-24T20:24:35.607-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Networking'/><title type='text'>Connect to a VPN using the PPTP (Microsoft propietary) protocol under openSuse 11.0 Linux</title><content type='html'>I use openSuse but it surely work under other distros too.&lt;br /&gt;I did some research and I didn't found much information about this on the web, that is why I am writing this little article.&lt;br /&gt;Install the “pptp” package, it comes with two binaries:&lt;br /&gt;“pptp” and “pptp-command”, we will be using “pptp-command” for everything.&lt;br /&gt;As root run:&lt;br /&gt;# pptp-command&lt;br /&gt;&lt;br /&gt;it will present four options:&lt;br /&gt;&lt;span style="font-style: italic;"&gt;1.)start&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;2.) stop&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;3.) setup&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;4.) quit&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;We need first to setup the connection so we select: 3&lt;br /&gt;it will present 8 options&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;1.) Manage CHAP secrets&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;2.) Manage PAP secrets&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;3.) List PPTP Tunnels&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;4.) Add a NEW PPTP Tunnel&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;5.) Delete a PPTP Tunnel&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;6.) Configure resolv.conf&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;7.) Select a default tunnel&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;8.) Quit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First we need to authenticate, so we have to select 1 or 2 depending on the kind of authentication the server use.&lt;br /&gt;When I configure it, the server I was trying to connect use CHAP so lets select 1&lt;br /&gt;It will present:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;1.) List CHAP secrets&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;2.) Add a New CHAP secret&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;3.) Delete a CHAP secret&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;4.) Quit&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We need to add a new CHAP secret, so we select: 2&lt;br /&gt;first the program ask for the Local Name,&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Local Name: myusername&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;there put the username of your vpn account, then it asks for the Remote Name [PPTP]&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Remote Name [PPTP]:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;there in most cases we can leave the default (see the explanation), so we left it blank... then it asks for the password of your vpn account&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Password: mypassword&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;there we put the password.&lt;br /&gt;Once this is done the CHAP secret is added, then we go back(or we can do any other task that the program offers), we press 4.&lt;br /&gt;&lt;br /&gt;The main menu appears again and we need to add a new PPTP tunnel so we select option 4&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Add a NEW PPTP Tunnel.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;1.) Other&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Which configuration would you like to use?: 1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Tunnel Name: thenameofmytunnel&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Server IP: serverdir&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;What route(s) would you like to add when the tunnel comes up?&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;This is usually a route to your internal network behind the PPTP server.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;You can use TUNNEL_DEV and DEF_GW as in /etc/pptp.d/ config file&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;TUNNEL_DEV is replaced by the device of the tunnel interface.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;DEF_GW is replaced by the existing default gateway.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;The syntax to use is the same as the route(8) command.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Enter a blank line to stop.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;route: add-net 192.168.10.0 netmask 255.255.255.0 dev TUNNEL_DEV&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Local Name and Remote Name should match a configured CHAP or PAP secret.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Local Name is probably your NT domain\username.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;NOTE: Any backslashes (\) must be doubled (\\).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Local Name: myusername&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Remote Name [PPTP]: &lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Adding thenameofmytunnel - serverdir - myusername&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Added tunnel  thenameofmytunnel&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It asks for the configuration to use, we select Other (there Is no any other choice), then it asks for the “Tunnel Name” we put there the name which you want to identify your tunnel, put it the way you want.&lt;br /&gt;Then it asks for the Server IP, put there the ip or name of the server which you want to connect to.&lt;br /&gt;Then it asks for the route, using the same syntax of the linux route command, you can put in there(for example): add-net 192.168.10.0 netmask 255.255.255.0 dev TUNNEL_DEV, so that the operating system knows that every packet send to the network 192.168.10.0 with the netmask 255.255.255.0 should use the device of the tunnel interface, here the program replaces TUNNEL_DEV with the name of the device of your vpn connection (generally ppp0). For this you should know the internal of the network behind your vpn connection.&lt;br /&gt;You could also left this blank and add the route from the operating system like this:&lt;br /&gt;#route add -net 192.168.10.0 netmask 255.255.255.0 dev ppp0&lt;br /&gt;but in this case it will be lost when you reboot the machine.&lt;br /&gt;&lt;br /&gt;At last it ask for the “Local Name” and the “Remote Name”, this have to match the ones you put in your CHAP secrets, remember that the local name is the username of your vpn account and the Remote Name we leave it blank.&lt;br /&gt;&lt;br /&gt;Once this is done we just quit and then we type again the pptp-command as root but here we select 1 (start), you could have also typed:&lt;br /&gt;#pptp-command start&lt;br /&gt;&lt;br /&gt;It asks for the connection you want to use, and thats it!, you should be connecting to your vpn.&lt;br /&gt;&lt;br /&gt;If you need to connect to a machine in your vpn that uses the RDP protocol which come installed with windows, you can download the package “rdesktop” and type:&lt;br /&gt;&gt;rdesktop -zfk keymap machineip &lt;keymap&gt; &lt;machineip&gt; &lt;keymap&gt; &lt;ip_from_the_machine_inside_the_vpn&gt;, you can look at the installed keymaps doing a&lt;br /&gt;&gt;locate keymap and see the ones that are installed inside ..rdesktop/keymaps this is important because by default it uses the english keymap, so if your keyboard is not english then you might have the keys changed.&lt;br /&gt;&lt;br /&gt;You can take a look at &lt;a href="http://pptpclient.sourceforge.net/"&gt;http://pptpclient.sourceforge.net&lt;/a&gt; for more details&lt;br /&gt;&lt;br /&gt;&lt;/ip_from_the_machine_inside_the_vpn&gt;&lt;/keymap&gt;&lt;/machineip&gt;&lt;/keymap&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-869458163490176335?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/869458163490176335/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=869458163490176335' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/869458163490176335'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/869458163490176335'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2008/08/connect-to-vpn-using-pptp-microsoft.html' title='Connect to a VPN using the PPTP (Microsoft propietary) protocol under openSuse 11.0 Linux'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-4158740745426756013</id><published>2008-07-27T16:32:00.000-07:00</published><updated>2009-02-21T08:49:03.818-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Music'/><title type='text'>Essential music for music lovers, musicians and curious listeners as well.</title><content type='html'>This time i will write a more “relaxed” post about another one of my big passions, Music!!.&lt;br /&gt;I have been a music fan since I was 12, I am 28 now, and I have listen to every possible album, going thru a lot of different styles. I tend to listen to mostly fusion instrumental music, but I like other styles as well.&lt;br /&gt;This is some of the music that i have found more interesting through all the years, in no particular order.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs661cdTTI/AAAAAAAABk0/37ukr68Y-AA/s1600-h/steve_high.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 115px; height: 115px;" src="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs661cdTTI/AAAAAAAABk0/37ukr68Y-AA/s200/steve_high.jpg" alt="" id="BLOGGER_PHOTO_ID_5303897768612154674" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;1. Steve Morse - High Tension Wires&lt;br /&gt;Probably the most beautiful album you could ever hear, the melodies are so nice, the compositions so tight, and amazing musicianship. "Tumeni notes" is the only fast tune, the others are likely to be hear while relaxing.&lt;br /&gt;Other Steve Morse or Dixie Dregs albums are good too, but i think they dont have the beauty and originality of this one.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs7OgVyMyI/AAAAAAAABk8/nsMaFxTrVmo/s1600-h/tribal_reality.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 115px; height: 115px;" src="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs7OgVyMyI/AAAAAAAABk8/nsMaFxTrVmo/s200/tribal_reality.jpg" alt="" id="BLOGGER_PHOTO_ID_5303898106544403234" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;2. Tribal Tech - Reality Check&lt;br /&gt;A little bit of everything on this one, some jazz improvisations, some furious solos on a more rocker base. Great musicians, great band.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vOmYgwl2bsw/SZs7XrjjzlI/AAAAAAAABlE/O_o3FAFMtoY/s1600-h/vinnie.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 115px; height: 115px;" src="http://3.bp.blogspot.com/_vOmYgwl2bsw/SZs7XrjjzlI/AAAAAAAABlE/O_o3FAFMtoY/s200/vinnie.jpg" alt="" id="BLOGGER_PHOTO_ID_5303898264173792850" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;3. Vinnie Colaiuta - Vinnie Colaiuta&lt;br /&gt;This is probably the most powerful Jazz-Fusion record i have ever heard, the band is incredible, the sound of the overall disk and specially the drum sound is a killer. Vinnie and Mike (Landau) have played together a lot and they sound so tight. “Im tweaked/...” is a VERY powrful start.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs7dfVTXKI/AAAAAAAABlM/Nr9TFo7nPWs/s1600-h/attent.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 115px; height: 115px;" src="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs7dfVTXKI/AAAAAAAABlM/Nr9TFo7nPWs/s200/attent.jpg" alt="" id="BLOGGER_PHOTO_ID_5303898363971984546" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;4. Attention Defficit - Attention Defficit&lt;br /&gt;Very strange music, some elments of King Crimson but more fusion oriented... Michael Manring is my favourite bass player, he can play a lot of different styles. Tim Alexander and Alex Skolnick back him up. Tim Alexander is one of my favourite drummers also, although he tends to play on not so good albums.&lt;br /&gt;The disc doesn't have tracks, it is more like an hour and a half jam session.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vOmYgwl2bsw/SZs7r6k0BnI/AAAAAAAABlc/WeLmvSjmnOU/s1600-h/mike_landau.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 120px; height: 120px;" src="http://1.bp.blogspot.com/_vOmYgwl2bsw/SZs7r6k0BnI/AAAAAAAABlc/WeLmvSjmnOU/s200/mike_landau.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303898611802965618" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;5. Mike Landau - Tales from the Bulge&lt;br /&gt;Amazing guitar album, "Judy" is a very very beautiful ballad, while "Johnny" is a monster fusion track.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs7kwKhvuI/AAAAAAAABlU/97bUnR_YuoA/s1600-h/jeff.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 119px; height: 119px;" src="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs7kwKhvuI/AAAAAAAABlU/97bUnR_YuoA/s200/jeff.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303898488749276898" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;6. Jeff Beck - Guitar Shop&lt;br /&gt;Another incredible guitar album by one of the most influential guitar players of all time, a lot of sounds, noises, great solos, great sound.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_vOmYgwl2bsw/SZs7yPmC75I/AAAAAAAABlk/OWI7Vg3LJpA/s1600-h/pat_maeth.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 122px; height: 122px;" src="http://4.bp.blogspot.com/_vOmYgwl2bsw/SZs7yPmC75I/AAAAAAAABlk/OWI7Vg3LJpA/s200/pat_maeth.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303898720524496786" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;7. Pat Metheny - The Pat Metheny Group&lt;br /&gt;Extremely melodic and light fusion, very complex tunes though. April wind and San Lorenzo are probably my favourite tracks, but the whole disc is great.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vOmYgwl2bsw/SZs72fJUAuI/AAAAAAAABls/aJQiLtMJrM0/s1600-h/allan.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 117px; height: 118px;" src="http://3.bp.blogspot.com/_vOmYgwl2bsw/SZs72fJUAuI/AAAAAAAABls/aJQiLtMJrM0/s200/allan.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303898793418425058" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;8. Allan Holdsworth - Secrets&lt;br /&gt;The #1 fusion guitarist, the most technical, the genius. All of his cds are a must listen, I didn't know which one to pick but this is very representative and a fusion classic. I am wondering who else can play “Peril Premonition”.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vOmYgwl2bsw/SZs79AlV-wI/AAAAAAAABl0/YYQqv6wedTs/s1600-h/weather.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 124px; height: 124px;" src="http://3.bp.blogspot.com/_vOmYgwl2bsw/SZs79AlV-wI/AAAAAAAABl0/YYQqv6wedTs/s200/weather.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303898905473579778" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;9. Weather Report - Black Market&lt;br /&gt;World class fusion. This has to be in every fusion lover collection. A total classic.&lt;br /&gt;Alphonso Johnson's bass lines and Joe's melodic keyboards on the title track intro(probably the most easygoin' track), are an excellente beginning.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs8B5jl7-I/AAAAAAAABl8/Hhv-WouP6IQ/s1600-h/pink_dark.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 125px; height: 125px;" src="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs8B5jl7-I/AAAAAAAABl8/Hhv-WouP6IQ/s200/pink_dark.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303898989486534626" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;10. Pink Floyd - Dark side of the moon&lt;br /&gt;Maybe the most beautiful rock album ever created. The atmosphere is total unique. Every Pink Floyd album is a MUST listen, but this one is THE classic. “The great gig in the sky” is one of the most original and beautiful songs ever.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs8Ggwe5yI/AAAAAAAABmE/cWJt8ExyHzY/s1600-h/led_ph.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 143px; height: 143px;" src="http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs8Ggwe5yI/AAAAAAAABmE/cWJt8ExyHzY/s200/led_ph.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303899068729059106" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;11. Led Zeppelin - Physical Graffiti&lt;br /&gt;Every zep album is great, but this one is the more ellaborated and complex. One of the first symphonic metal albums, amazing songs, Jimmy Page is a genius, I dont know why he release such a few solo works(except for the one with Coverdale, the others did not trascend very much)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vOmYgwl2bsw/SZs8KxZY74I/AAAAAAAABmM/JBcSKsvwo2A/s1600-h/porcupine.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 98px; height: 132px;" src="http://1.bp.blogspot.com/_vOmYgwl2bsw/SZs8KxZY74I/AAAAAAAABmM/JBcSKsvwo2A/s200/porcupine.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303899141915078530" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;12. Porcupine Tree - Arriving Somewhere&lt;br /&gt;A very interesting band, kind of progressive but a little bit more popular oriented. They also have some grunge and metal influences. Great melodies and atmospheres. This live disc sounds great.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_vOmYgwl2bsw/SZs8QbAk0rI/AAAAAAAABmU/UfWoNIdpXDw/s1600-h/brett.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 124px; height: 124px;" src="http://3.bp.blogspot.com/_vOmYgwl2bsw/SZs8QbAk0rI/AAAAAAAABmU/UfWoNIdpXDw/s200/brett.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303899238984635058" border="0" /&gt;&lt;/a&gt;13. Brett Garsed – Big Sky&lt;br /&gt;A very inspired album by this monster guitarrist. The rhythm guitar on the back is very distinctive and his tone and phrasing are beautiful. “Friend or foe” is one of the best ballads I have ever heard.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vOmYgwl2bsw/SZs8Waym6pI/AAAAAAAABmc/vCP4SJQv0dc/s1600-h/miles_kind.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 135px; height: 135px;" src="http://1.bp.blogspot.com/_vOmYgwl2bsw/SZs8Waym6pI/AAAAAAAABmc/vCP4SJQv0dc/s200/miles_kind.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303899342005267090" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;14. Miles Davis – Kind Of Blue&lt;br /&gt;A total classic jazz album. Great soloing and musicianship by Miles and John Coltrane.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_vOmYgwl2bsw/SZs8ag7p3eI/AAAAAAAABmk/Bpt1mNcf5-o/s1600-h/pat_martino.jpeg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 130px; height: 130px;" src="http://1.bp.blogspot.com/_vOmYgwl2bsw/SZs8ag7p3eI/AAAAAAAABmk/Bpt1mNcf5-o/s200/pat_martino.jpeg" alt="" id="BLOGGER_PHOTO_ID_5303899412373298658" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;15. Pat Martino – Live at Yoshis&lt;br /&gt;Pat Martino is THE jazz guitarrist, this one is with monster keyboard/”bass” player Joey De Francesco, throwing the bass lines with the keyboard, and drummer Bill Hart. The dynamic between Pat and Joey is total unique.&lt;br /&gt;“Pat has one of the more inspirational personal stories in music. A guitar legend in the '70s, he had to completely relearn the instrument after a near-fatal brain aneurysm in 1980--and he can now lay claim to one of the more inspirational live albums released in years.”, read it somewhere.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I will write soon the other parts.&lt;br /&gt;&lt;br /&gt;Bye!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-4158740745426756013?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/4158740745426756013/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=4158740745426756013' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/4158740745426756013'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/4158740745426756013'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2008/07/essential-music-for-music-lovers.html' title='Essential music for music lovers, musicians and curious listeners as well.'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_vOmYgwl2bsw/SZs661cdTTI/AAAAAAAABk0/37ukr68Y-AA/s72-c/steve_high.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7812374370851301442.post-4119325334766619489</id><published>2008-07-06T20:00:00.000-07:00</published><updated>2008-07-06T22:09:51.294-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>Some tweaks on linux.</title><content type='html'>   	&lt;meta equiv="CONTENT-TYPE" content="text/html; charset=utf-8"&gt; 	&lt;title&gt;&lt;/title&gt; 	&lt;meta name="GENERATOR" content="OpenOffice.org 2.4  (Linux)"&gt; 	&lt;style type="text/css"&gt; 	&lt;!-- 		@page { size: 8.5in 11in; margin: 0.79in } 		P { margin-bottom: 0.08in } 	--&gt; 	&lt;/style&gt;  &lt;p style="margin-bottom: 0in;"&gt;I have recently install openSuSE 11.0 on my new Compaq Presario F756 laptop.  &lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;I am going to tell you about a few little tweaks you can do to prepare your system, I use opensuse, but you can apply them to other linux distros as well.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;b&gt;Partitioning:&lt;/b&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;Partitioning a harddisk is always complicated because you never know the amount of space you will use on each partition, and if you need to resize a partition you have to backup and all stuff...&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;I have a 120 GB disc and what I did was to reserve 12 GB for the root partition, 7 GB for /home, 1 GB for /swap(i have 1 GB of RAM and I know I am not going to need any more swap space, but this totally depends on how you use your system, anyway if you need more space you can &lt;a href="http://www.linux.com/feature/113956"&gt;create a swap file&lt;/a&gt; on any partition and use it) and the rest I assign it as a big partition to store music, movies and large files like iso images for example.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;When you format a partition with the ext3 filesystem, by default it allocates a 5% of the space to the superuser, but if it is not a system partition for example the partition i keep for big files, it does not make a lot of sense, and if the partition is big this will take you out a lot of space. So what we can do, is use the tune2fs command like this:  &lt;/p&gt;  &lt;p style="margin-bottom: 0in; font-style: italic;"&gt;# tune2fs -m 0 /dev/xxx&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;this is the explanation for the -m option:&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;(-&lt;b&gt;m&lt;/b&gt; reserved-blocks-percentage&lt;br /&gt;Specify the percentage of the filesystem blocks reserved for the super-user. This avoids fragmentation,&lt;br /&gt;and allows root-owned daemons, such as syslogd(to continue to function correctly after non-privileged&lt;br /&gt;processes are prevented from writing to the filesystem. The default percentage is 5%.)  &lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;I dont know if you can do this, once you have data on the partition, do it at your own risk.&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;&lt;a href="http://en.wikipedia.org/wiki/TMPFS"&gt;&lt;b&gt;TMPFS (Temporary file system)&lt;/b&gt;&lt;/a&gt; &lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;This is a very useful stuff and I have not heard very much about it around there. I find it when I was looking how to setup a ramdisk for linux, and I find this that is much better.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;A tmpfs is a filesystem that is stored in RAM, and it also can dynamically grow as you put data on it, if your linux kernel is 2.4 or above you can use this feature.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;It is very useful to store temporary files (like recently decompress files, small downloads from the internet or browsers cache) to avoid fragmentation and innecesary writes to the disk, it also release you from the need of manually deleting those temporary files, because once you power off or reboot the system they disappear... you have to be careful also.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;You can mount a filesystem of this type any time you want this way:&lt;/p&gt;  &lt;p style="margin-bottom: 0in; font-style: italic; font-family: lucida grande;"&gt;# mount -t tmpfs tmpfs /tmp&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;(It is possible to add another parameters but this is the simplest way)&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;or if you want it to be mounted at system startup, add this line to your /etc/fstab:&lt;/p&gt;  &lt;p style="margin-bottom: 0in; font-style: italic;"&gt;tmpfs          /somewhere   tmpfs     auto,user,sync,rw 0 0&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;Once you do this you can assign the firefox cache to this file system (browsers cache completely full your harddisk with a lot of little temporary files) this way:&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;In the location bar, type about:config and hit enter, then right-click in the white-space, and choose New-&gt;String,&lt;br /&gt;add the name “browser.cache.disk.parent_directory” (without quotes) and click ok, In the next box, enter the full patch to the directory you want to store your cache in. Something like “/somewhere/firefoxcache”&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;Then restart firefox and done.&lt;/p&gt;  &lt;p style="margin-bottom: 0in;"&gt;Useful things for firefox:&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;Install the google toolbar, it is very useful to store bookmarks (on the server) and avoids going to the google page everytime you need to search for something, it has several other useful functions.&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;Another very useful tool if you are a web developer is Firebug, excelent tool for debugging javascript, and a lot of other stuff.&lt;br /&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;I know there are plenty of other very useful add-ons, I have to spend some time digging.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;b&gt;Wireless&lt;/b&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;Another thing I had to do and is known for not being very linux friendly is configure a wireless card.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;If you have an atheros card you can choose between mad-wifi which is an open source projects that provides linux native drivers for atheros cards, or ndiswrapper which is a program that installs windows XP drivers in linux. If your card is not atheros, I think the only choice is ndiswrapper, or maybe your card manufacturer made some linux native drivers.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;I have an atheros wi-fi card but I decided to go with  ndiswrapper instead of native mad-wifi because I did some research and the common mad-wifi download will not work with my wireless card.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;So I install ndiswrapper, follow the instructions &lt;a href="http://en.opensuse.org/Ndiswrapper"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;it is just:&lt;/p&gt; &lt;p style="margin-bottom: 0in; font-style: italic;"&gt;&lt;span style="font-size:100%;"&gt;# ndiswrapper -i /path/to/your/inffile/xxx.inf  &lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;you need to have both windows drivers files, the inf file and the sys file in the same directory.&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;Then if all goes well you can verify it with this:&lt;/p&gt; &lt;p style="margin-bottom: 0in; font-style: italic;"&gt;# ndiswrapper – l&lt;/p&gt; &lt;p&gt;If you did it right it will display something like this:  &lt;/p&gt; &lt;pre&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;Installed ndis drivers:&lt;/span&gt; &lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;&lt;driver&gt; driver present, hardware present&lt;/driver&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p&gt; Where &lt;driver&gt; shows the name of the windows driver installed with ndiswrapper.  &lt;/driver&gt;&lt;/p&gt; &lt;p&gt;If it says "invalid driver" then you need to uninstall that driver and try another one.  &lt;/p&gt; &lt;p&gt;To uninstall a driver, you need to type:  &lt;/p&gt; &lt;pre style="margin-bottom: 0.2in;"&gt;ndiswrapper -e &lt;then&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;Then install the module with: &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;modprobe ndiswrapper&lt;/span&gt; &lt;span style="font-size:100%;"&gt;and restart your network manager with:&lt;/span&gt; &lt;span style="font-size:100%;"&gt;&lt;br /&gt;# /etc/init.d/network restart&lt;/span&gt;&lt;br /&gt;&lt;/then&gt;&lt;/pre&gt;&lt;p style="margin-bottom: 0in;"&gt; &lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;To load the driver at boot, add the line: “modprobe ndiswrapper” at the beginning to your /etc/init.d/network startup script (I have read that if after “modprobing” ndiswrapper you configure everything with yast, you don't need to edit the /etc/init.d/network script, but for me it didn't work. This is the only thing that is specific for opensuse), maybe there is a neater way of doing this, but this just works.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;So after doing all this, I use yast to configure the wireless, just create a  new connection with Device Type → Wireless and in Module Name type “ndiswrapper”. Then hit next and put there the name (ESSID) of your wireless LAN and the type of authentication you use in your router, (I try to use KnetworkManager to manage the authentication and leave empty the settings in yast but with wap-psk which is the one that I use it was impossible) and that's it, reboot and if you put the authentication type, the code, and the ESSID right, you will have wireless.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;&lt;b&gt;Some useful programs:&lt;/b&gt;&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;First add the Packman repositories which are available in the “software repositories” in yast along with the standard SuSE ones.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;openSuSE does not come with the useful command “locate”, so install it via yast, the name of the package is findutils-locate.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;Another useful tool is the command line tool “rar” to compress and decompress rar archives, which is very popular in windows world.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;Talking about windows, there are certain windows programs that maybe useful and don't have a linux version, for this you can install “wine” and you can run most windows little programs, and the heavy ones also with a little tweaking.&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;For playing audio, I use to love winamp in windows. In linux there is audacious which is a winamp clone and works better than the old xmms, in SuSE repositories(standard ones   plus packman) there are input plugins for every possible sound file format including wma (which sometimes we can not avoid)&lt;/span&gt;&lt;/p&gt; &lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;For playing video there is mplayer, which I think is a very good player, although I have never tried VLC which I heard is good also.&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;Well, this were some basic things i did to put linux to work the way i like, other recomendations are welcome!!&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style="margin-bottom: 0in;"&gt;&lt;span style="font-family:DejaVu Sans,sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7812374370851301442-4119325334766619489?l=samstaff.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://samstaff.blogspot.com/feeds/4119325334766619489/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7812374370851301442&amp;postID=4119325334766619489' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/4119325334766619489'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7812374370851301442/posts/default/4119325334766619489'/><link rel='alternate' type='text/html' href='http://samstaff.blogspot.com/2008/07/some-tweaks-on-linux.html' title='Some tweaks on linux.'/><author><name>Bruno</name><uri>http://www.blogger.com/profile/13642757957648242908</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://bp1.blogger.com/_vOmYgwl2bsw/SHWV_Y1lwYI/AAAAAAAAAI0/d-wbEyRFOcE/S220/foto3.jpg'/></author><thr:total>0</thr:total></entry></feed>
