Ruby Closures

Thiru Njuguna
TEZZA SOFTWARE DEVELOPMENT
17 min readJul 3, 2018

Closures are, without a doubt are Ruby’s nagging.

Blocks, procs, lambdas, and methods which are available in Ruby are collectively called closures.

As useful as they can be, their slight differences at times, make you feel they are just different names for the same Ruby construct.

However, if you look closely, they have their differences, and it takes an eager eye to figure them out.

We are going to analyze Ruby closures, and you will learn:

  1. What blocks, procs, lambdas, and methods are
  2. How they differ from each other
  3. How you can use blocks, procs, lambdas, and methods in your code

Blocks

The simplest kind of closure is a block.A block is a chunk of code that can be passed to an object/method and is executed under the context of that object.If you have worked with arrays, you have probably used an array’s each method that allows you to iterate through the array’s contents.

arr = [1, 2, 3, 4, 5]

arr.each do | element |
puts element
end

And here is the output.

1
2
3
4
5

In this case, the code between do and end which is puts element is a block.Although it is a block with a single line of code, blocks can be as long as hundred lines of code depending on what you are trying to achieve using a block.Below is an example that uses an array’s each_index function.

arr = [50,4,5,7]

arr.each_index do | i |
puts ‘The element at #{i} is #{arr[i]}’ puts ‘The square of #{arr[i]} is # {arr[i]**2}’ puts ‘The cube of #{arr[i]} is #{arr[i]**3}’
end

The code above produces the output.

The element at 0 is 1
The square of 1 is 1
The cube of 1 is 1
The element at 1 is 2
The square of 2 is 4
The cube of 2 is 8
The element at 2 is 3
The square of 3 is 9
The cube of 3 is 27
The element at 3 is 4
The square of 4 is 16
The cube of 4 is 64
The element at 4 is 5
The square of 5 is 25
The cube of 5 is 125

Notice the variables element and index that are enclosed within the | operator to pass into the block in both of our examples.Depending on how the block is written, you can pass one or more variables into your blocks.

The delete_if method of the Hash class is an example. It deletes all elements from the hash for which the block evaluates to true.

hash = {a: 1, b: 2, c: 3, d: :d, e: :e, f: :f}

hash = hash.delete_if do | key, value|
key == value
end

In this case, the hash variable is reduced to {a: 1, b: 2, c: 3}.

There is some object function in Ruby that accepts blocks then executes them in the object context they are passed to.

I recommend you read the official Ruby documentation when working with any object. It is the best source to learn an object’s specifics and will also help you come across methods that accept blocks as a parameter.

So, knowing how to pass blocks to the core object methods is all good, but in a way, it limits our possibilities if we do not know how to write our methods that accept blocks.

Writing Methods That Accept Blocks

From our discussion on blocks so far, you might think that you are about to embark on the most complicated parts of this tutorial. But this isn’t the case.

Before we move to write our block-accepting methods, let us write a pure Post class that we can use throughout this article.

class Post
attr_accessor :title, :content, :author, :publish_date
def initialize(title, content, author, publish_date)
@title = title
@content = content
@author = author
@publish_date = publish_date
end
end

We have created a post-class with the attributes title, content, author, and publish_date. Using the attr_accessor method, we have made all these four attributes readable and writable. The object constructor which is the initialize method accepts all four of them as a parameter and sets merely the matching variables.

The next thing to note is the yield keyword.

As simple as it may sound, writing your block-accepting functions is just using the yield keyword.

I will showcase this by writing a block_inspec method in our post class, which accepts a block and pass in the post object’s instance variable names and values to the given block.

class Post
attr_accessor :title, :content, :author, :publish_date
def initialize(title, content, author, publish_date)
@title = title
@content = content
@author = author
@publish_date = publish_date
end

def block_inspect
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
yield(stringified_instance_variable_name, self.instance_variable_get(instance_variable))
end
end
end

To better understand our block_inspect method, let us first talk about the instance_variables and instance_variable_get methods.

Both the instance_variables and instance_variable_get methods are part of the core Object class. Since all objects inherit from Object in Ruby, they are automatically available on our post-class.

The instance_variables function returns an array of symbolized instance variable names.

In case of the post class, it would return.

[:@title, :@content, :@author, :@publish_date]

The instance_variable_get method returns the value for each of these instance variables. All you have to do is pass in the instance variable name.

So, instance_variable_get(:@title) would return the post’s title and so on.

Inside our block_inspect method, we have called self.instance_variables returns array:-

[:@title, :@content, :@author, :@publish_date]

Our code resolves to:-

[:@title, :@content, :@author, :@publish_date]

Each of them we as we saw before, this all us to work with each of the element in this array.

Because we want our post attribute names to be readable, we convert them to strings then get rid off @ symbol. This line

stringified_instance_variable_name =instance_variable.to_s.sub(‘@’, ‘’)

does that, saving the resulting string to the variable stringified_instance_variable_name.

The next part yield(stringified_instance_variable_name, self.instance_variable_get(instance_variable))is pretty simple and interesting.

By using the yield keyword, we are merely telling the compiler to take the block passed to this function and pass it the post instance variable’s name and value which are stringified_instance_variable_name, and self.instance_variable_get(instance_variable) respectively. These variables correspond to the variables passed to the block enclosed within the | operator.

Since we have used each function, It’s done for the post’s instance variables.

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)

post.block_inspect do |k, v|
puts “#{k} = #{v}”
end

The output will be.

title = Title
content = Content
author = Author
publish_date = Publish_Date

Though it looks like our block_inspect function is done, there is one more task we can add to it to make cleaner.

We outline the problem if we leave our block_inspect function as it is.

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)
post.block_inspect

If you run the above code, you’ll be greeted with the no block gave (yield) (LocalJumpError) error.

This means our block_inspect method assumes a block is passed when it is invoked.

However, imagine if you are creating a REST API. The LocalJumpError, whenever encountered, would break your whole app for no reason.

To remedy that, we need to tell our block_inspect function to invoke the block if it is given using the block_given? Function.

Below is the re-written block_inspect function.

def block_inspect
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
if block_given?
yield(stringified_instance_variable_name, self.instance_variable_get(instance_variable))
end
end
end

Or a neater way to do this would be.

def block_inspect
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
yield(stringified_instance_variable_name, self.instance_variable_get(instance_variable)) if block_given?
end
end

Now, try the block_inspect method again without passing any block. The LocalJumpError is no longer encountered, and everything functions as it should.

Apart from yield, we can use a block’s call method to write block-accepting functions, but by using it, we have to explicitly declare in our method definition that a block will be passed to it.

Let’s edit the block_inspect method once again to understand how that is done.

def block_inspect(&block)
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
block.call(stringified_instance_variable_name, self.instance_variable_get(instance_variable)) if block_given?
end
end

Starting with the method signature, we have explicitly added a block to the parameters list. The only change apart from that is invoking the block using block. Call and pass the variable instance of names and values so that they are available in the block.

Note that we have included & before block when specifying the function parameters. It means that the blocks need not be passed by value, but by reference.

Procs

The easiest way to understand procs (short for procedures) is when you save your blocks to a variable, it is called a proc.

In other words, a block is a proc, only that it has been declared inline and not saved to a variable.

Here is a proof of concept.

Let us write a very simple function that accepts a block as a parameter. We will only be echoing the class of the passed block inside the function.

def show_class(&block_object)
puts “The block class is #{block_object.class}” if block_given?
yield if block_given?
end
show_class do
puts “Hi! from inside the block.”
end

The output is:-

The block class is Proc
Hi! from inside the block

Let us add another function to post class for inspection with proc.

def proc_inspect(block)
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
block.call(stringified_instance_variable_name, self.instance_variable_get(instance_variable))
end
end

The proc_inspect function looks like the block_inspect function, the only changes done is getting rid off & before the method parameter and block_given? Conditional.

The proc_inspect function works like any other method and will be able to know the number of parameters required.

In case a proc is not passed to the method, there will be a wrong number of arguments error instead of a LocalJumpError.

Here is the proc_inspect method in action.

proc_inspect = Proc.new do |attribute, value|
puts “#{attribute} = #{value}”
end

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)

post.proc_inspect(proc_inspect)

The above code output is as same as before.

As mentioned earlier, procs are blocks that can be saved to a variable, as clearly illustrated in the first line of code.

The next two lines create a post object and pass it the proc object using the proc_inspect function.

Procs make code re-usable.Imagine if you wrote a 1000-line block that goes through an object, detailing its specifics like attribute names, values, and the memory each of them consumes.

In such a case, writing a 100-line block in-line everywhere it needs to be used sounds very untidy and impractical.

For such scenarios and similar, you can create a proc and merely call it when it’s needed.

Lambdas

Lambdas look the same as procs. Let us see their practical implementation.

Add another function lambda_inspect in the post class.

def lambda_inspect(lambda)
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
lambda.call(stringified_instance_variable_name, self.instance_variable_get(instance_variable))
end
end

It is like the proc_inspect function and calling it will not outline any differences except for a few.

lambda_inspect = lambda do |k, v|
puts “#{k} = #{v}”
end
post.lambda_inspect(lambda_inspect)

So what are the differences?

Well,

The first one is a proc doesn’t report an error if the number of parameters passed doesn’t match the number of parameters it should accept whereas a lambda matches.

See below.

proc_inspect = Proc.new do |k,v, answer_to_method|
puts “#{k} = #{v}”
puts ‘Answer to method is #{answer_to_method.class}’end

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)

post.proc_inspect(proc_inspect)

Output is:-

title = Title
Answer to method is NilClass
content = Content
Answer to method is NilClass
author = Author
Answer to method is NilClass
publish_date = Publish_Date
Answer to method is NilClass

The class of answer_to_method is printed NilClass for all the iterations. We could have printed the variable answer_to_life_and_universe using puts answer_to_life_and_universe, but since it is NIL, nothing is printed out.

Now, let us do the same thing using a lambda.

lambda_inspect = lambda do |attribute, value, answer_to_life_and_universe|
puts “#{attribute} = #{value}”
puts “Answer to life and universe is #{answer_to_life_and_universe.class}”
end

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)

post.lambda_inspect(lambda_inspect)

You will be greeted with the wrong number of arguments (given 2, expected 3) error and the compiler will be all over you like an angry girlfriend.

The second difference has to do with the return keyword.

When you use return inside a proc (which is inside a function), it behaves as though using return inside the function, halting further execution and exiting the function with the returned value.

Whereas in case of lambdas, only the value is returned and the function resumes execution as usual.

def proc_return
Proc.new do
return 'Inside proc' end.call
return 'Inside proc_return!!"'end

def lambda_return
lambda do
return 'Inside lambda_inspect!!"' end.call
return 'Inside lambda_return!!" 'end

puts proc_return
puts lambda_return

The output is:-

Inside proc 
Inside lambda_return

Methods

Functions and object methods can be called methods.

There is nothing much to discuss regarding the specifics of methods.

However, concerning closures, it is worth mentioning that (tongue twister alert!) the method makes methods usable in place of blocks, procs, and lambdas.

def print_object_property(attribute, value)
puts “#{attribute} = #{value}”
end

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)
post.block_inspect(&(method(:print_object_property)))
puts ‘ ‘post.proc_inspect(method(:print_object_property))
puts ‘ ‘post.lambda_inspect(method(:print_object_property))

The output shows our function is used in place of a block, proc, and lambda flawlessly.

title = Title
content = Content
author = Author
publish_date = Publish_Date

title = Title
content = Content
author = Author
publish_date = Publish_Date

title = Title
content = Content
author = Author
publish_date = Publish_Date

Ruby Closures

Closures are, without a doubt are Ruby’s nagging.

Blocks, procs, lambdas, and methods which are available in Ruby are collectively called closures.

As useful as they can be, their slight differences at times, make you feel they are just different names for the same Ruby construct.

However, if you look closely, they have their differences, and it takes an eager eye to figure them out.

We are going to analyze Ruby closures, and you will learn:

  1. What blocks, procs, lambdas, and methods are
  2. How they differ from each other
  3. How you can use blocks, procs, lambdas, and methods in your code

Blocks

The simplest kind of closure is a block.A block is a chunk of code that can be passed to an object/method and is executed under the context of that object.If you have worked with arrays, you have probably used an array’s each method that allows you to iterate through the array’s contents.

arr = [1, 2, 3, 4, 5]

arr.each do | element |
puts element
end

And here is the output.

1
2
3
4
5

In this case, the code between do and end which is puts element is a block.Although it is a block with a single line of code, blocks can be as long as hundred lines of code depending on what you are trying to achieve using a block.Below is an example that uses an array’s each_index function.

arr = [50,4,5,7]

arr.each_index do | i |
puts ‘The element at #{i} is #{arr[i]}’ puts ‘The square of #{arr[i]} is # {arr[i]**2}’ puts ‘The cube of #{arr[i]} is #{arr[i]**3}’
end

The code above produces the output.

The element at 0 is 1
The square of 1 is 1
The cube of 1 is 1
The element at 1 is 2
The square of 2 is 4
The cube of 2 is 8
The element at 2 is 3
The square of 3 is 9
The cube of 3 is 27
The element at 3 is 4
The square of 4 is 16
The cube of 4 is 64
The element at 4 is 5
The square of 5 is 25
The cube of 5 is 125

Notice the variables element and index that are enclosed within the | operator to pass into the block in both of our examples.Depending on how the block is written, you can pass one or more variables into your blocks.

The delete_if method of the Hash class is an example. It deletes all elements from the hash for which the block evaluates to true.

hash = {a: 1, b: 2, c: 3, d: :d, e: :e, f: :f}

hash = hash.delete_if do | key, value|
key == value
end

In this case, the hash variable is reduced to {a: 1, b: 2, c: 3}.

There is some object function in Ruby that accepts blocks then executes them in the object context they are passed to.

I recommend you read the official Ruby documentation when working with any object. It is the best source to learn an object’s specifics and will also help you come across methods that accept blocks as a parameter.

So, knowing how to pass blocks to the core object methods is all good, but in a way, it limits our possibilities if we do not know how to write our methods that accept blocks.

Writing Methods That Accept Blocks

From our discussion on blocks so far, you might think that you are about to embark on the most complicated parts of this tutorial. But this isn’t the case.

Before we move to write our block-accepting methods, let us write a pure Post class that we can use throughout this article.

class Post
attr_accessor :title, :content, :author, :publish_date
def initialize(title, content, author, publish_date)
@title = title
@content = content
@author = author
@publish_date = publish_date
end
end

We have created a post-class with the attributes title, content, author, and publish_date. Using the attr_accessor method, we have made all these four attributes readable and writable. The object constructor which is the initialize method accepts all four of them as a parameter and sets merely the matching variables.

The next thing to note is the yield keyword.

As simple as it may sound, writing your block-accepting functions is just using the yield keyword.

I will showcase this by writing a block_inspec method in our post class, which accepts a block and pass in the post object’s instance variable names and values to the given block.

class Post
attr_accessor :title, :content, :author, :publish_date
def initialize(title, content, author, publish_date)
@title = title
@content = content
@author = author
@publish_date = publish_date
end

def block_inspect
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
yield(stringified_instance_variable_name, self.instance_variable_get(instance_variable))
end
end
end

To better understand our block_inspect method, let us first talk about the instance_variables and instance_variable_get methods.

Both the instance_variables and instance_variable_get methods are part of the core Object class. Since all objects inherit from Object in Ruby, they are automatically available on our post-class.

The instance_variables function returns an array of symbolized instance variable names.

In case of the post class, it would return.

[:@title, :@content, :@author, :@publish_date]

The instance_variable_get method returns the value for each of these instance variables. All you have to do is pass in the instance variable name.

So, instance_variable_get(:@title) would return the post’s title and so on.

Inside our block_inspect method, we have called self.instance_variables returns array:-

[:@title, :@content, :@author, :@publish_date]

Our code resolves to:-

[:@title, :@content, :@author, :@publish_date]

Each of them we as we saw before, this all us to work with each of the element in this array.

Because we want our post attribute names to be readable, we convert them to strings then get rid off @ symbol. This line

stringified_instance_variable_name =instance_variable.to_s.sub(‘@’, ‘’)

does that, saving the resulting string to the variable stringified_instance_variable_name.

The next part yield(stringified_instance_variable_name, self.instance_variable_get(instance_variable))is pretty simple and interesting.

By using the yield keyword, we are merely telling the compiler to take the block passed to this function and pass it the post instance variable’s name and value which are stringified_instance_variable_name, and self.instance_variable_get(instance_variable) respectively. These variables correspond to the variables passed to the block enclosed within the | operator.

Since we have used each function, It’s done for the post’s instance variables.

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)

post.block_inspect do |k, v|
puts “#{k} = #{v}”
end

The output will be.

title = Title
content = Content
author = Author
publish_date = Publish_Date

Though it looks like our block_inspect function is done, there is one more task we can add to it to make cleaner.

We outline the problem if we leave our block_inspect function as it is.

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)
post.block_inspect

If you run the above code, you’ll be greeted with the no block gave (yield) (LocalJumpError) error.

This means our block_inspect method assumes a block is passed when it is invoked.

However, imagine if you are creating a REST API. The LocalJumpError, whenever encountered, would break your whole app for no reason.

To remedy that, we need to tell our block_inspect function to invoke the block if it is given using the block_given? Function.

Below is the re-written block_inspect function.

def block_inspect
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
if block_given?
yield(stringified_instance_variable_name, self.instance_variable_get(instance_variable))
end
end
end

Or a neater way to do this would be.

def block_inspect
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
yield(stringified_instance_variable_name, self.instance_variable_get(instance_variable)) if block_given?
end
end

Now, try the block_inspect method again without passing any block. The LocalJumpError is no longer encountered, and everything functions as it should.

Apart from yield, we can use a block’s call method to write block-accepting functions, but by using it, we have to explicitly declare in our method definition that a block will be passed to it.

Let’s edit the block_inspect method once again to understand how that is done.

def block_inspect(&block)
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
block.call(stringified_instance_variable_name, self.instance_variable_get(instance_variable)) if block_given?
end
end

Starting with the method signature, we have explicitly added a block to the parameters list. The only change apart from that is invoking the block using block. Call and pass the variable instance of names and values so that they are available in the block.

Note that we have included & before block when specifying the function parameters. It means that the blocks need not be passed by value, but by reference.

Procs

The easiest way to understand procs (short for procedures) is when you save your blocks to a variable, it is called a proc.

In other words, a block is a proc, only that it has been declared inline and not saved to a variable.

Here is a proof of concept.

Let us write a very simple function that accepts a block as a parameter. We will only be echoing the class of the passed block inside the function.

def show_class(&block_object)
puts “The block class is #{block_object.class}” if block_given?
yield if block_given?
end
show_class do
puts “Hi! from inside the block.”
end

The output is:-

The block class is Proc
Hi! from inside the block

Let us add another function to post class for inspection with proc.

def proc_inspect(block)
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
block.call(stringified_instance_variable_name, self.instance_variable_get(instance_variable))
end
end

The proc_inspect function looks like the block_inspect function, the only changes done is getting rid off & before the method parameter and block_given? Conditional.

The proc_inspect function works like any other method and will be able to know the number of parameters required.

In case a proc is not passed to the method, there will be a wrong number of arguments error instead of a LocalJumpError.

Here is the proc_inspect method in action.

proc_inspect = Proc.new do |attribute, value|
puts “#{attribute} = #{value}”
end

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)

post.proc_inspect(proc_inspect)

The above code output is as same as before.

As mentioned earlier, procs are blocks that can be saved to a variable, as clearly illustrated in the first line of code.

The next two lines create a post object and pass it the proc object using the proc_inspect function.

Procs make code re-usable.Imagine if you wrote a 1000-line block that goes through an object, detailing its specifics like attribute names, values, and the memory each of them consumes.

In such a case, writing a 100-line block in-line everywhere it needs to be used sounds very untidy and impractical.

For such scenarios and similar, you can create a proc and merely call it when it’s needed.

Lambdas

Lambdas look the same as procs. Let us see their practical implementation.

Add another function lambda_inspect in the post class.

def lambda_inspect(lambda)
self.instance_variables.each do |instance_variable|
stringified_instance_variable_name = instance_variable.to_s.sub(‘@’, ‘’)
lambda.call(stringified_instance_variable_name, self.instance_variable_get(instance_variable))
end
end

It is like the proc_inspect function and calling it will not outline any differences except for a few.

lambda_inspect = lambda do |k, v|
puts “#{k} = #{v}”
end
post.lambda_inspect(lambda_inspect)

So what are the differences?

Well,

The first one is a proc doesn’t report an error if the number of parameters passed doesn’t match the number of parameters it should accept whereas a lambda matches.

See below.

proc_inspect = Proc.new do |k,v, answer_to_method|
puts “#{k} = #{v}”
puts ‘Answer to method is #{answer_to_method.class}’end

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)

post.proc_inspect(proc_inspect)

Output is:-

title = Title
Answer to method is NilClass
content = Content
Answer to method is NilClass
author = Author
Answer to method is NilClass
publish_date = Publish_Date
Answer to method is NilClass

The class of answer_to_method is printed NilClass for all the iterations. We could have printed the variable answer_to_life_and_universe using puts answer_to_life_and_universe, but since it is NIL, nothing is printed out.

Now, let us do the same thing using a lambda.

lambda_inspect = lambda do |attribute, value, answer_to_life_and_universe|
puts “#{attribute} = #{value}”
puts “Answer to life and universe is #{answer_to_life_and_universe.class}”
end

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)

post.lambda_inspect(lambda_inspect)

You will be greeted with the wrong number of arguments (given 2, expected 3) error and the compiler will be all over you like an angry girlfriend.

The second difference has to do with the return keyword.

When you use return inside a proc (which is inside a function), it behaves as though using return inside the function, halting further execution and exiting the function with the returned value.

Whereas in case of lambdas, only the value is returned and the function resumes execution as usual.

def proc_return
Proc.new do
return 'Inside proc' end.call
return 'Inside proc_return!!"'end

def lambda_return
lambda do
return 'Inside lambda_inspect!!"' end.call
return 'Inside lambda_return!!" 'end

puts proc_return
puts lambda_return

The output is:-

Inside proc 
Inside lambda_return

Methods

Functions and object methods can be called methods.

There is nothing much to discuss regarding the specifics of methods.

However, concerning closures, it is worth mentioning that (tongue twister alert!) the method makes methods usable in place of blocks, procs, and lambdas.

def print_object_property(attribute, value)
puts “#{attribute} = #{value}”
end

post = Post.new(“Title”, “Content”, “Author”, “Publish_Date”)
post.block_inspect(&(method(:print_object_property)))
puts ‘ ‘post.proc_inspect(method(:print_object_property))
puts ‘ ‘post.lambda_inspect(method(:print_object_property))

The output shows our function is used in place of a block, proc, and lambda flawlessly.

title = Title
content = Content
author = Author
publish_date = Publish_Date

title = Title
content = Content
author = Author
publish_date = Publish_Date

title = Title
content = Content
author = Author
publish_date = Publish_Date

--

--