Tuesday, January 19, 2010

Section 8.5. Hooks








8.5. Hooks


Module, Class, and
Objectimplement several callback methods, or hooks. These methods are
not defined by default, but if you define them for a module, class, or
object, then they will be invoked when certain events occur. This gives
you an opportunity to extend Ruby's behavior when classes are subclassed,
when modules are included, or when methods are defined. Hook methods
(except for some deprecated ones not described here) have names that end in
"ed."


When a new class is defined, Ruby invokes the class method inherited on the superclass of the new
class, passing the new class object as the argument. This allows classes
to add behavior to or enforce constraints on their descendants. Recall
that class methods are inherited, so that the an
inherited method will be invoked if it is defined by
any of the ancestors of the new class. Define
Object.inherited to receive notification of all new
classes that are defined:


def Object.inherited(c)
puts "class #{c} < #{self}"
end



When a module is included into a class or into another module, the
included class method of the included module is invoked
with the class or module object into which it was included as an argument.
This gives the included module an opportunity to augment or alter the
class in whatever way it wants—it effectively allows a module to define
its own meaning for include. In addition to adding
methods to the class into which it is included, a module with an
included method might also alter the existing methods
of that class, for example:


module Final             # A class that includes Final can't be subclassed
def self.included(c) # When included in class c
c.instance_eval do # Define a class method of c
def inherited(sub) # To detect subclasses
raise Exception, # And abort with an exception
"Attempt to create subclass #{sub} of Final class #{self}"
end
end
end
end



Similarly, if a module defines a class method named
extended, that method will be invoked any time the
module is used to extend an object (with
Object.extend). The argument to the
extended method will be the object that was extended,
of course, and the extended method can take whatever
actions it wants on that object.


In addition to hooks for tracking classes and the modules they
include, there are also hooks for tracking the methods of classes and
modules and the singleton methods of arbitrary objects. Define a class
method named method_added for any class or module and
it will be invoked when an instance method is defined for that class or
module:


def String.method_added(name) 
puts "New instance method #{name} added to String"
end



Note that the method_added class method is
inherited by subclasses of the class on which it is defined. But no class
argument is passed to the hook, so there is no way to tell whether the
named method was added to the class that defines
method_added or whether it was added to a subclass of
that class. A workaround for this problem is to define an
inherited hook on any class that defines a
method_added hook. The inherited
method can then define a method_added method for each
subclass.


When a singleton method is defined for any object, the method
singleton_method_added is invoked
on that object, passing the name of the new method. Remember that for classes, singleton methods
are class methods:


def String.singleton_method_added(name)
puts "New class method #{name} added to String"
end



Interestingly, Ruby invokes this
singleton_method_added hook when the hook method itself
is first defined. Here is another use of the hook. In this case, singleton_method_added is defined as an
instance method of any class that includes a module. It is notified of any
singleton methods added to instances of that class:


# Including this module in a class prevents instances of that class
# from having singleton methods added to them. Any singleton methods added
# are immediately removed again.
module Strict
def singleton_method_added(name)
STDERR.puts "Warning: singleton #{name} added to a Strict object"
eigenclass = class << self; self; end
eigenclass.class_eval { remove_method name }
end
end



In addition to method_added and
singleton_method_added, there are hooks for tracking
when instance methods and singleton methods are removed or undefined. When
an instance method is removed or undefined on a class or module, the class
methods method_removed and
method_undefined are invoked on that module. When a
singleton method is removed or undefined on an object, the methods
singleton_method_removed and
singleton_method_undefined are invoked on that
object.


Finally, note that the method_missing and
const_missing methods documented elsewhere in this chapter also behave like
hook methods.









The Player Sprite









The Player Sprite


PlayerSprite represents the player and is a subclass of TiledSprite. The statechart for PlayerSprite in Figure 13-14 shows that the sprite performs three concurrent activities.


The move( ) and tryPickup( ) transitions are triggered by the user from the keyboard. The hitByAlien( ) transition is initiated by the WorldDisplay object when an alien tells it that it has hit the player.


The transitions in Figure 13-14 are labeled with method names; this is a practice that I'll use when there's a direct mapping from a transition to a method call. This makes it easier to see the mapping from the statechart to the corresponding code.




Figure 13-14. PlayerSprite statechart




Moving (and Standing Still)


A PlayerSprite TRies to move when the user presses one of the quadrant keys (9, 3, 1, or 7):



public void move(int quad)
{
Point newPt = tryMove(quad);
if (newPt == null) { // move not possible
clipsLoader.play("slap", false);
standStill( );
}
else { // move is possible
setTileLoc(newPt); // update the sprite's tile location
if (quad == NE)
setImage("ne");
else if (quad == SE)
setImage("se");
else if (quad == SW)

setImage("sw");
else // quad == NW
setImage("nw");
world.playerHasMoved(newPt, quad);
}
} // end of move( )



The attempt is handled by TiledSprite's inherited tryMove( ) method, and the sprite's tile location is updated if it's successful. The move is dressed up with an image change for the sprite and the playing of a sound effect if the move is blocked.


The player can press 5 to make the sprite stand still, which only changes its associated image. Normally, the sprite is poised in a running position, pointing in one of the quadrant directions.



public void standStill( )
{ setImage("still"); }





Drawing the Player


The statechart includes a draw state, triggered by a draw( ) transition. The draw activity is implemented by using the setPosition( ) and draw( ) methods inherited from Sprite. The drawing isn't initiated by code in PlayerSprite but is by WorldDisplay's draw( ) method:



public void draw(Graphics g)
// in WorldDisplay
{ g.drawImage(floorIm, xOffset, yOffset, null); // draw floor image
wItems.positionSprites(player, aliens); // add sprites
wItems.draw(g, xOffset, yOffset); // draw things
wItems.removeSprites( ); // remove sprites
}



As explained earlier, all the sprites, including the player, are added to WorldItems temporarily so they can be drawn in the correct z-order. Each sprite is stored as a TileOccupier object, and setPosition( ) and draw( ) are called from there.




Being Hit by an Alien


PlayerSprite maintains a hit counter, which is incremented by a call to hitByAlien( ) from the WorldDisplay object:



public void hitByAlien( )
{ clipsLoader.play("hit", false);
hitCount++;
if (hitCount == MAX_HITS) // player is dead
atPanel.gameOver( );
}



When hitCount reaches a certain value (MAX_HITS), it's all over. The sprite doesn't terminate though; it only notifies AlienTilePanel. This allows AlienTilesPanel to carry out "end of game" tasks, which in this case are reporting the game score and playing a sound clip of applause. AlienTilesPanel could do a lot more, such as ask users if they wanted to play another game. These kinds of game-wide activities should be done at the game panel level and not by a sprite.




Trying to Pick Up a Pickup


The user tries to pick up an item by pressing 2 on the numbers keypad. The hard work here is determining if the sprite's current tile location contains a pickup and to remove that item from the scene. The two operations are handled by WorldDisplay methods:



public boolean tryPickup( )
{
String pickupName;
if ((pickupName = world.overPickup( getTileLoc( ))) == null) {
clipsLoader.play("noPickup", false); // nothing to pickup
return false;
}
else { // found a pickup
clipsLoader.play("gotPickup", false);
world.removePickup(pickupName); // tell WorldDisplay
return true;
}
}



The name of the pickup on the current tile is obtained and used in the deletion request. If the tile is empty, a sound clip will be played instead.










    Recipe 17.7. Getting and Setting a Transparent Color










    Recipe 17.7. Getting and Setting a Transparent Color



    17.7.2. Problem


    You want
    to set one color in an image as transparent. When the image is overlayed on a background, the background shows through the transparent section of the image.




    17.7.3. Solution


    Use
    ImageColorTransparent( ):


    $color = ImageColorAllocate($image, $red, $green, $blue);
    ImageColorTransparent($image, $color);





    17.7.4. Discussion


    Both GIFs and PNGs support transparencies; JPEGs, however, do not. To refer to the transparent color within GD, use the constant IMG_COLOR_TRANSPARENT. For example, here's how to make a dashed line that alternates between black and transparent:


    // make a two-pixel thick black and white dashed line
    $style = array($black, $black, IMG_COLOR_TRANSPARENT, IMG_COLOR_TRANSPARENT);
    ImageSetStyle($image, $style);



    To find the current transparency setting, take the return value of ImageColorTransparent( ) and pass it to ImageColorsForIndex( ):


    $transparent = ImageColorsForIndex($image, ImageColorTransparent($image));
    print_r($transparent);

    $transparent = ImageColorsForIndex($image, ImageColorTransparent($image));
    print_r($transparent);
    Array
    (
    [red] => 255
    [green] => 255
    [blue] => 255
    )



    The ImageColorsForIndex( ) function returns an array with the red, green, and blue values. In this case, the transparent color is white.




    17.7.5. See Also


    Documentation on ImageColorTransparent( ) at http://www.php.net/imagecolortransparent and on ImageColorsForIndex( ) at http://www.php.net/imagecolorsforindex.













    Setting Up Samba as a Client





    Setting Up
    Samba as a Client



    Samba can be compiled from the source
    distribution or installed as a Debian or RPM package. In either case, there are
    several different components that will be installed.
    The server
    components are:



    lang=EN-GB style='font-size:10.0pt;font-family:Symbol'>�        
    smbd: a daemon that shares out files and
    printers from the Linux system



    lang=EN-GB style='font-size:10.0pt;font-family:Symbol'>�        
    nmbd: a daemon that provides NetBIOS name
    resolution



    style='font-size:10.0pt;font-family:Symbol'>�        
    sambaconfig: a reconfiguration tool



    lang=EN-GB style='font-size:10.0pt;font-family:Symbol'>�        
    smbpasswd: an SMB password maintenance tool



    The client components are:



    lang=EN-GB style='font-size:10.0pt;font-family:Symbol'>�        
    smbclient: an FTP-like program for accessing
    shares



    lang=EN-GB style='font-size:10.0pt;font-family:Symbol'>�        
    smbspool: a tool to send print jobs to shared
    printers



    lang=EN-GB style='font-size:10.0pt;font-family:Symbol'>�        
    smbmount, smbumount: tools to, respectively,
    mount and unmount SMB shares.



    All of the Samba components use a single
    configuration file, usually located at /etc/samba/smb.conf.
    The majority of configuration options in this file affect the behavior of the
    Samba server, but a few options need to be set correctly in order to use the
    client applications.



    Like many other Linux configuration files,
    the Samba configuration file is a simple text document. Blank lines and white
    space are not significant (except in parameter values), and comments begin with
    a semicolon and extend to the end of the line. The whole file is case
    insensitive, so WORKGROUP is the same as class=docemphasis1>workgroup
    is the same as WoRkGrOuP.
    Booleans can be yes/no, 0/1, or true/false. There are three special sections:
    [global], [homes], and [printers]. The man page covers this and more in pretty
    good detail.



    The default configuration file is heavily
    commented, describing the purpose of each line. The only significant thing
    you'll have to do for using client applications is to change the default
    workgroup:



    ; "security = user" is always a good idea. This will require a
    lang=EN-GB>; Unix account in this server for every user accessing the server.
    lang=EN-GB>security = domain
    ; Change this for the workgroup your Samba server will part of
    lang=EN-GB>workgroup = WORKGROUP
    server string = %h server (Samba %v)


    Modify the line starting with workgroup = to
    specify the name of your Windows workgroup or Windows NT domain. Actually, this
    step is not strictly necessary, since the Samba client tools will also accept
    the -W command line option to specify a nondefault workgroup. But it's easier
    to use a tool if you don't have to remember (and type!) a long list of arcane
    options and flags.



     





    A Robust Fluid Layout








    A Robust Fluid Layout


    Converting the fixed-width layout to a fluid center column layout involves a number of changes to the markup. Here are the three main changes.


    1. Most notably, you must remove all the width:774px declarations off the containers, since they now have to change size as the browser width changes. Without an explicit declaration, the containers default to width:auto, which is just what you want.

    2. You also need to change from the floating method of arranging the columns to the relative/absolute technique. Absolutely positioned elements (the side columns, in this case) use the positioning context of their closest absolutely positioned ancestor (the column container). By using the top and left settings for the left column and the top and right settings for the right column, you can move the columns up into the top corners of their respective containers.

      One big advantage of this method of positioning the side columns is that you can now reorganize the markup so that the center column with the page content comes first; the side columns are absolutely positioned, so it doesn't matter where they appear in the markup. There are two benefits to doing this. First, users with disabilities, who might be using a screen reader or non-mouse navigation device to step through the markup, will encounter the content immediately. Second, search engines tend to rank content that is placed near the top of the markup highest, so this arrangement can help your content rank higher in search engines.

    3. The new fluid layout has some constraints on just how fluid it can be. Fluid sizing is definitely user friendly, because the layout can be adjusted to match the available screen real estate. The problems with fluid layouts, however, are that, by narrowing the browser window, the user can either crush the content until the side columns overlap and the content disappears or stretch the browser so wide that text lines become very long. Both of these options make it hard for the user's eye to move from the end of one line to the start of the next. By constraining the maximum and minimum widths to which the layout can size, you give the user the benefits of a fluid layout, while avoiding these two problems.


    CSS2 introduced the max-size and min-size properties, which enable you to set how wide or narrow an element can size. By using these properties on your mainwrap that encloses the whole layout, you can control the range of your fluid layout. As a final touch, in the following markup, I also used auto margins so that if the user sets the browser wider than the maximum width allowed for the layout, the layout centers itself in the browser window.


    Let's look at the new markup


    [View full width]

    <body>
    <div id="mainwrap">
    <div id="header"><p>A fluid-width faux-columns example</p></div>
    <div id="contentarea" class="clearfix">
    <div id="contentarea2" class="clearfix">

    <div id="column2">
    <p>This layout uses absolute/relative positioning to position the side columns within
    their respective faux columns containers.</p>
    <p>You can control the maximum and minimum widths of the fluid center area.
    Once the layout reaches its maximum width, it centers itself in the browser as the window
    gets wider.</p>
    <p>Nulla scelerisque. Sed tincidunt. Quisque eu nisl. Phasellus
    mi ante, aliquet vel, vestibulum sit amet, consectetuer non, ante. Suspendisse
    consequat condimentum enim. Morbi vestibulum lorem sit amet enim. Nulla venenatis
    fermentum purus.</p>
    <p>Nunc justo nisl, vulputate in, sagittis in, pretium sodales,
    magna. Nullam felis diam, bibendum ut, dictum in, tincidunt vitae, magna.
    Nunc mattis congue leo.</p>
    </div><!--end column2-->
    <div id="column1">
    <ul>
    <li><a href="#">Link 1</a></li>
    <li><a href="#">Link 2</a></li>
    <li><a href="#">Link 3</a></li>
    </ul>
    </div><!--end column1-->
    <div id="column3">
    <p>This template uses the Alsett clearing method.</p>
    </div><!--end column3-->
    </div><!--end contentarea2-->
    </div><!--end contentarea-->
    <div id="footer">This is the footer</div>
    </div><!--end mainwrap-->
    </body>


    Note that column2, the center content area, appears before the two side columns, column1 and column3, in this markup.


    Here is the CSS:




    <style type="text/css">
    body {font: 1.0em verdana, arial, sans-serif;
    text-align:center; <-- a
    }
    * {margin:0; padding:0;}
    div#mainwrap {min-width:780px; max-width:960px; <-- b
    margin-left:auto; margin-right:auto; <-- c
    text-align:left; <-- d
    }
    div#header {height:32px; background-color:#CAF; text-align:center;} <-- e
    div#contentarea { background-color:#FFF; <-- f
    background:url(images_pres/faux_left.gif) repeat-y top left; <-- g
    position:relative; <-- h
    }
    div#contentarea2 {background-color:#FFF;
    background:url(images_pres/faux_right.gif) repeat-y top right; <-- i
    position:relative; <-- j
    }
    div#column1 {width:150px;
    position: absolute; <-- k
    top:0px; left:0px; <-- l
    background-color:#CCC; <-- m
    overflow:hidden; <-- n
    }

    div#column2 {background-color:#FFF;
    margin:0 170px 0 150px; <-- o
    }
    div#column3 {width:170px;
    position:absolute; <-- p
    top:0px; right:0px; <-- q
    background-color:#DDD; <-- r
    overflow:hidden; <-- s
    }
    div#footer {background-color:#FAC; text-align:center; padding-top:6px;} <-- t

    div#column1 ul {margin: 20px 0 0 26px;} <-- 20
    div#column2 p {font-size:.8em; margin:0 30px 1em ;} <-- 20
    div#column3 p {margin: 20px 10px 0 10px;} <-- 20
    /* Alsett Clearing Method code removed here to save space */ <-- u


    (a)Centers the layout in IE 5

    (b)Sets the max and min widths

    (c)Centers the layout in SCBs

    (d)Stops elements from inheriting the body's text-center

    (e)Temporary placeholder styles for header

    (f)Ensures bg is white if faux graphic doesn't load

    (g)Faux-column graphic left column

    (h)Set positioning context for left sidebar div

    (i)Faux-column graphic right column

    (j)Set positioning context for right sidebar div

    (k)Contextual positioning in contentarea container

    (l)Positions col within contentarea container

    (m)Left column bg color

    (n)Prevents overlarge elements breaking out of column

    (o)Margins to make room for sidebars

    (p)Contextual positioning in contentarea container

    (q)Positions col within contentarea container

    (r)Left column bg color

    (s)Prevents overlarge elements breaking out of column

    (t)Temp footer styles

    (20)Some basic styles for placeholder content

    (20)

    (20)

    (u)See Chapter 5 for this code or go to www.bbd.com/stylin.


    The layout in Figure 6.10 sizes to the browser width but cannot become too wide or narrow. It works in all modern, standardscompliant browsers, and it doesn't have the issues associated with floats wrapping the right column under the left if columns become too wide (from an overly large image, for example).


    Figure 6.10. This layout is fluid but has maximum and minimum constraints to prevent the layout from getting too wide or too narrow.

    [View full size image]



    Note also that it is the use of positioning context (see Chapter 4) that makes this layout work. The side columns are absolutely positioned, which means that by default, their positioning context is body. In order to have the layout center in the screen after it reaches maximum width, the columns can't be positioned relative to body (which is always the width of the browser window), because if this was the case, the sidebars would stay at the edge of the browser, even as the rest of the layout moved away from the browser edges. By setting the column containers' position property to relative, they provide the positioning context for the sidebar divs; the side columns then move with the rest of the layout.


    The side columns each have an overflow:hidden declaration to visually trim graphics or other elements that are wider than the column rather than have them spill out over other areas.



    To see this for yourself, temporarily remove position:relative from each of the container divs. Then save and reload and open up the browser wider than the maximum width value so that the layout starts to move away from the browser's sides. If you do so, you will see that those side columns remain at the edge of the browser window because their positioning context has reverted to the default, body.


    I will show you how to work extensively with this template in the next chapter.








      SUMMARY



      [ Team LiB ]





      SUMMARY


      DB2 v8 is one of the most complete DB2 releases to date. In fact, it has so many new features and enhancements that this chapter is just an introduction to some of them. Through Autonomic Computing and the SMART initiative, IBM has made DB2 v8 very easy to operate and manage. Some configuration parameters can now be automatically configured by DB2. These changes, along with the new wizards and tools, will help make DBAs more productive. With the new Development Center, application development has been tightly integrated into DB2 with support for a myriad of development tools. The availability enhancements�which include infinite logging, online index and table reorganization, online configuration parameters, and online table load�precisely positions DB2 to be able to handle the tough demands of today's businesses, and to grow with them into the future. And lastly, v8's full 64-bit capability will enable DB2 to not only handle today's demands, but handle them well into the future. You'll find lots of information on enhancements and new features in v8 throughout the book.





        [ Team LiB ]



        1.1 What Is SQL?











         < Day Day Up > 







        1.1 What Is SQL?





        SQL is a special-purpose language used to define, access, and

        manipulate data. SQL is nonprocedural,

        meaning that it describes the necessary components (i.e., tables) and

        desired results without dictating exactly how those results should be

        computed. Every SQL implementation sits atop a database

        engine
        ,

        whose job it is to interpret SQL statements and determine how the

        various data structures in the database should be accessed to

        accurately and efficiently produce the desired outcome.





        The SQL language includes two distinct sets of commands:

        Data Definition Language (DDL)

        is the subset of SQL used to define

        and modify various data structures, while Data Manipulation

        Language
        (DML) is the subset

        of SQL used to access and manipulate data contained within the data

        structures previously defined via DDL. DDL includes numerous commands

        for handling such tasks as creating tables, indexes, views, and

        constraints, while DML is

        comprised

        of just five statements:






        INSERT





        Adds data to a

        database.






        UPDATE





        Modifies data in a

        database.






        DELETE





        Removes data from a

        database.






        MERGE





        Adds and/or modifies data in a database. MERGE is part of the 2003

        ANSI SQL standard.






        SELECT





        Retrieves data from a

        database.









        Some people feel that DDL is the sole property of database

        administrators, while database developers are responsible for writing

        DML statements, but the two are not so easily separated. It is

        difficult to efficiently access and manipulate data without an

        understanding of what data structures are available and how they are

        related; likewise, it is difficult to design appropriate data

        structures without knowledge of how the data will be accessed. That

        being said, this book deals almost exclusively with DML, except where

        DDL is presented to set the stage for one or more DML examples. The

        reasons for focusing on just the DML portion of SQL include:





        • DDL is well represented in various books on database design and

          administration as well as in SQL reference guides.

        • Most database performance issues are the result of inefficient DML

          statements.

        • Even with a paltry five statements, DML is a rich enough topic to

          warrant not just one book, but a whole series of books.





        Anyone who writes SQL in an Oracle environment should be armed with

        the following three books: a reference guide to the SQL language,

        such as Oracle in a Nutshell

        (O'Reilly); a performance-tuning guide, such as

        Optimizing Oracle Performance

        (O'Reilly); and the book you are holding, which

        shows how to best utilize and combine the various features of

        Oracle's SQL implementation.








        So why should you care about SQL? In this age of Internet computing

        and n-tier architectures, does anyone even care about data access

        anymore? Actually, efficient storage and retrieval of information is

        more important than ever:





        • Many companies now offer services via the Internet. During peak

          hours, these services may need to handle thousands of concurrent

          requests, and unacceptable response times equate to lost revenue. For

          such systems, every SQL statement must be carefully crafted to ensure

          acceptable performance as data volumes increase.

        • We can store a lot more data today than we could just a few years

          ago. A single disk array can hold tens of terabytes of data, and the

          ability to store hundreds of terabytes is just around the corner.

          Software used to load or analyze data in these environments must

          harness the full power of SQL to process ever-increasing data volumes

          within constant (or shrinking) time windows.



        Hopefully, you now have an appreciation for what SQL is and why it is

        important. The next section will explore the origins of the SQL

        language and the support for the SQL standard in

        Oracle's products.

















           < Day Day Up >