Organizing Structures

Ruby has two basic concepts for organizing methods: classes and modules. We cover each in turn.

Classes

Here’s a Ruby class definition:

1: class​ Order < ApplicationRecord
has_many ​:line_items
def​ self.​find_all_unpaid
self.​where​(​'paid = 0'​)
5: end
def​ ​total
sum = 0
line_items.​each​ {|li| sum += li.​total​}
sum
10: end
end

Class definitions start with the class keyword, followed by the class name (which must start with an uppercase letter). This Order class is defined to be a subclass of the ApplicationRecord class.

Rails makes heavy use of class-level declarations. Here, has_many is a method that’s defined by Active Record. It’s called as the Order class is being defined. Normally these kinds of methods make assertions about the class, so in this book we call them declarations.

Within a class body, you can define class methods and instance methods. Prefixing a method name with self. (as we do on line 3) makes it a class method; it can be called on the class generally. In this case, we can make the following call anywhere in our application:

 to_collect = Order.​find_all_unpaid

Objects of a class hold their state in instance variables. These variables, whose names all start with @, are available to all the instance methods of a class. Each object gets its own set of instance variables.

Instance variables aren’t directly accessible outside the class. To make them available, write methods that return their values:

 class​ Greeter
 def​ ​initialize​(name)
  @name = name
 end
 
 def​ ​name
  @name
 end
 
 def​ ​name​=(new_name)
  @name = new_name
 end
 end
 
 g = Greeter.​new​(​"Barney"​)
 g.​name​ ​# => Barney
 g.​name​ = ​"Betty"
 g.​name​ ​# => Betty

Ruby provides convenience methods that write these accessor methods for you (which is great news for folks tired of writing all those getters and setters):

 class​ Greeter
  attr_accessor ​:name​ ​# create reader and writer methods
  attr_reader ​:greeting​ ​# create reader only
  attr_writer ​:age​ ​# create writer only
 end

A class’s instance methods are public by default; anyone can call them. You’ll probably want to override this for methods that are intended to be used only by other instance methods:

 class​ MyClass
 def​ ​m1​ ​# this method is public
 end
 protected
 def​ ​m2​ ​# this method is protected
 end
 private
 def​ ​m3​ ​# this method is private
 end
 end

The private directive is the strictest; private methods can be called only from within the same instance. Protected methods can be called both in the same instance and by other instances of the same class and its subclasses.

Classes aren’t the only organizing structure in Ruby. The other organizing structure is a module.

Modules

Modules are similar to classes in that they hold a collection of methods, constants, and other module and class definitions. Unlike with classes, you can’t create objects based on modules.

Modules serve two purposes. First, they act as a namespace, letting you define methods whose names won’t clash with those defined elsewhere. Second, they allow you to share functionality among classes. If a class mixes in a module, that module’s methods become available as if they had been defined in the class. Multiple classes can mix in the same module, sharing the module’s functionality without using inheritance. You can also mix multiple modules into a single class.

Helper methods are an example of where Rails uses modules. Rails automatically mixes these helper modules into the appropriate view templates. For example, if you wanted to write a helper method that’s callable from views invoked by the store controller, you could define the following module in the store_helper.rb file in the app/helpers directory:

 module​ ​StoreHelper
 def​ ​capitalize_words​(string)
  string.​split​(​' '​).​map​ {|word| word.​capitalize​}.​join​(​' '​)
 end
 end

One module that’s part of the standard library of Ruby deserves special mention, given its usage in Rails: YAML.

YAML

YAML[31] is a recursive acronym that stands for YAML Ain’t Markup Language. In the context of Rails, YAML is used as a convenient way to define the configuration of things such as databases, test data, and translations. Here’s an example:

 development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000

In YAML, indentation is important, so this defines development as having a set of four key-value pairs, separated by colons. While YAML is one way to represent data, particularly when interacting with humans, Ruby provides a more general way for representing data for use by applications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.178.133