====== Code Samples ======
===== Outputting the Alphabet =====
<% "A".upto("Z") do |c| %>
>
<%= link_to '' + c + '', {:action => 'list', :character => c.downcase} %>
<% end %>
===== Keyword Search (In MySQL) =====
@words = Word.find(:all, :conditions => [" root LIKE CONCAT('%',CONCAT(:keyword,'%')) ", {:keyword => keyword}])
===== How to Divide or Split an Array (Or how to Turn One Array into Multiple Arrays) =====
This code adds a "/" instance method to the Array class.
class Array
def / pieces
len = self.length;
mid = (len/pieces)
chunks = []
start = 0
1.upto(pieces) do |i|
last = start+mid
last = last-1 unless len%pieces >= i
chunks << self[start..last] || []
start = last+1
end
chunks
end
end
(I didn't invent this myself, but I've lost the url to the original code. If you're the author, or you know the author, please contact me and I'll put in a link here).
Suppose you have a an array of words which you want to output in two columns. Here's how to do this, using our "/" method:
left, right = *(@words / 2)
The "*" operator is called the **splat** operator, or sometimes the **splash** operator. As is explained [[http://rubysnips.com/splatter-that-array|here]] the splat operator takes an array and pulls the contents out of the array. You can use the splat operator to simplify this code:
why = [:lucky, :stiff, :with, :chunky, :bacon]
v1 = why[0]
v2 = why[1]
v3 = why[2]
v4 = why[3]
v5 = why[4]
To this code:
why = [:lucky, :stiff, :with, :chunky, :bacon]
v1,v2,v3,v4,v5 = *why
Update (20071104): the splat / splash operator returns a copy. Otherwise, a reference is returned. In other words, this code -- without splat/splash -- will also work:
why = [:lucky, :stiff, :with, :chunky, :bacon]
v1,v2,v3,v4,v5 = why
I can't find a real difference between using the splat/splash operator, and not using it, though:
irb(main):001:0> a = Array.new()
=> []
irb(main):002:0> a.push(:first)
=> [:first]
irb(main):003:0> a.push(:second)
=> [:first, :second]
irb(main):004:0> my_first,my_second = a
=> [:first, :second]
irb(main):005:0> puts "my_first: #{my_first}"
my_first: first
=> nil
irb(main):006:0> my_first.equal?(a[0])
=> true
irb(main):007:0> my1, my2 = *a
=> [:first, :second]
irb(main):008:0> puts "my1: #{my1}"
my1: first
=> nil
irb(main):009:0> my1.equal?(a[0])
=> true
irb(main):010:0> b = ['e1','e2']
=> ["e1", "e2"]
irb(main):011:0> split_a1, split_a2 = b
=> ["e1", "e2"]
irb(main):012:0> split_a1.equal?(b[0])
=> true
irb(main):013:0> split_b1, split_b2 = *b
=> ["e1", "e2"]
irb(main):014:0> split_b1.equal?(b[0])
=> true
This seems to indicate that a reference is returned in all cases.
===== How to Return All Elements of an Array Up to An Unknown Point =====
The Array object comes with various handy methods, such as ''collect'' or ''select'' to create a subset. But recently I ran into a problem: how do you return //all elements up till and including the element that meets your search criteria?//
Usually this is not very hard. If your set is ordered by some criterion, you just use ''select'':
# Find all future rock concerts
scheduled_concerts = rock_concerts.select {|rc| rc.date > Date.today}
But now suppose that your set is ordered, but by many criteria. Of course, you could use multiple conditions in the body of the ''select'' method. But now suppose that you already have the id of the object which is your right limit. The following code snippet exemplifies this:
@completed_exercises = Array.new
if (not @saved_game.nil?)
@scheduled_exercises.each do |s|
@completed_exercises.push(s.id)
break if s.id == @saved_game.scheduled_exercise_id
end
end
Here, I needed both the entire set of available exercises (@scheduled_exercises, retrieved elsewhere), as well as the set of completed exercises (@completed_exercises).