Useful Blogs I: Web Development and Design
map_by_method
students.map_by_name which will return the names of the students as an array. This is a ruby gem and you can find more information about it at: map_by_method
Find or Create
1 2 |
foo = Bar.find(:first, :conditions => {:name => "Fred"}) || Bar.new(:name => "Fred") |
Model.find_or_create_by_COLUMN, where COLUMN is the name of the column.
(Not) Helpful Helpers
In Rails 2.0.x, application.rb has a:
1 2 |
helper :all
|
FooController and BarController, then the helpers will be loaded in the following order:
- ApplicationHelper
- BarHelper
- FooHelper
So, if you expect to have different behaviours in Foo and Bar, you'll be disappointed. The behaviours override each other, leaving a single behaviour across the application. In order to fix this, remove or comment out the declaration in application.rb.
Ruby2Ruby
Ruby2Ruby is a gem which allows you to look at the code of a class. To install do:
gem install ruby2ruby(you may need to do a sudo in front of it)
Here's an example of its use:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
irb(main):001:0> require 'rubygems' => true irb(main):002:0> require 'ruby2ruby' => true irb(main):003:0> class Foo irb(main):004:1> def fud irb(main):005:2> puts "groo" irb(main):006:2> end irb(main):007:1> end => nil irb(main):008:0> Ruby2Ruby.translate Foo => "class Foo < Object\n def fud\n puts(\"groo\")\n end\nend" irb(main):009:0> class Foo irb(main):010:1> def fi irb(main):011:2> puts "fo" irb(main):012:2> end irb(main):013:1> end => nil irb(main):014:0> Ruby2Ruby.translate Foo => "class Foo < Object\n def fi\n puts(\"fo\")\n end\n \n def fud\n puts(\"groo\")\n end\nend" irb(main):015:0> class Foo irb(main):016:1> def fud irb(main):017:2> puts "Hello World!" irb(main):018:2> end irb(main):019:1> end => nil irb(main):020:0> Ruby2Ruby.translate Foo => "class Foo < Object\n def fi\n puts(\"fo\")\n end\n \n def fud\n puts(\"Hello World!\")\n end\nend" irb(main):021:0> |
Notice how it changes the class output. One thing I have found is that if you create instance variables outside of a method they won't show up in the output. Otherwise, it works quite well and is a good addition to a metaprogramming toolkit.
sub vs sub!
sub does not do the same thing as sub!:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
irb(main):001:0> a="something" => "something" irb(main):002:0> b=a.sub(/e/,"E") => "somEthing" irb(main):003:0> b => "somEthing" irb(main):004:0> a => "something" irb(main):005:0> c=a.sub!(/thing/,"one") => "someone" irb(main):006:0> c => "someone" irb(main):007:0> a => "someone" irb(main):008:0> b=a.sub(/thing/,"body") => "someone" irb(main):009:0> b => "someone" irb(main):010:0> c=a.sub!(/thing/,"body") => nil |
They behave the same when there is a pattern matched and a change, however, when there is not a pattern matched they behave differently. This can cause grief as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
irb(main):011:0> a="something" => "something" irb(main):012:0> b=a.tr("n-za-m","a-z") => "fbzrguvat" irb(main):013:0> b=a.sub(/thing/,"one").tr("n-za-m","a-z") => "fbzrbar" irb(main):014:0> a => "something" irb(main):015:0> b=a.sub!(/body/,"one").tr("n-za-m","a-z") NoMethodError: undefined method `tr' for nil:NilClass from (irb):15 from :0 |
This is the general behaviour of any method ending in !, so be careful when you are using them.
xargs
The UNIX command /bin/find is useful, particularly its exec flag. However, for each invocation of the exec it spawns a sub process. xargs is much more efficient; it will spawn only so many as are needed -- it does this based on the size of the command line. For instance, if there are 1000 matches to a find, then find would fork 1000 subprocesses, whereas xargs would do far fewer, perhaps even as few as one.
The other useful thing about xargs is you can use it when you an glob (such as *) returns too many matches. Instead of some command * you could do ls * | xargs some command.
Super!
method_missing is to leave out a super. This means that if you don't handle all the cases which could cause an invocation of method_missing then the exception will be lost. So, always include super, unless you have a good reason not to do so.
DateTime to Seconds since Epoch
DateTIme objects to the seconds since the epoch:
1 2 3 4 5 6 7 8 9 10 |
>> d=DateTime.now => Thu, 03 Jan 2008 15:49:21 -0500 >> t=Time.parse(d.strftime("%c")) => Thu Jan 03 15:49:21 -0500 2008 >> t.to_f => 1199393361.0 >> t.to_f.floor => 1199393361 >> |
Hashing properties
This is just a simple piece of code to create a hash of the values of properties of a Ruby object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Object # All objects will inherit this method def make_hash h={ } # start out with a "known quantity" self.instance_variables.each do |v| # for each instance variable do # Instance variables start with an @, so strip it v.sub!(/@/,"") # add our key/value pair to the array only if the variable has # been exposed h[v] = self.send(v) if self.respond_to? v end h # return the hash end end |
Ok, let's test it out:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
$ irb >> load 'nifty.rb' => true >> "a".instance_variables => [] >> "a".make_hash => {} >> class Foo >> attr_reader :bar, :fud >> def initialize >> @bar="Hello World" >> @fud=123 >> @groo = Time.now >> end >> end => nil >> f=Foo.new => #<Foo:0xb7857174 @groo=Wed Jan 02 10:20:36 -0500 2008, @fud=123, @bar="Hello World"> >> f.instance_variables => ["@groo", "@fud", "@bar"] >> f.make_hash => {"bar"=>"Hello World", "fud"=>123} >> quit |
Note that although Foo has three instance variables, only two of those have been exposed (the attr_reader line).
vi global substitution
Something old, something new. vi has been around for almost 30 years, and it seems fitting to start the year with it. vi has what many would consider a cryptic command set, but for all of its age is still quite powerful.
In order to do a global substitution in vi, type the following (escaped if necessary) outside of insert mode:
:%s/from/to/g
%specifies to look on all lines.ssays to substitute./from/to/is the pattern which specifies what is being replaced, as well as its replacementgspecifies that it is a global replacement, that is, all instances on a line, not just the first, are replaced.
