Saturday, February 10, 2007

A Ruby Metaprogramming Introduction

I was playing around with some unit tests to explore Ruby singleton classes on a recent flight when I decided they could be fleshed out into a pretty nice introduction to some basics of Ruby metaprogramming for those who haven't done much with Ruby (which probably includes most people who've only written Rails applications). I particularly like the format because readers can

  • read it in their syntax-highlighting editor of choice, and
  • play with the code locally to explore further.

If you want to get straight to mucking around, download this zip file, which also contains demo_test_unit_extensions.rb.

If you're not that invested yet, here it is.


require 'demo_test_unit_extensions'

class MetaprogrammingIntroduction < Test::Unit::TestCase

=begin
This is a demonstration of dynamic method definition using the private method
Module#define_method and an introduction to singleton classes (also known as
metaclasses). This is the basis of Ruby metaprogramming.

Note that I'm going to avoid use or discussion of Ruby's very important eval
methods in this article. This is only to reduce the scope of what's explained.
In practice I'd prefer module_eval or class_eval to reopening of classes or
modules or use of Object#send to invoke private methods.

Chapter 24 in the Pickaxe is your reference for the nuts and bolts of Ruby
classes. There's surprisingly little discussion of things you can do with
metaprogramming, but all the information you need is there. _why the lucky
stiff's Seeing Metaclasses Clearly is dense and opaque, but fun:
http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
=end
show "Calling define_method on a class adds an instance method to both
existing and new instances.
" do
GuineaPig = Class.new
pig = GuineaPig.new
class GuineaPig
define_method :next_integer do
@count = (@count || 0) + 1
end
end

assert_equal 1, pig.next_integer
assert_equal 2, pig.next_integer
assert_equal 1, GuineaPig.new.next_integer
end
=begin
This isn't all that cool, as we could have defined next_integer using the def
keyword. But Module#define_method allows us to do a couple of things the def
keyword doesn't.

First, we can define our method name dynamically. Module#define_method takes a
symbol or string as the method name, whereas the method name following the def
keyword must be spelled out literally. You can satisfy this by evaluating a
string of Ruby code that defines the method using def, but I usually find this
less readable than using define_method. Try them both and see which reads better
in your context.

The second interesting aspect of using define_method is that you pass it a
block, Ruby's closure.
=end
show "Method bodies created with define_method can reference the context in
which they were created.
" do
GuineaCounter = Class.new
shared_count = 0 # A new local variable.
GuineaCounter.send :define_method, :double_count do
shared_count += 1
@count ||= 0
@count += 1
[shared_count, @count]
end
first_counter = GuineaCounter.new
second_counter = GuineaCounter.new

assert_equal [1, 1], first_counter.double_count
assert_equal [2, 2], first_counter.double_count
assert_equal [3, 1], second_counter.double_count
assert_equal [4, 2], second_counter.double_count
end
=begin
Even if the method that defined the local variable shared_count completed
execution, the method in GuineaCounter will still be bound to the context of the
method. (This binding isn't simple, as the block also assigns instance variables
which obviously land in the right place. Look for a forthcoming write-up
exploring this in depth.)

Note the use of Object#send to invoke define_method, where we just reopened the
class in earlier demonstrations. This is necessary if we want the block to bind
to our local context. As mentioned earlier, I prefer module_eval or class_eval
for this, but I'm leaving those out of this article.

This next one may seem obvious, but it'll only take a moment.
=end
show "Sending define_method to a module is consistent with sending it to a
class.
" do
o = Object.new.extend(Enumerable)
# Object#extend mixes a module into an instance without affecting other
# instances of the same class.

assert(o.is_a?(Enumerable) && {}.is_a?(Enumerable))

hash = {}
Enumerable.send :define_method, :next_integer_for_enumerables do
@count_for_enumerables = (@count_for_enumerables || 0) + 1
end

assert_equal 1, o.next_integer_for_enumerables
assert_equal 1, hash.next_integer_for_enumerables
assert_equal 2, hash.next_integer_for_enumerables
assert_equal 1, Array.new.next_integer_for_enumerables
# But since we only extended that one instance of Object up above ...
assert_raises(NoMethodError) { Object.new.next_integer_for_enumerables }
end
=begin
This next point is something of a tangent, but it's important to keep in mind,
as it could bite you at some point.
=end
show "Remember that adding methods to Object puts them all over the place, so
be careful!
" do
o = Object.new
Object.send :define_method, :next_integer_for_all do
@count_for_all = (@count_for_all || 0) + 1
end

# So obviously, ...
assert_equal 1, o.next_integer_for_all
assert_equal 2, o.next_integer_for_all

# But we also now have the method in this Test::Unit::TestCase.
assert_nil @count_for_all
assert_equal 1, next_integer_for_all
assert_equal 1, @count_for_all

# Classes are Objects too, so they've all gained a class method, which
# maintains a count independent from its instances.
assert_equal 1, String.next_integer_for_all
assert_equal 2, String.next_integer_for_all
assert_equal 1, "".next_integer_for_all
end
=begin
This isn't mind-blowing, but it can be easy to accidentally call the method with
the wrong receiver if you lose track of your current context.

The takeaways from that are:
* don't add methods to Object unless you've got a damn good reason, and
* prove that you're getting the desired behavior with tests.

Now here's where the cool stuff starts! Let's talk about singleton methods and
classes.

Above, we used Object#extend to mix a module into one instance of Object without
affecting other instances or the Object class itself. You've probably also seen
that Ruby allows you to define methods on just single instances. When done the
simple way, this looks like the following:
=end
show "Methods can be defined on single instances using the def keyword.
These are referred to as 'singleton methods.'
" do
o, p = Object.new, Object.new

def o.say_hi
'hello there'
end

assert_equal 'hello there', o.say_hi
assert_raises(NoMethodError) { p.say_hi }
assert_equal ['say_hi'], o.singleton_methods
assert_true p.singleton_methods.empty?
end
=begin
So that's neat, but what if we want some of the power of Module#define_method
discussed earlier? What module or class should define_method to add a method to
just one object? The singleton class!

Classes and Modules are special objects that can hold methods for other objects
to respond to. It would have been a shame for Matz to have had to implement
another sort of method owning facility to handle singleton methods, so Ruby does
some hidden trickery when we define a method on an instance: it creates a
virtual class to hold methods specific to that object, inserting it into the
chain of classes that will be checked for methods when it's looking to handle a
message sent to the object. The object's class method will still return the
original class, but the singleton class actually gets "first dibs" at responding
to a call. These classes are hidden from ObjectSpace and created without calling
Class.new, making them hard to get a hold of.

What do we call these things? The term 'singleton class' makes some sense, as
there's only one per object. This name can be confusing though, because of the
Singleton design pattern (easily implemented in Ruby by including the stdlib
module Singleton). The term 'metaclass' is used frequently, but it comes from
other languages and really applies only to the class of a class. Matz is
considering calling singleton classes 'eigenclasses' in future versions of Ruby
to reduce confusion with other concepts. (Chances are you don't have a
preconceived notion of what 'eigenclass' ought to mean, so there's nothing to
get mixed up with these funny classes in Ruby.) I'll continue to refer to these
as 'singleton classes' for now.

How unusual is it for singleton classes to come into play? It happens far more
frequently than we think about them, because all class methods are actually
singleton methods of instances of Class. Here's a simple class with a couple
class methods.
=end
class Greeter
def greet; 'hello!'; end

def self.describe_greeting
'Mostly it''s just saying hello to people.'
end
end

def Greeter.say_more
'Actually, saying hello pretty much covers it.'
end
=begin
Notice how similar the second and third method definitions look to our singleton
method definition above. That's not a coincidence: describe_greeting and
say_more are both singleton methods of the object Greeter, an instance of the
class Class. These methods are both held in Greeter's singleton class, the first
place Ruby looks for methods when Greeter receives a message.
=end
show "So-called 'class methods' are really just singleton methods of
instances of Class.
" do
assert_equal ['describe_greeting', 'say_more'].sort, Greeter.singleton_methods.sort
end
=begin
Once you digest it, this hidden consistency makes it much easier to keep track
of what's going on in Ruby.

Now, we said above that singleton classes are hidden. How do we get at them?
Ruby gives us just one way in: the "class double-ell." Let's use this to add a
singleton method to a Greeter.
=end
show "The 'class double-ell' gets us into the definition of an object's
singleton class.
" do
jim, jane = Greeter.new, Greeter.new
class << jim
def greet_enthusiastically
self.greet.upcase
end
end

assert_equal 'HELLO!', jim.greet_enthusiastically
assert_raises(NoMethodError) { jane.greet_enthusiastically }
end
=begin
This is also a third way (besides the two we saw above) to create class methods.
It's the only one that allows Ruby's visibility modifiers to work the way
they're normally used for instance methods (where they look like keywords even
though they're really method calls).
=end
show "The 'class double-ell' can be used to create non-public class methods." do
class Greeter
class << self
private
def secret_truth
'Greeting gets old fast!'
end
public
def truth
secret_truth.gsub /old fast/, 'better with every passing year'
end
end
end
assert_raises(NoMethodError) { Greeter.secret_truth } # because it's private
assert_equal 'Greeting gets better with every passing year!', Greeter.truth
end
=begin
Now let's make these singleton classes easier to get to. We create an instance
method on Object that returns the receiver's singleton class. I use the
convention of calling this method 'metaclass,' even though it's a poor name for
reasons already discussed.
=end
class ::Object
def metaclass
class << self
self
end
end
end

show "The singleton class is a class, but not the same one returned by the
Object#class method.
" do
hash = Hash.new

assert_true hash.metaclass.is_a?(Class)
assert_false hash.class == hash.metaclass
end

show "Our method returns the same object on repeated calls to the same
receiver.
" do
hash = {}

assert_same hash.metaclass, hash.metaclass
end

show "Instances do not share the same singleton class instance." do
assert_not_same({}.metaclass, {}.metaclass)
end
=begin
I'd also like to demonstrate here that an object doesn't have a singleton class
until it's actually needed, but I can't think of a way to do that given the
hiding discussed earlier.

Get ready for a mouthful.
=end
show "The singleton class instance of a class is the superclass of the
singleton class instances of instances of that class. Phew!
" do
assert_same( {}.metaclass.superclass, Hash.metaclass)
end
=begin
I can't think of any reason that's useful, but there it is. The same goes for
singleton classes of classes (true metaclasses).
=end
show "Same diff when the instance in question is a class." do
assert_same Hash.metaclass.superclass, Class.metaclass
end

show "Bizarrely, same diff even when the instance in question is Class
itself!
" do
assert_same Class.metaclass.superclass, Class.metaclass
end
=begin
Right this moment, it appears the inheritance chain of singleton classes may
change in the next version of Ruby. See this relatively awesome distillation of
changes in play for Ruby 1.9:
http://eigenclass.org/hiki.rb?Changes+in+Ruby+1.9

Anyway, back to what we were trying to do: use Module#define_method to create a
singleton method.
=end
show "Calling define method on a singleton class creates a singleton
method.
" do
o = Object.new

assert_equal 0, o.singleton_methods.size

o.metaclass.send :define_method, :countdown do
(@numbers ||= (1..3).to_a.reverse.push('POW!')).shift
end

assert_equal ['countdown'], o.singleton_methods
assert_raises(NoMethodError) { Object.new.countdown }
assert_equal 3, o.countdown
assert_equal 2, o.countdown
assert_equal 1, o.countdown
assert_equal 'POW!', o.countdown
end
=begin
I'm surprised that Matz didn't put a method on Object called
define_singleton_method, allowing us to do the same thing we did above without
exposing singleton classes. To me they feel like an implementation detail we
shouldn't have needed to see.

Let's create that method now.
=end
class ::Object
def define_singleton_method name, &body
singleton_class = class << self; self; end
singleton_class.send(:define_method, name, &body)
end
end
=begin
This is functionally equivalent to _why's meta_def method, but that name bugs
me a lot, so I'm not using it.
=end
show "Use of our newly created Object#define_singleton_method to create a
singleton method without ever seeing the singleton class.
" do
o = Object.new
o.define_singleton_method :get_excited do
@excitation_rant = (@excitation_rant || "I'm getting excited.").gsub(/excited/, "really excited")
end

assert_equal "I'm getting really excited.", o.get_excited
assert_equal "I'm getting really really excited.", o.get_excited
assert_equal "I'm getting really really really excited.", o.get_excited
end
=begin
With the ability to dynamically define methods on classes and instances at
runtime, you have the tools needed for some pretty interesting metaprogramming.
Have fun with it, just keep an eye on the developers around you to see if you're
going too meta on them.

---

If you have any comments, questions, suggestions, corrections, or additions for
this write-up, please leave comments on Practical Ruby
(http://practicalruby.blogspot.com/).

Thanks to a whole bunch of people for useful feedback, particularly: Jay Fields,
Z, Chris George, Ali Aghereza, and Omar Ghaffar.
=end
end

Labels:

57 Comments:

Anonymous Anonymous said...

This is awesome work! Thank you!

6:07 PM  
Blogger John Hume said...

For an exploration of Ruby eval, see Jay's recent article on InfoQ.

10:02 AM  
Anonymous Rupert said...

wow - excellent - many thanks. I think I've got my head round most of it and my brain only hurts slightly!

The one thing I've had a real problem grasping though is this:

------------------
class Greeter
def self.describe_greeting
'Mostly it''s just saying hello to people.'
end
end

g = Greeter.new
g.metaclass.send :define_method, :get_excited do
"but sometimes I just can't control myself"
end
------------------

now, I understand that

------------------
Greeter.singleton_methods # => ["describe_greeting"]
g.singleton_methods # => ["get_excited"]
------------------

but the thing I don't get is why I get the following....

------------------
Greeter.metaclass.methods(false) # => []
g.metaclass.methods(false) # => ["describe_greeting"]
------------------

I was not expecting this at all and don't unsderstand why describe_greeting in the methods for g's
metaclass.

I was expecting that the singleton methods of an object would be the same as the methods in that object's metaclass.

Hoping this makes sense and you can help to clear my confusion - as I've obviously not totally grasped something important

Thanks again for a great article

Cheers

Rupert

11:50 AM  
Anonymous Rupert said...

Think I've got it sussed now ....after a very late night with irb and rather a lot of itterations of a diagram to show me what's happening it's all clicked into place :)

Thanks again for the artticle - Cheers

Rupert

9:15 AM  
Anonymous free ps3 said...

Thanks for the nice post!

7:59 AM  
Blogger John Hume said...

If you're trying to wrap your head around singleton classes and metaclasses, have a look at a couple of recent posts by Patrick Farley: "The Singleton Class," and "The Metaclass."

7:13 AM  
Anonymous Anonymous said...

Thanks John! Great article.

11:41 AM  
Anonymous Tammo Freese said...

Great post, especially using tests to ensure that the results are correct. I found only one small glitch. You wrote:

"Right this moment, it appears the inheritance chain of singleton classes may change in the next version of Ruby."

In fact, it won't change, but the methods superclass and < for class will be fixed to return correct values:

The superclass of the metaclass of a hash is Hash, the superclass of the metaclass of Hash is the metaclass of Object, and the superclass of the metaclass of Class is the metaclass of Module. Phew! ;)

3:29 AM  
Blogger John Hume said...

For an updated version of this article, see the metaprogramming_introduction project on GitHub.

5:29 AM  
Anonymous website design nyc said...

nice post

4:27 AM  
Blogger john said...

ITemplatez.com offers professional web templates, flash templates ,swish templates, dreamweaver templates, and other web design productsavailable for immediate download.

4:41 AM  
Blogger 独孤客 said...

When the Wow Gold wolf finally found the wow gold cheap hole in the chimney he crawled cheap wow gold down and KERSPLASH right into that kettle of water and that was cheapest wow gold the end of his troubles with the big bad wolf.

game4power.
The next day the Buy Wow Goldlittle pig invited hisbuy gold wow mother over . She said "You see it is just as Cheapest wow goldI told you. The way to get along in the world is to do world of warcraft gold things as well as you can." Fortunately for that little pig, he buy cheap wow gold learned that lesson. And he just wow gold lived happily ever after!.

11:18 PM  
Blogger buy wow gold said...

When the Wow Gold wolf finally found the wow gold cheap hole in the chimney he crawled cheap wow gold down and KERSPLASH right into that kettle of water and that was cheapest wow gold the end of his troubles with the big bad wolf.

game4power.
The next day the Buy Wow Goldlittle pig invited hisbuy gold wow mother over . She said "You see it is just as Cheapest wow goldI told you. The way to get along in the world is to do world of warcraft gold things as well as you can." Fortunately for that little pig, he buy cheap wow gold learned that lesson. And he just wow gold lived happily ever after!.

4:51 AM  
Blogger fashion jewelry said...

wholesale jewelryhandmade jewelryjewelry wholesalefashion jewelrycostume jewelry

6:52 PM  
Blogger feilin said...

My friends and I like to buy habbo credits, because the habbo gold is very useful to upgrade equipment. Only your equipment becomes better, then you can win this game. In habbo coins, you can buy everything you want in this game. Tomorrow will be my birthday, so my friends promise to buy habbo gold as gifts. I am so happy. They understand me so well, cheap habbo credits is my favorite.
I like hero gold very much because it is very useful. In fact at first sight I have fallen in love with hero online gold. So no matter how much I have spent to buy hero gold, I never regret. Because of hero online money, I meet a lot of friends. So I never hesitate to buy hero money.

6:30 PM  
Blogger buy wow gold said...

When the Wow Gold wolf finally found the wow gold cheap hole in the chimney he crawled cheap wow gold down and KERSPLASH right into that kettle of water and that was cheapest wow gold the end of his troubles with the big bad wolf.

game4power.
The next day the Buy Wow Goldlittle pig invited hisbuy gold wow mother over . She said "You see it is just as Cheapest wow goldI told you. The way to get along in the world is to do world of warcraft gold things as well as you can." Fortunately for that little pig, he buy cheap wow gold learned that lesson. And he just wow gold lived happily ever after!.

3:27 AM  
Blogger belrion18 said...

buy wow goldbuy wow goldbuy wow accountbuy wow gold

5:14 AM  
Anonymous Anonymous said...

I always heard something from my neighbor that he sometimes goes to the internet bar to play the game which will use him some Perfect World Gold,he usually can win a lot of Buy Perfect World Gold,then he let his friends all have some Perfect World Silver,his friends thank him very much for introducing them the Perfect World money,they usually cheap Perfect World Gold together. And get more fun from the pw gold.
I am so happy to get some Pirates of the Burning Sea Gold and the potbs gold is given by my close friend who tells me that the potbs Doubloon is the basis to enter into the game. Therefore, I should potbs money with the spare money and I gain some buy potbs Doubloon from other players.

6:11 PM  
Anonymous Anonymous said...

Do you know cabal online alz? I like it.
My brother often goes to the internet bar to buy cabal alz and play it.
After school, He likes playing games using these cabal gold with his friend.
I do not like to play it. Because I think that it not only costs much money but also spend much time. One day, he give me many cabal money and play the game with me.
I came to the bar following him and found buy cabal alz was so cheap. After that, I also go to play game with him.


Do you know dofus kamas? I like it.
My brother often goes to the internet bar to buy kamas and play it.
After school, He likes playing games using these cheap kamas with his friend.
I do not like to play it. Because I think that it not only costs much money but also spend much time. One day, he give me many dofus gold and play the game with me.
I came to the bar following him and found buy dofus kamas was so cheap. After that, I also go to play game with him.

6:21 PM  
Anonymous Anonymous said...

Have you heared about a game which you need use priston tale Gold to play, and you can also borrow priston tale Money from other players? But you can buy priston tale Gold, or you will lose the choice if you do not have cheap priston tale Gold. If you get it, you can continue this game.
Have you heared about 9Dragons which you need use 9Dragons gold to play, and you can also borrow 9 Dragons gold from other players? But you can buy 9 Dragons gold, or you will lose the choice if you do not have cheap 9Dragons gold. If you get 9Dragons money, you can continue this game.

7:42 PM  
Anonymous Anonymous said...

I want give they happy time, twelve sky Gold, I work here with 12sky gold. Though, I can not make much money, twelvesky Gold, But I want to Exercise myself, 12Sky Silver Coins, I get up early 12 sky goldI always believe the angel is being and 12sky2 Gold . In fact, we all like listening to the songs of milk tea twelve sky2 Gold .
Generally speaking, I think is her voice very comfortable and mood of the story twelvesky2 Gold , We feel life bit by bit, looking forward the love belonging of the life feelings buy 12sky2 Gold , you will love milk tea like me, let us love her together and play cheap twelve sky2 Gold .

9:46 PM  
Anonymous Anonymous said...

Buy Rom Gold is the chance. I always have a bad dream when my account was theft, since I buy Rom Gold ; I had not had the bad memory. At present, I want to say thanks to the people who stole my account, if he did not to do that, I would not play game, I would not have Runes of Magic Gold . Although I have little Runes of Magic money , I will on the way of the game for long time. At one time or another, I am a pessimistic person, but when I have cheap Runes of Magic Gold , it changes my attitude of life.

Remembered the first time I played the game and bought wonderland Gold , it is about two years. Since the first day I bought wonderland online Gold , we should know that the day will come sooner or later. And I will not leave my wonderland money . My friends forever, even though I will leave you one day, I will remember you forever. At that time, I was a naive; I must used money to buy wonderland Gold , as that I would not depend on myself. But I was not regret to buy cheap wonderland online Gold . It is just a way bring me to the success.

10:37 PM  
Anonymous Anonymous said...

Do you know that the knight gold, and do you want to know? In the game many players need the knight noah to up their levels. so they often search where can buy the knight online gold, I think our website is your choice. Many friends told me that in here can knight online noah, and you will also practice your online games skills. So i hope more and more players come here to buy the cheap knight gold.
Do you want to know the magic of online games, and here you can get more requiem gold. Do you want to have a try? Come on and requiem lant can make you happy. You can change a lot requiem money for play games. Playing online games can make much cheap requiem lant. If you want your game level to up highly, you can come here. And you can use the requiem online gold do what you want to do in the online game.

10:56 PM  
Blogger 梦中林 said...

A slim, wide-eyed mygamegoldwoman almost human in virbanksfeatures eyed agamegold the pair. Her nose was sharp, but very elegant. She had tbcgold a pale, trade4gamebeautiful face the color of ivory, and veryge for hair she wore a wondrous mane of downy feathers. Her gown fluttered as she walked—on two delicate worldofgolds but still sharply-taloned feet. “Awake, awake you are,” she said with a pvp365 slight frown. “You should rest, rest.” Krasus bowed to her. “I am ezmmorpg grateful for your ighey hospitality, mistress, but I am well enough to continue on9a9z now.” She cocked her head as a bird might, giving the mageltk365 a reproving look. “No, no…too soon, toogold4guild soon. Please, sit.” The duo looked around u4game and discovered that two chairs, made in the same ready4game fashion as the nest, waited behind happygolds them. Malfurion waited for Krasus, who finally nodded and sat.

12:53 AM  
Blogger buy wow gold said...

There are several tbcgold races stand up and take the fightakgame to the demons under assault by the Legion. The races are unaligned at character mygamestock start, and can choose to become ttgaming friendly with either Horde or Alliance over the course of their careers. Faction gained belrion with one side eventually live4game causes faction loss with the other, until the character is as much Horde or Alliance as an Orc or mmopawn Human. Each race has awowgoldget starting city with 1-20 zone content.
When you hunt, the enemies you agamegoldkill drop items, and even the most useless ones can be sold to vendors for money. Quests trade4game on the other hand give up rewards in money and items, the money gamersell part is most useful as it is usually a large sum world of warcraft rpg-tradergold. Crafting is also another alternative for earning Gold, you just choose wowpoweronany two professions and use it to gather raw materials or create gamegoodyitems which you can sell to vendors or players. Items sell egrichhigher to players since vendors have a set price and people always want to buy wow gold us ogpalat a lower price than the vendor but sell at a higher price, so there usually is a euwowgoldmiddle price world of warcraft gold. To see what the going ratemymmoshop is, type in "PC" (Price Check) in the Trade Chat window and the item you want to price check and someone should reply with the going-rate for that item

4:45 AM  
Anonymous Gold Guide for World of Warcraft said...

good post :)

12:02 PM  
Blogger buy wow gold said...

There are several tbcgold races stand up and take the fightakgame to the demons under assault by the Legion. The races are unaligned at character mygamestock start, and can choose to become ttgaming friendly with either Horde or Alliance over the course of their careers. Faction gained belrion with one side eventually live4game causes faction loss with the other, until the character is as much Horde or Alliance as an Orc or mmopawn Human. Each race has awowgoldget starting city with 1-20 zone content.
When you hunt, the enemies you agamegoldkill drop items, and even the most useless ones can be sold to vendors for money. Quests trade4game on the other hand give up rewards in money and items, the money gamersell part is most useful as it is usually a large sum world of warcraft rpg-tradergold. Crafting is also another alternative for earning Gold, you just choose wowpoweronany two professions and use it to gather raw materials or create gamegoodyitems which you can sell to vendors or players. Items sell egrichhigher to players since vendors have a set price and people always want to buy wow gold us ogpalat a lower price than the vendor but sell at a higher price, so there usually is a euwowgoldmiddle price world of warcraft gold. To see what the going ratemymmoshop is, type in "PC" (Price Check) in the Trade Chat window and the item you want to price check and someone should reply with the going-rate for that item brogameswagvaultgoldsoonoforuigxethsale

8:34 PM  
Blogger To said...

Jewelry MarketKorean Jewelry

10:54 PM  
Blogger 梦中林 said...

A slim, wide-eyed mygamegoldwoman almost human in virbanksfeatures eyed agamegold the pair. Her nose was sharp, but very elegant. She had tbcgold a pale, trade4gamebeautiful face the color of ivory, and veryge for hair she wore a wondrous mane of downy feathers. Her gown fluttered as she walked—on two delicate worldofgolds but still sharply-taloned feet. “Awake, awake you are,” she said with a pvp365 slight frown. “You should rest, rest.” Krasus bowed to her. “I am ezmmorpg grateful for your ighey hospitality, mistress, but I am well enough to continue on9a9z now.” She cocked her head as a bird might, giving the mageltk365 a reproving look. “No, no…too soon, toogold4guild soon. Please, sit.” The duo looked around u4game and discovered that two chairs, made in the same ready4game fashion as the nest, waited behind happygolds them. Malfurion waited for Krasus, who finally nodded and sat.
brogameswagvaultgoldsoonoforuigxethsale

1:17 AM  
Blogger miyuki said...

A study last yearnike tn, the author in the essay read NIKE , a reporter at the Shanghai headquarters in an interview, nike chaussuressee a pr in high school to read a league plans, employees interviewed told reporters in Beijing's streets, they children to interview, the children said, "truly understand them." tn chaussures These words, if the author touches product function, brand spirit and culture is to become part of the consumer of two basic methods

7:52 PM  
Blogger qwee2232 said...

Our store provide New babolat pure drive, feel more soft,and greatly reduced the previous disadvantage of wilson k six hard and shock-absorbing.With the Cortex System head microgel,Aero Modular Technology, and Woofer technology,the prince-o3-tour has so much put into ball control its not only going to give you the maximum control but cheap tennis racquets will give you a faster swing.

6:47 PM  
Blogger qwee2232 said...

polo ralph lauren integrates two types of luxury and leisure style, now more and more popular men’s burberry polos“thin” sense, most designers have sought to perfect the cut with “cutting” polo women clothing a bag of bones polo logo of the body. It is amazing that a tight lacoste polo shirts with pencil pants, full of retro style with a European aristocratic culture of leisure. Color of polo shirts in vogue, including white polo shirt, pink polo shirt, blue polo shirt , and yellow cheappolos , timely reflects the mainstream of men’s summer fashion colors polo fashion.

6:52 PM  
Blogger j said...

ralph lauren poloburberry polo shirtthe north face jacketcolumbia jacketspyder jacket

7:16 PM  
Blogger j said...

Bought the Tennis Racquet is important, exercise can reduce the harm, especially for the wrist injury. But the good of Tennis Racket in general in the real prices are more expensive, so a lot of websites now have cheap tennis racquet,tennis racquet discount,cheap tennis racket,discount Tennis Racket .

7:16 PM  
Blogger crystal said...

Men's polo shirts was the shirt of choice for diverse groups of

teenagers

Brightly coloured polo shirts can make you look like a Day-glo

dirigible.

Wonderful!You can find the father who desire fashionable, intellectual polo shirt simultaneously

11:41 PM  
Blogger crystal said...

God bless you!I really agree with your opinions.Also,there are some new fashion things here,gillette razor blades,ugg boots,polo clothing.gillette mach3 razor

blades
,gillette venus razor blades,gillette fusion blades are all the best choice for you.

11:42 PM  
Blogger crystal said...

Wonderful!!You can find the father who desire fashionable, intellectual cheap

polos
simultaneously, you can find a psychologist to study the most harmonious of families should be pink mens clothing, so do not want to take the mature route for the father, buy cheap polos, the learn from such a walk in between the formal and casual

styling, refined style to create a sense of mild authority.

11:44 PM  
Anonymous Anonymous said...

Do not mean bad.Thank you so much!I just want to show some fashion things to all of you.I like ugg boots.black ugg boots,Loose T

-shirt or super-size clothing are the best partners, it allows you to exercise in relax.The classic style cheap uggs may fit someone.You should never design yourself into a monster of

no golden section point because beautiful cheap ugg boots.Also,for ladies,

in winter sheepskin boots are the excellent choice.ugg boots on sale

11:45 PM  
Blogger crystal said...

Awesome!!!Best wishes for you !! wholesale polo shirts is the father of the

summer should be prepared to most commonly used item, it has both style and shape of polo clothing, and vest with a random function, so that in the short-sleeved

apply to both on many occasions, the pink and black color men's polo shirts

brought into effect, lightweight cotton, linen texture to demonstrate masculine temperament and sense of fashion

exhaustively. polo shirts for sale

12:02 AM  
Anonymous lljj said...

Perfect!!You are a outstanding person!Have you ever wore chaussures puma, puma CAT,Puma shoes store gives some preview of puma

speed cat
,puma basket, puma speed, puma speed and other puma shoes. These puma sport items are at store recently and available for anyone.

12:03 AM  
Blogger nike said...

Lacoste polo shirts
north face jackets
cheap handbags
cheap purse
women's nike shoes

5:48 PM  
Blogger haitao said...

cheap hair straighteners

new polo shirts
cheap Lacoste polo shirts
cheap Lacoste polo shirts

cheap handbags
cheap bags
puma chaussures
chaussures puma
chaussure puma

Men's North Face
Women's North Face


hair straighteners
sexy lingerie store
cheap ugg boots
tattoo wholesale
men's clothing
women's clothing


2009 nike shoes
new nike shoes
Women's max
Men's max 93
nike shox
Nike air force
Nike air max 2003
nike air max ltd
nike air max tn
Nike air rift
Nike air Yeezy
nike airmax
Nike air max 90
Nike air max 97
nike birds nest shoes
nike dunk
nike RT1 shoes
nike SB
nike shox shoes
Nike shox OZ shoes
Nike shox R2 shoes
Nike shox R3 shoes
Nike shox R4 shoes
Nike shox R5 shoes
Nike shox TL3
nike trainers lovers

tennis rackets
Wilson tennis rackets
HEAD tennis rackets
Babolat tennis rackets

11:46 PM  
Blogger milf said...

dessicant air dryerpediatric asthmaasthma specialistasthma children specialistcarpet cleaning dallas txcarpet cleaners dallascarpet cleaning dallas

vero beach vacationvero beach vacationsbeach vacation homes veroms beach vacationsms beach vacationms beach condosmaui beach vacationmaui beach vacationsmaui beach clubbeach vacationsyour beach vacationscheap beach vacations

bob hairstylebob haircutsbob layeredpob hairstylebobbedclassic bobCare for Curly HairTips for Curly Haircurly hair12r 22.5 best pricetires truck bustires 12r 22.5

washington new housenew house houstonnew house san antonionew house ventura

6:45 AM  
Blogger milf said...

new houston house houston house txstains removal dyestains removal clothesstains removalteeth whiteningteeth whiteningbright teeth

jennifer grey nosejennifer nose jobscalebrities nose jobsWomen with Big NosesWomen hairstylesBig Nose Women, hairstyles

6:45 AM  
Blogger milf said...

black mold exposureblack mold symptoms of exposurewrought iron garden gatesiron garden gates find them herefine thin hair hairstylessearch hair styles for fine thin hairnight vision binocularsbuy night vision binocularslipitor reactionslipitor allergic reactionsluxury beach resort in the philippines

afordable beach resorts in the philippineshomeopathy for eczema.baby eczema.save big with great mineral makeup bargainsmineral makeup wholesalersprodam iphone Apple prodam iphone prahacect iphone manualmanual for P 168 iphonefero 52 binocularsnight vision Fero 52 binocularsThe best night vision binoculars here

night vision binoculars bargainsfree photo albums computer programsfree software to make photo albumsfree tax formsprintable tax forms for free craftmatic air bedcraftmatic air bed adjustable info hereboyd air bedboyd night air bed lowest price

6:46 AM  
Blogger milf said...

find air beds in wisconsinbest air beds in wisconsincloud air beds

best cloud inflatable air bedssealy air beds portableportables air bedsrv luggage racksaluminum made rv luggage racksair bed raisedbest form raised air bedsbed air informercialsbest informercials bed airmattress sized air beds

bestair bed mattress antique doorknobsantique doorknob identification tipsdvd player troubleshootingtroubleshooting with the dvd playerflat panel television lcd vs plasmaflat panel lcd television versus plasma pic the bestadjustable bed air foam The best bed air foam

hoof prints antique equestrian printsantique hoof prints equestrian printsBuy air bedadjustablebuy the best adjustable air bedsair beds canadian storesCanadian stores for air beds

migraine causemigraine treatments floridaflorida headache clinicdrying dessicantair drying dessicant

6:46 AM  
Blogger nike said...

http://www.shoesbuying.com/ : 2009 nike shoes
http://www.shoesbuying.com/2009-nike-shoes-c-153.htm : new nike shoes
http://www.shoesbuying.com/air-max-classic-bw-c-185.htm : Women's max
http://www.shoesbuying.com/mens-max-93-c-188.htm : Men's max 93
http://www.shoesbuying.com/nike-shox-c-165.htm : nike shox
http://www.shoesbuying.com/nike-force-c-174.htm : Nike air force
http://www.shoesbuying.com/nike-2003-c-181.htm : Nike air max 2003
http://www.shoesbuying.com/nike-air-max-ltd-c-166.htm : nike air max ltd
http://www.shoesbuying.com/nike-air-max-tn-c-167.htm : nike air max tn
http://www.shoesbuying.com/nike-rift-shoes-c-162.htm : Nike air rift
http://www.shoesbuying.com/nike-yeezy-c-184.htm : Nike air Yeezy
http://www.shoesbuying.com/nike-airmax-c-154.htm : nike airmax
http://www.shoesbuying.com/nike-airmax-c-155.htm : Nike air max 90
http://www.shoesbuying.com/nike-airmax-c-157.htm : Nike air max 97
http://www.shoesbuying.com/nike-birds-nest-shoes-c-152.htm : nike birds nest shoes
http://www.shoesbuying.com/nike-dunk-high-c-177.htm : nike dunk
http://www.shoesbuying.com/nike-shoes-c-168.htm : nike RT1 shoes
http://www.shoesbuying.com/nike-sb-c-180.htm : nike SB
http://www.shoesbuying.com/nike-shox-shoes-c-156.htm : nike shox shoes
http://www.shoesbuying.com/nike-shox-shoes-c-158.htm : Nike shox OZ shoes
http://www.shoesbuying.com/nike-shox-shoes-c-159.htm : Nike shox R2 shoes
http://www.shoesbuying.com/nike-shox-shoes-c-160.htm : Nike shox R3 shoes
http://www.shoesbuying.com/nike-shox-shoes-c-163.htm : Nike shox R4 shoes
http://www.shoesbuying.com/nike-shox-shoes-c-164.htm : Nike shox R5 shoes
http://www.shoesbuying.com/nike-shox-c-171.htm : Nike shox TL3
http://www.shoesbuying.com/nike-trainers-lovers-c-118.htm : nike trainers lovers

http://www.racketsoffer.com/ : tennis rackets
http://www.racketsoffer.com/wilson-racquets-c-19/ : Wilson tennis rackets
http://www.racketsoffer.com/head-racquets-c-18/ : HEAD tennis rackets
http://www.racketsoffer.com/babolat-racquets-c-17/ : Babolat tennis rackets

10:51 PM  
Blogger Miker said...

I like your blog . They are really great. Ermunterung ++ .
some new style Air shoes is in fashion this year.Do you know Air Shoes is a best . another kinds of nike air rift is better . the Puma basket will make you feel very relaxed when you play basketball.
If you want to buy the Cheap puma shoes shoes ,you can buy them online. Very high-caliber and cheap puma shoes as same as you buy from the authorized store..My younger sister's long hair is always chaotic. so i presented a hair straighteners to her for Christmas last year .she were very pleasantly surprised

2:33 AM  
Blogger Miker said...

I like your blog . They are really great. Ermunterung ++ .
some new style Air shoes is in fashion this year.Do you know Air Shoes is a best . another kinds of nike air rift is better . the Puma basket will make you feel very relaxed when you play basketball.
If you want to buy the Cheap puma shoes shoes ,you can buy them online. Very high-caliber and cheap puma shoes as same as you buy from the authorized store..My younger sister's long hair is always chaotic. so i presented a hair straighteners to her for Christmas last year .she were very pleasantly surprised

2:38 AM  
Blogger Miker said...

this is a introduction about my brother, sister and I .
I like wear Ugg Boots ,they are ugly ,but very cool and very easy. my young brother is a fans of CONVERSE shoes .he often wears orange CONVERSE shoes .he likes orange color .My younger sister's long hair is always chaotic. so i presented a hair straighteners to her for Christmas last year .she were very pleasantly surprised .it looks very confusing , but I love them .
____

2:39 AM  
Blogger Miker said...

this is a introduction about my brother, sister and I .
I like wear Ugg Boots ,they are ugly ,but very cool and very easy. my young brother is a fans of CONVERSE shoes .he often wears orange CONVERSE shoes .he likes orange color .My younger sister's long hair is always chaotic. so i presented a hair straighteners to her for Christmas last year .she were very pleasantly surprised .it looks very confusing , but I love them .
____

2:40 AM  
Blogger Miker said...

You are currently spoilt for choice Polo Shirts On Sale with the selection of current star names to get put on the back of the polo ralph lauren, with such playres as Maldini, Toni, Di Rossi, Iaquinta, Pirlo, and Canavarro to name just a few cheappolos. And three are othre rising stars who might take your fancy burbrery polos, like Rossi, Balotelli, Pazzini and Aquilani. Ralph Lauren Polo Shirts are all going to be names that you’ll hear a lot more Burbrery Polo Shirts of in the future I’m sure.

2:45 AM  
Blogger Miker said...

You are currently spoilt for choice Polo Shirts On Sale with the selection of current star names to get put on the back of the polo ralph lauren, with such playres as Maldini, Toni, Di Rossi, Iaquinta, Pirlo, and Canavarro to name just a few cheappolos. And three are othre rising stars who might take your fancy burbrery polos, like Rossi, Balotelli, Pazzini and Aquilani. Ralph Lauren Polo Shirts are all going to be names that you’ll hear a lot more Burbrery Polo Shirts of in the future I’m sure.

2:46 AM  
Blogger Miker said...

In spite of the fact that many critics comment on ed hardy clothing as nothing but tattoo pattrens, being full of unnecessary and useless things, ed hardy clothes is widely acknowledged that ed hardy shirts draws the most attention of both common young people as well as many Hollywood welcomed stars for its punk rock styles. In fact, in today’s world, many ed hardy t-shirtsdesigns are more or less the same with each othre, and ed hardy mens and ed hardy womens , absolutely, brings a totally new shock in the fashion world for its design being out of ordinary ed hardy sunglasses.

2:51 AM  
Blogger Miker said...

In spite of the fact that many critics comment on ed hardy clothing as nothing but tattoo pattrens, being full of unnecessary and useless things, ed hardy clothes is widely acknowledged that ed hardy shirts draws the most attention of both common young people as well as many Hollywood welcomed stars for its punk rock styles. In fact, in today’s world, many ed hardy t-shirtsdesigns are more or less the same with each othre, and ed hardy mens and ed hardy womens , absolutely, brings a totally new shock in the fashion world for its design being out of ordinary ed hardy sunglasses.

2:52 AM  
Blogger lla said...

Wilson k factor KTour the flexibility of a good tennis racket is suitable for all type, doubles, singles players. Wilson k six shoot better on the first rotation speed to produce a very good help.Babolat aeropro drive Racquets is Nadal's babolat tennis racket used.In many places to be able to buy cheap tennis racquets.Babolat pure drive is a Babolat be proud of the company products, and a large number of professional tennis players to choose from, coupled with near-perfect design and adapt wider.
ralph lauren polo
burberry polo shirt

11:20 PM  
Blogger lla said...

Ed hardy clothes in Hollywood is a very popular brand hot.Classic tattoo art and fashion classic elements included in the ed hardy clothing .
Wholesale Handbags
Cheap Handbags
Womens Handbags
Cheap Purses
Designer Handbags

11:20 PM  

Post a Comment

<< Home