ask the manowar fan
Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

  
#!/usr/bin/env ruby
require File.dirname(__FILE__) + '/../config/environment'
before_time = Time.now
config = Rails::Configuration.new
db_config = config.database_configuration[RAILS_ENV]
{
:table=>"statement"
}.each do |table, statement|
system(%{cd #{RAILS_ROOT}/public && mysql -u #{db_config["username"]} -h #{db_config["host"]} -p#{db_config["password"]} #{db_config["database"]} -e '#{statement}' --xml > #{table}.xml})
end
after_time = Time.now
puts "Took: #{after_time - before_time}"



So awesome, I am.

 

 

I got sick of re-writing the crawl login again and again, and I don't like using the attribute CSS selectors [attr=value]

So I wrote this.


require 'rubygems'
require 'open-uri'
require 'net/http'
require 'hpricot'

class Rule
attr_accessor :tag, :callback
def initialize(tag, &callback)
@tag = tag
@callback = callback
@preconditions = []
end

def all_ok?(tag)
@preconditions.each do |condition|
return false unless condition.call(tag)
end
true
end

def with(condition, &callback)
@preconditions << condition
self.callback = callback
self
end

def with(attribute, value, &callback)
@preconditions << lambda {|tag| tag.attributes[attribute.to_s].include?(value)}
self.callback = callback
self
end
end

class Farser
def initialize(source)
@source = Hpricot(open(source))
@rules = []
end

def find(tag, &callback)
rule = Rule.new(tag, &callback)
@rules << rule
rule
end

def farse
@rules.each do |rule|
@source.search(rule.tag) do |found|
next unless rule.all_ok?(found)
rule.callback.call(found)
end
end
end

def self.fetch(from, to)
uri = URI.parse(from)
return if File.exists?(to)
File.open(to, "wb") do |f|
Net::HTTP.start(uri.host) { |http|
resp = http.get(uri.path)
f.write(resp.body)
}
end
end
end


The usage is pretty simple


farser = Farser.new("http://something.com")
farser.find("a").with(:href, 'index').with(:name, 'someone') do |index_link|
end


No error handling and super duper method chaining.

I love it!

 

"Barring a sharp blow to the head, as you stand here today you are as dumb as you'll ever be."

Quote from Design Patterns in Ruby explaining why solving a problem you haven't encountered yet (eg: internationalizing your application without the real need for it) is risky because you're betting you can solve it right, and you can solve it right now.

Further ...
"Whenever you put in a feature before
you really need it, you are guilty of programming while stupid; if you wait until you
really need the thing, you are likely to have a better understanding of what you need
to do and how you should go about doing it."

 

Bashfully yours gemdocs

That is setting up your bash to give you gemdocs with like ... one line. Or that's kicking your ass.

PS: I had to replace open with firefox for it to work with my Ubuntu box. You might find that helpful.

Peace and love,
The Sid Sid man.

 



require 'test/unit'

class NotTest < Test::Unit::TestCase
def test_quirky_little_bastard_not
assert 1
assert_equal false, !1
assert_equal false, (not 1)
assert (1 && 2), (1 and 2)
assert_equal (not 1 && 2), !(1 && 2)
assert_equal false, (not 1 && nil) == (!1 and nil)
assert_equal (not 1 && nil), (!(1 and nil))
end
end



Quirky little bastard that one, I think the only intuitive approach to this is ... given the list of operator precedence:

!
&&
||
not
or
and

The though could have been not to mix and match hardcore operators (&, !, blah) with English (and, not, blah)

"I can assure you he's a better man than me,
So fuck you, don't tell me."
Dry Kill Logic - Better Man Than Me.

 

Rails fields_for is the cheese

Posted In: , , . By Sid

The reason I really really dig the Rails fields_for helper is this reason:


<%= fields_for "parent[child_object_name][]", child_object_instance do |f| %>
<%= f.text_field :attribute%>
<%end%>


Generates ...


<input id="parent_child_object_name_#{child_object_instance.id}"
name="parent[child_object_name[#{child_object_instance.id}]]" />


In fact you could even try ...


<%= fields_for "parent[child_object_name][]", child_object_instance do |f| %>
<%= f.text_field :attribute, :index=>child_object_instance.name%>
<%end%>

<input id="parent_child_object_name_#{child_object_instance.name}"
name="parent[child_object_name[#{child_object_instance.name}]]" />


This really helps when you're trying to pump in or edit a complicated object graph through a form that was originally designed for a single model. I love this approach because it saves me the trouble of having to initialize my objects in my controller actions in accordance to the way the form was designed just so Rails can populate the fields with the right values.

There's also a cool RailsCast about using fields_for in comlex forms.

 

Initialize Objects from Hashes without using AR:B - Jay Fields

"Check this riff out,
It's fucking tasty"
Tenacious D(Satan) - Pick Of Destiny

 



def sort(arr, crit, i)
final = []
arr = arr.sort_by {|a| a.send(crit[i])}
hash = arr.slice_into_groups(crit[i])
sorted_keys = hash.sort_by {|k, v| k}.gimme_firsts
if i < crit.size - 1
sorted_keys.each do |key|
final << sort(hash[key], crit, i+1)
end
else
final = arr
end
return final.flatten
end

class Array

def slice_into_groups(crit)
hash = {}
self.each do |a|
hash[a.send(crit)] = [] if hash[a.send(crit)].blank?
hash[a.send(crit)] << a
end
hash
end

def gimme_firsts
self.collect{|a| a.first}
end



And Tests for the Array code.



class ArrayTest < Test::Unit::TestCase
def test_slice_into_groups
objects = Model.find(:all)
assert_not_nil objects.size
old_size = objects.size

grouped_objects = objects.slice_into_groups('attribute')

sum = 0
grouped_objects.each do |k, v|
sum += v.size
v.each do |obj|
assert_equal k, obj.attribute
end
end
assert_equal old_size, sum
end

def test_gimme_firsts
assert_equal [1, 2, 3, 4, 5, 6, 7], [[1, 2, 3],[2, 2, 3],[3, 2, 3],[4, 2, 3],[5, 2, 3],[6, 2, 3],[7, 2, 3]].gimme_firsts
end
end



This is basically to keep tests in place for MySQL order bys ... which I know make absolutely no sense, but if there's a requirement and someone changes something I like a test to break to tell them I didn't put the order by in there for nothing.

The index passing down the call stack is fairly ugly but I need to find a better way.

"Open your eyes"
Metallica - Invisible Kid.

 

Ruby StringIO and clone

Posted In: , , . By Sid


>> a = StringIO.new("abcd")
=> #<StringIO:0xb6e1b354>
>> b = a
=> #<StringIO:0xb6e1b354>
>> b.read
=> "abcd"
>> b = a
=> #<StringIO:0xb6e1b354>
>> b.read
=> ""


Notice the hash signature for b is the same as the hash signature for a. Which is why even though you re-assign it to point to a it's already read the contents of the StringIO you created and hence nils out.

Now see this.


>> a = StringIO.new("abcd")
=> #<StringIO:0xb70570a0>
>> b = a.clone
=> #<StringIO:0xb7055994>
>> b.read
=> "abcd"
>> b = a.clone
=> #<StringIO:0xb7053464>
>> b.read
=> ""


The first time you clone a and point it to b, it creates the hash signature as "#<StringIO:0xb6d968ac>" and the second time you clone it it creates a different hash signature "#<StringIO:0xb7053464>". Hence, multiple clone calls actually still point to different memory space, but it's still the same variable?

Now see this.

>> a = StringIO.new("abcd")
=> #<StringIO:0xb7042240>
>> b = a.clone
=> #<StringIO:0xb7040bfc>
>> b.read
=> "abcd"
>> b.rewind
=> 0
>> b = a.clone
=> #<StringIO:0xb703d1dc>
>> b.read
=> "abcd"
>> b
=> #<StringIO:0xb703d1dc>


Apparently when I clone an object, it still retains the property that StringIO has been read. Which behaves uniquely for StringIO considering the read pointer concept. But yes, somethings amiss.

"I came in with my word,
I will leave with my word intact."
Al Pacino - The Insider

 

If you have code that uses DateTime.now you ask yourself "How's my test supposed to pass?" and your pair says "I'd peg it at 1 out of ten times" and if your pair is Rohan Kini you know you have a way out.

Let's set it up right. I have this object:


class User

def initialize
@time_of_birth = DateTime.now
@name = "The dude"
end

def take_over_the_world
p "#{self.name} is taking over the world"
end

end


The tests for which look like


def test_if_use_is_born_with_right_defaults
the_dude = User.new
assert_equal the_dude.time_of_birth, DateTime.now
assert_equal the_dude.name, "The dude"
end


Now obviously a few milliseconds might have past since the execution of User.new so odds are your test will fail even though they should pass.

Here's how you change things around a bit.

In your user class you need to abstract the DateTime.now bit, so you can override things in your test


class User

def date
DateTime.now
end

def initialize
@time_of_birth = date
@name = "The dude"
end

def take_over_the_world
p "#{self.name} is taking over the world"
end

end


And in your test override the new date method you created.

NOW = DateTime.now

class << User

def date
NOW
end

end

def test_if_use_is_born_with_right_defaults
the_dude = User.new # Will use now because you've overridden User::date in the context of this test
assert_equal the_dude.time_of_birth, NOW
assert_equal the_dude.name, "The dude"
end

 

You have a textarea and you're rendering the text you get from it on a page.

Textarea Input:

This is on the first line.

This is on the second line.

This is on the third.

Browser Output:

This is on the first line.This is on the second line.This is on the third.

Now that sucks.


@string = $F(TextAreaId).value
@string = CGI.unescape(@string).gsub(/\n/,"<br />")


And you're done!

PS: $() is prototype.js for getElementById()

"They make you drink your blood,
and tear yourself to pieces!"
Accept - Balls To The Wall

 

Web Spiders in Ruby

Posted In: , . By Sid

A cool PDF on web spiders in Ruby

I'm thinking of trying my hand at one.