A Small Refactoring – –



A Small Refactoring – –

0 0


presentation-refactoring

A presentation to share with the team about a refactoring on our current project.

On Github Heath101 / presentation-refactoring

A Small Refactoring

Naming your data

LessonsController

# app/controllers/lessons_controller.rb

class LessonsController < ApplicationController
  LESSONS_CONTENT ||= YAML.load_file('config/lesson_content.yml')

  def index
    redirect_to welcome_path unless current_user.welcomed?
    @lessons_content = LESSONS_CONTENT
  end

  def show
    raise_not_found unless valid_lesson_slug?
    @lesson_content = LESSONS_CONTENT[params[:lesson_slug]]
    current_user.watch_lesson @lesson_content[:lesson_number]
    render params[:lesson_slug].underscore
  end

private
  def valid_lesson_slug?
    Settings.lessons.slugs.include? params[:lesson_slug]
  end
end

LessonsController

# app/controllers/lessons_controller.rb

class LessonsController < ApplicationController
  LESSONS_CONTENT ||= YAML.load_file('config/lesson_content.yml')

  def index
    # redirect_to welcome_path unless current_user.welcomed?
    @lessons_content = LESSONS_CONTENT
  end

  def show
    # raise_not_found unless valid_lesson_slug?
    @lesson_content = LESSONS_CONTENT[params[:lesson_slug]]
    # current_user.watch_lesson @lesson_content[:lesson_number]
    # render params[:lesson_slug].underscore
  end

# private
  # def valid_lesson_slug?
  #  Settings.lessons.slugs.include? params[:lesson_slug]
  # end
end

config/lesson_content.yml

  ---
  digging-out-the-roots:
    :lesson_number: 1
    :title:  "Digging out the Roots"
    :slug: "digging-out-the-roots"
    :summary: "You have a passion for helping others, but you're ..."
    :description: "In this lesson you learned about the power ..."
    :image: 'lesson-1.png'
    :activity: 'foc_activity_1.pdf'

  solving-perspective-problems:
    :lesson_number: 2
    :title: "Solving Perspective Problems"
    :slug: "solving-perspective-problems"
    :summary: "The first step toward creating an effective budget ..."
    :description: "In this lesson, Dave unpacked four key areas ..."
    :image: 'lesson-2.png'
    :activity: 'foc_activity_2.pdf'
            

Lesson Video Page

<div class="LessonVideo">
  <div class="LessonVideo-player">
    <%= image_tag content[:video_image] %>
  </div>
  <div class="LessonVideo-detail">
    <h3>After the video</h3>
    <p><%= content[:description] %></p>
    <%= link_to download_url_for(content[:activity]), class: "Button Button--primary" do %>
      Download Activity <i class="fa fa-file-pdf-o"></i>
    <% end %>
  </div>
</div>

app/views/lessons/index.erb

<h1>Lessons</h1>

<% @lessons_content.each do |lesson_slug, lesson_content| %>
  <%= render 'lesson_summary',  slug: lesson_slug,
                             content: lesson_content %>
<% end %>

app/views/lessons/_lesson_summary.erb

<div class="LessonSummary">
  <div class="LessonSummary-image">
    <%= link_to image_tag(content[:image]), lesson_path(slug) %>
  </div>
  <div class="LessonSummary-detail">
    <h3><%= content[:title]   %></h3>
    <p><%=  content[:summary] %></p>
    <%= lesson_link_for(content, current_user) %>
  </div>
</div>
            

app/views/lessons/_lesson_summary.erb

<div class="LessonSummary">
  <div class="LessonSummary-image">
    <%= link_to image_tag(content.image), lesson_path(slug) %>
  </div>
  <div class="LessonSummary-detail">
    <h3><%= content.title  %></h3>
    <p><%=  content.summary %></p>
    <%= lesson_link_for(content, current_user) %>
  </div>
</div>
            

"Most intermediate programmers are too reluctant to extract classes." - Bob Martin

Lesson

class Lesson
  attr_reader :lesson_number
  attr_reader :title
  attr_reader :slug
  attr_reader :summary
  attr_reader :description
  attr_reader :image
  attr_reader :activity

  def initialize(attributes)
    attributes.each do |key, val|
      instance_variable_set("@#{key}", val) if respond_to? key
    end
  end
end

LessonsController

# app/controllers/lessons_controller.rb

class LessonsController < ApplicationController
  LESSONS_CONTENT ||= YAML.load_file('config/lesson_content.yml')

  # . . .

end

LessonsController

# app/controllers/lessons_controller.rb

class LessonsController < ApplicationController
  LESSONS_CONTENT ||= begin
    raw_content = YAML.load_file('config/lesson_content.yml')
    raw_content.each_with_object({}) do |(slug, content), lessons|
      lessons[slug] = Lesson.new(content)
    end
  end

  # . . .

end

Refactoring Questions

What is this class's responsibility? Who should know about this data?

Extrinsic

LessonsController

# app/controllers/lessons_controller.rb

  class LessonsController < ApplicationController
    LESSONS_CONTENT ||= begin
      raw_content = YAML.load_file('config/lesson_content.yml')
      raw_content.each_with_object({}) do |(slug, content), lessons|
        lessons[slug] = Lesson.new(content)
      end
    end

    # . . .

  end

LessonsController

# app/controllers/lessons_controller.rb

  class LessonsController < ApplicationController
    LESSONS ||= Content.load_lessons

    # . . .
  end

Content

module Content

  def self.load_lessons
    raw_content = YAML.load_file('config/lesson_content.yml')
    raw_content.each_with_object({}) do |(slug, content), lessons|
      lessons[slug] = Lesson.new(content)
    end
  end
end
module Content
  class Lesson
    attr_reader :lesson_number
    attr_reader :title
    attr_reader :slug
    attr_reader :summary
    attr_reader :description
    attr_reader :image
    attr_reader :activity

    def initialize(attributes)
      attributes.each do |key, val|
        instance_variable_set("@#{key}", val) if respond_to? key
      end
    end
  end
end

Vertical Slides

Slides can be nested inside of each other.

Use the Space key to navigate through all slides.

Basement Level 1

Nested slides are useful for adding additional detail underneath a high level horizontal slide.

Basement Level 2

That's it, time to go back up.

Slides

Not a coder? Not a problem. There's a fully-featured visual editor for authoring these, try it out at http://slides.com.

Point of View

Press ESC to enter the slide overview.

Hold down alt and click on any element to zoom in on it using zoom.js. Alt + click anywhere to zoom back out.

Touch Optimized

Presentations look great on touch devices, like mobile phones and tablets. Simply swipe through your slides.

Markdown support

Write content using inline or external Markdown. Instructions and more info available in the readme.

<section data-markdown>
  ## Markdown support

  Write content using inline or external Markdown.
  Instructions and more info available in the [readme](https://github.com/hakimel/reveal.js#markdown).
</section>

Fragments

Hit the next arrow...

... to step through ...

... a fragmented slide.

This slide has fragments which are also stepped through in the notes window.

Fragment Styles

There's different types of fragments, like:

grow

shrink

fade-out

current-visible

highlight-red

highlight-blue

Transition Styles

You can select from different transitions, like: None - Fade - Slide - Convex - Concave - Zoom

Slide Backgrounds

Set data-background="#dddddd" on a slide to change the background color. All CSS color formats are supported.

Image Backgrounds

<section data-background="image.png">

Tiled Backgrounds

<section data-background="image.png" data-background-repeat="repeat" data-background-size="100px">

Video Backgrounds

<section data-background-video="video.mp4,video.webm">

... and GIFs!

Background Transitions

Different background transitions are available via the backgroundTransition option. This one's called "zoom".

Reveal.configure({ backgroundTransition: 'zoom' })

Background Transitions

You can override background transitions per-slide.

<section data-background-transition="zoom">

Pretty Code

function linkify( selector ) {
  if( supports3DTransforms ) {

    var nodes = document.querySelectorAll( selector );

    for( var i = 0, len = nodes.length; i < len; i++ ) {
      var node = nodes[i];

      if( !node.className ) {
        node.className += ' roll';
      }
    }
  }
}

Code syntax highlighting courtesy of highlight.js.

Marvelous List

  • No order here
  • Or here
  • Or here
  • Or here

Fantastic Ordered List

One is smaller than... Two is smaller than... Three!

Tabular Tables

Item Value Quantity Apples $1 7 Lemonade $2 18 Bread $3 2

Clever Quotes

These guys come in two forms, inline: “The nice thing about standards is that there are so many to choose from” and block:

“For years there has been a theory that millions of monkeys typing at random on millions of typewriters would reproduce the entire works of Shakespeare. The Internet has proven this theory to be untrue.”

Intergalactic Interconnections

You can link between slides internally, like this.

Speaker View

There's a speaker view. It includes a timer, preview of the upcoming slide as well as your speaker notes.

Press the S key to try it out.

Oh hey, these are some notes. They'll be hidden in your presentation, but you can see them if you open the speaker notes window (hit 's' on your keyboard).

Export to PDF

Presentations can be exported to PDF, here's an example:

Global State

Set data-state="something" on a slide and "something" will be added as a class to the document element when the slide is open. This lets you apply broader style changes, like switching the page background.

State Events

Additionally custom events can be triggered on a per slide basis by binding to the data-state name.

Reveal.addEventListener( 'customevent', function() {
  console.log( '"customevent" has fired' );
} );

Take a Moment

Press B or . on your keyboard to pause the presentation. This is helpful when you're on stage and want to take distracting slides off the screen.

Much more

THE END

- Try the online editor - Source code & documentation

A Small Refactoring Naming your data