stephanie writes code

(For People Who Read English Good)


The Ruby ‘Struct’ Class

After months of hearing the book’s name in mass circulation, I finally decided to get up close and personal with Sandi Metz’ Practical Object-Oriented Design in Ruby. I made this decision in part because the weeks leading up to Flatiron’s graduation (Dec. 13th!) had been particularly Rails and JavaScript heavy, in part because this in turn had made me miss Ruby, and also in part because I felt it necessary to fortify my understanding of object-oriented programming best practices.

Though I’m still in the early chapters of POODR, I can already tell this is going to be a monumental asset not only to my understanding and appreciation of Ruby, but also to my sensibilities and skills as a programmer. Most laudably, it’s just written so damn well. Maybe too well, as one reviewer has tellingly marveled:

“I was rather surprised how, even though the book starts with simple examples, it quickly develops and builds on them to provide good explanations.”

In other words, POODR is comprehensible, digestible, and accessible. As such, it’s actually an effective learning tool. Shocking!

Anyhow, the crux of this post is — in addition to praise for Metz’ work — the Ruby Struct class. I came across this neat little ‘class helper’, if you will, for the first time in Chapter 2 of POODR.


What is a Struct?

According to the official Ruby documentation, a Struct is “a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class.” After playing around with it a bit in pry, it feels like a quick and cheap way to create Class-like instances on the fly that can possess both behaviors and qualities (much like regular Classes). Here’s a sample Struct that I’ll build out called Person:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Person = Struct.new(:name, :age, :gender) do

  def greet_world
    "Hello world, my name is #{name}."
  end

  def ask_question
    "What is your favorite programming language?"
  end

end


stephanie = Person.new("Stephanie", "26", "female")

stephanie.name          # => "Stephanie" 
stephanie.age           # => "26"
stephanie.gender        # => "female"

stephanie.greet_world   # => "Hello world, my name is Stephanie."
stephanie.ask_question  # => "What is your favorite programming language?"

Cool, right? Remember, the symbols you pass to your new Struct upon initialization — in this case :name, :age, and :gender — act like regular attr_accessors. So I could make some alterations after the matter, like so:

1
2
3
4
stephanie.name = "Ruby"
stephanie.age = "21"

stephanie.greet_world   # => "Hello world, my name is Ruby."

…but that might be a little confusing.

I can now also make a bunch of new Persons, instantiating each one with his or her name/age/gender, and he or she will also respond to the greet_world and ask_question methods.


When would you use a Struct?

This is a great question. It wasn’t immediately clear to my why or when one would use a Struct, especially when the more ubiquitous Class is always an option. According to what I’ve read so far in POODR, it seems that using a Struct is one way to separate structure from meaning; it plays nicely with Classes, and also helps to make your methods more transparent.

If all of that sounded a bit vague and not yet super helpful, then it might help to look at another example wherein a Struct is used within a Class in order to break down method responsibilities and also make those methods more transparent:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
data = [["Stephanie", "female"], ["Matz", "male"], ["Sandi", "female"], ["David", "male"],
["Aaron", "male"]]

class TransparentRoster
  attr_accessor :participants

  def initialize(data)
    @participants = structify(data)
  end

  def sorted_names
    participants.collect { |person| person.name }.sort
  end

  def participant_list
    puts "This year's participants include:"
    sorted_names.each { |name| puts name }
  end

  # here's where we turn the 2D array of data into struct objects

  Person = Struct.new(:name, :gender)

  def structify(data)
    data.collect { |pair| Person.new(pair[0], pair[1]) }
  end

end

The TransparentRoster Class above takes a parameter called ‘data’ — in this case, that data is coming in the form of a 2-dimensional array. It is immediately dealt with upon initialization, calling on a method named structify(data) that turns each [name, gender] pair from the given array into Struct objects that can be further dealt with via the :participants attr_accessor, and which respond to both .name and .gender.

In taking this approach, we were able to give the TransparentRoster class mostly the illusion of single-class responsibility (i.e technically, the Roster class shouldn’t be responsible for, say, initializing new Persons; it should deal solely with duties that might sensibly pertain to a Roster like listing names, ordering them, etc). Furthermore, we were able to keep all of its methods small and single-purpose as well. Finally, the handling of raw data was kept limited to one place — the structify(data) method — so that if the given data were to change from a 2-dimensional array to a different structure, such as a hash, the code to extract the necessary data would only need to be altered in one place. All other method dependencies could remain relatively unharmed.

I’m curious to see in what other contexts and real-life code bases I might come across Structs. So far, they seem like a great tool for managing single-class responsibility when you’re not yet sure how many classes you ought to build or of what magnitude these classes should be for an evolving project. There’s a lot left of POODR to read so maybe subsequent chapters will shed further light on this.


KEY TAKEAWAYS

  1. POODR is awesome.
  2. A Struct is a convenient way to bundle together attributes without having to build out or commit to building a whole Class.
  3. Structs can be included within Classes.
  4. If done so, a Struct can help illuminate the given Class’s ‘single purpose’ by handling the extraneous stuff; this also keeps the Class’s methods short and sweet.

Rails in 15 Minutes

It’s been about 4 weeks since we began learning Rails, and two of those weeks we’ve spent in manic project mode. Manic in a good way, of course — as in everyone has been relentlessly devoted to building Rails-based web applications (which has also forced many of us to learn WAY more about AJAX and jQuery on the fly than we ever thought possible in such a short amount of time, especially in tandem with learning an entire framework from the ground up). I think what I’m hinting at is: major brain overload (or brain… overflow? sorry — terrible joke).

I take it for granted now that I occasionally have to battle my instance variables when using form_fors or forget to set before_actions. Because not too long ago, in a very serious way, I literally had no idea what Rails was.

Sure, I’d heard and read multiple times that Rails “is a framework for building web applications”. But what, then, was a framework? How did Ruby fit into it? Were Rails and Ruby on Rails the same thing? I had so many questions prior to these last 4 weeks, and though many had recommended Code School’s Rails for Zombies series, I just couldn’t get into it.

So hopefully, the following breakdown is helpful to anyone who’s just embarking upon their soon-to-be awesome journey into Rails:


Okay, so what is Rails?

Rails is a framework for building web applications.

Just kidding.

Well, that’s actually true, but I’m going to attempt a better explanation because that one is vague and unhelpful. To begin, I’d like to share a few broad (as in, not specific to code or programming) definitions of the word ‘framework’ that I think best apply to the context of Rails:

framework [ˈfreɪmˌwɜːk] n

  1. A skeletal structure designed to support or enclose something else
  2. A set of concepts, assumptions, values, and practices that constitutes a way of viewing reality

Okay, now keep those definitions on a mental back-burner. Because they apply to Rails in the sense that they help add brushstrokes and color to the overall picture, but neither of those definitions alone is entirely helpful in grasping — at the most basic level — what Rails IS.

As simply and literally put as possible, Rails is a kind of software, or ‘magic kit’, that you download locally on your computer via one simple command in your terminal (assuming you already have the RubyGems packaging system): gem install rails. Once you’ve installed it, Rails provides you with a whole bunch of functionality so that you can efficiently start building web applications. In other words, there’s a vast library behind the scenes (i.e the Rails source code) into which a lot of complex methods and logic have been defined and pre-coded by some really smart people (like this guy) so that you don’t have to; instead, you can type some simple commands like rails new [project name] or rails generate scaffold [model], and Rails will respond to them.


Now, how exactly is Rails like a ‘framework’?

To relate this back to the above definitions, rails is a framework in the sense that its many built-in shortcuts will magically create skeletal structures (organized directories, basic routes, empty models with their corresponding migrations, etc.) for you to fill in with further details, i.e code and logic. It also encapsulates its creator(s)‘ values, assumptions, and opinions on programming best-practices, i.e THEIR way of viewing ‘reality’.

One of the most definitive illustrations of how ‘framework-like’ Rails is is the directory structure you instantly get after running rails new [project name]. Something like 30 directories come pre-organized, nested and labeled for you — and some even contain files with pre-written CODE! Thus, rather than leave it up to each individual programmer to organize his or her directories in whatever way he/she deemed fit, the masterminds behind Rails decided to take choice out of the equation and hammer home instead a pre-determined layout to encourage convention. Their values and assumptions are clearly at play here. And though it may sound stiff and undemocratic at first, once you use Rails to build stuff (and conversely, have to jump into other people’s Rails projects — oftentimes to debug), you’ll realize how time-saving and mental energy-saving these baked-in conventions truly are. So thank you, DHH, for having an opinion!


So you can build real web apps in fewer than 5 lines of code??

Well, sort of. Five lines of code will get you some basic CRUD functionality, but that’s about it.

Unfortunately, while Rails’ out-of-the-box mileage is great, it isn’t really going to cut it when you have to build anything for real. That is, any serious web application you build using Rails is going to require a lot of customization, i.e you’re going to need to read quite a bit of Rails documentation and learn how it’s really used — and knowing the Ruby language will really help here.

A lot of well-known sites and applications do use Rails, including some you may have heard of: Shopify, Twitter, Github, and more.

Exicted to start Rails-ing, much?

(If the answer is ‘YES!’, then I suggest starting here, with Michael Hartl’s free Rails tutorial. It’s super step-by-step, controlled, and well-explained every step of the way. He also ties in some Git and Heroku, which is a nice touch because it helps contextualize all the other stuff you’ll actually come in contact with when you use Rails for real. And personally, I say skip the Rails guide for now until you’ve had some practice going through the motions, a la Hartl’s tutorial. Otherwise, you’ll have no context. Besides, guides are best used in general for “sandboxed queries” — once you have an idea of something specific you need an answer to).


Are ‘Rails’ and ‘Ruby on Rails’ the same thing?

Yes.

Rails is simply the shorthand version of saying it; Ruby on Rails is the same thing.


How does Ruby fit into it?

Rails/Ruby on Rails was built using the Ruby programming language, and thus also runs on Ruby. That’s a pretty direct way in which Ruby ‘fits into the picture’. And as mentioned above, any customization and/or granular manipulation of your Rails-based web application is going to require some real knowledge of Ruby; you don’t need to be an expert, but much of what you want to accomplish and much of the control over what data you choose to display (or not display) is going to rely on basic Ruby stuff like the .each method, if else logic, etc.

(If you want recommendations on free beginner Ruby resources, I personally like Codecademy, RubyMonk, and Chris Pine’s Learn to Program.)


I think that was approximately 15 minutes’ worth of reading?

Happy Rails-ing!

5 Simple Tips/Lessons From Gem-Building

Two posts ago, I dropped a hint about a basic ruby gem I was trying to build. At the time, building one’s own gem(s) seemed to be the de rigueur object of our collective fascination at Flatiron. I guess that’s because we were all itching to start building things, and we hadn’t yet begun to learn Rails.

So I’m a little late to our gem-party, but I’m so happy I gave it a go (better late than never, right? Cue: mental reminders about ‘unrealistic self-expectations’). Because inevitably, the thing you learn most about through the process of gem-building — as is the case with absolutely anything you’ll ever build with code — is git.

Only joking.

But really, I did actually learn an unexpected amount more about git. And with that said, since everyone loves lists, here’s a list of 5 simple tips and lessons from my personal experience with ruby gem-building:


1. Just start with the RubyGems Guide. Like, seriously.

Don’t waste hours debating your starting point. Just start with the RubyGems Guide. Having done precisely the opposite — I ditched the guide in favor of a Treehouse video tutorial then got confused and ended up coming back to the guide — I know now that the RubyGems Guide is actually the easiest thing to follow. It walks you through the process of building a simple “Hello World!” gem, and without having to worry much at all about project directories or structure, you can build and ship your first ruby gem in about 15 minutes.

2. Then try a tutorial, like this one

Once you’ve familiarized yourself a bit with basic directory organization and in which directories stuff should go, you can then follow along with this Treehouse tutorial to build your real gem. The main reason I suggest you wait until you’ve practiced with the RubyGems Guide first before diving into a tutorial like this one is that the latter instructs you to run this simple command as your starting point:

bundle gem <the name of your gem>

This will perform a bit of magic for you — not unlike the Rails/DHH magic we have at our disposal with the rails g scaffold <the name of your project> command — and instantly create a bunch of directories with files that have placeholder text and stuff in them. While this might sound totally awesome, it can also be confusing to use this as your starting point because you won’t know why things have been set up the way they have. Which is to say, it will be harder for you to customize stuff to suit your needs — because you won’t know what’s going to cause the whole thing to break and what’s okay to change.

So build your directories and files from the ground up yourself first (following the RubyGems Guide), THEN take advantage of shortcuts like bundle gem <the name of your gem>.

3. Don’t forget, you’re using git

If you do go off of the bundle gem shortcut, be aware: it initializes a git repo in your project directory automatically.

Yes. Look at the last line! Initializing git repo... it says. Somehow, I didn’t pay attention to this detail, so later down the road when I pushed my first version of the gem up to rubygems then instantly realized I had to make an edit and push up a new version, I ran into a huge wall. I kept getting error messages that said something along the lines of “[some_file_name, some_other_file_name] are not files”. And I thought “WHY??! WHAT DO YOU MEAN THEY AREN’T FILES? I’VE SAVED EVERYTHING, I CAN SEE THEM IN MY DIRECTORIES, THEY EXIST! OF COURSE THEY’RE FILES!!”

Well. Turns out, my computer wanted me to do a git add . and git commit before I could proceed with pushing up new gem versions. This is because the bundle gem <the name of my gem> shortcut initialized a git repo for me, which meant I had to start tracking my changes. The fact that I’d forgotten this and/or hadn’t paid attention to the activity in my console from the get-go didn’t change the fact that I now had to answer to git.

4. Make sure your gem-name isn’t already taken

The problem I ran into above (and the subsequent 3 hours of de-bugging) was all due to this basic mistake: I’d forgotten to make sure my gem name wasn’t already taken. So after building everything and trying to run gem push <my gem>, I was promptly denied. This forced me to have to go back and make a lot of changes, including RENAMING MY GEM.

So just check first on RubyGems.org that your gem name hasn’t already been taken! And don’t assume, like I did, that it’s necessarily something more complicated — like an error with my API-key (I ran around in circles trying to ‘fix’ that for a while, when that was never the issue to begin with). It’s really easy to get excited and just start building, and equally easy to jump to crazy conclusions as to where and how you should start debugging your errors.

5. Handle your gemspec with care

Your gemspec is not just some random file you can treat as an afterthought (as is often done unfortunately with README files, for example), just because it doesn’t live in the ‘all-important’ lib or bin directories. Your gemspec file is literally the roadmap TO YOUR GEM, or a blueprint, rather. It contains tons of valuable information such as your gem’s version number, executables, and run-time dependencies, to name a few.

Furthermore, as you can see, when you actually run the gem build <yourgemname.gemspec> command to BUILD your gem, you have to build it off of the gemspec! It’s just convention. Needless to say, your gemspec file is important. Update it, make sure it contains accurate information, and treat it with care.

================================================================

All of that said, I had a lot of fun building my first gem. Special shoutout to our TA Spencer Rogers for helping me de-bug and ultimately realize that my 3-hour roadblock had, in fact, stemmed 100% from git troubles.

My gem is called billboard_chart.

You can install it by running gem install billboard_chart.

Then simply type billboard_chart to see what happens!

(NOTE: 24 hours after I published my gem, Billboard.com decided to switch up some of their CSS selectors so now the scraper generating my data — I used Nokogiri — is acting funny, which means the data also looks a bit funny now. Looks like I now have some ACTUAL de-bugging to do!!!)

The Myth of ‘I Can’t Code’

This past Friday, my Ruby-003 cohorts and I hit the halfway point of our time as students at the Flatiron School. Halfway points are — by nature of being, well, halfway between the start and the end — always a bittersweet thing. They’re also an opportune time for reflection. So before it becomes too far off from the halfway point to be a meaningful post, I wanted to share some reflections on my journey thus far into programming.

Or more accurately, I should say, my ongoing battle with programming.

Because the truth is, it’s felt more like a struggle and raging internal war these last six weeks than anything else. And what exactly have I been struggling with and/or against?

Ridiculous self-expectations

It’s really, really easy to be hard on yourself at the Flatiron School. Why? Because you’re surrounded by highly intelligent, highly motivated people day in and day out. Everyone comes from varying degrees of prior exposure and experience with coding. And whether there is any rational sense or not, as a complete novice, in expecting to learn things as quickly as others who have had more exposure or experience, or even learn things differently than you do — you do it anyway. You expect ridiculous things of yourself. Like “why can’t I build my own ruby gem already?” when a day prior, you barely understood methods. Or “how are my friends (AT OTHER BOOTCAMPS) able to build such cool things with rails (IN THEIR WEEK 7) while I can barely understand what rails IS??” when a month prior, you didn’t even know what an HTML tag was. Indeed, unreasonable self-expectations were a huge part of my struggle the first few weeks.

Impostor Syndrome

This is something we’ve spoken about very candidly at Flatiron, and I’m glad for it. Because it’s one of those things that I never really had a proper name for but had felt in random spurts throughout my life, and once given the proper lexicon for it, could finally make sense of the feeling in the first place. Impostor syndrome. Where you feel like you don’t really belong or deserve to belong to a particular group. That being, in this case, a combination of both the Flatiron School and the general world of programming as a whole. For the first few weeks, I thought surely that I had slipped through the admissions cracks; that I had duped everyone and somehow “impostored” my way into Flatiron. I felt this way due to a number of reasons, none of which were actually reasonable: I wasn’t good at programming yet (of course I wasn’t — I’d never programmed in my life and I was here to learn!), I hadn’t majored in Comp Sci in college (barely anyone else in the program had, either), I didn’t know many, if ANY, keyboard shortcuts upon entering the program (because knowing keyboard shortcuts automatically makes one a good programmer…?), and I was/am a woman. Once again, being unreasonable with myself was largely responsible for my struggling.

The actual learning of programming and programming itself

Finally, we arrive at this point: the challenge and struggle of CODING ITSELF! Learning how to code is hard, period. For 99.9% of the world. There might be five people on the planet for whom learning how to code was/is ‘just easy’. So yes, learning how to code is hard enough on its own, but as you can surmise from the above, I’d made it exponentially harder on myself to absorb or learn anything productively because my brain was already on such overload with totally unreasonable mental roadblocks. So much so, in fact, that I began to buy into the unfortunate myth of ‘maybe I can’t do it — maybe I just can’t code’.

The myth of ‘maybe I just can’t code’

This myth is, I think, the sum total of all of one’s unreasonable internal voices combined with the point-blank fact that programming can indeed be a challenge to learn if you’ve never done it before. JUST LIKE ANYTHING ELSE YOU’RE NEW AT AND HAVE NEVER DONE BEFORE BUT WANT TO LEARN AND GET GOOD AT. It’s funny how we underplay, too, the things we have become good at over the years in order to somehow justify harder that programming IS SO IMPOSSIBLE – MAYBE I JUST CAN’T DO IT. Like playing the piano. I probably put in 12340918108241 hours of practice before I could play my first sonata — yet in far fewer hours, I’ve learned enough Ruby and programming to build my own ruby gem. Equivalently, if anyone could study the piano for just 6 weeks and play a Mozart-ANYTHING, they’d probably be considered a prodigy.

So this notion that ‘I can’t code’ — based on your performance after just a handful of weeks — is just plain wrong. Okay fine, maybe you can’t code AT XYZ LEVEL (yet). But that’s the key distinction to make: yet. If you adopt a deterministic attitude about your current AND future coding abilities based on your present noobness, i.e you decide “I’m not good 3 weeks into this so I’ll NEVER be good”… well, it already sounds ridiculous, doesn’t it? Especially when, as long as you keep learning and keep trying, it’s literally impossible to maintain your noobness forever. Which is to say, eventually you get better. Until you’re good. Maybe even great.

Anyhow, after being unreasonably hard on my psyche and emotions the first four weeks or so, a weird thing happened around week five: I finally gave in to learning. That sounds weird to say, because it wasn’t for lack of trying that I didn’t feel like I was really LEARNING weeks one through four. More than likely, I was learning just as much that entire time — but every little thing came harder and felt more uncomfortable. Because I was familiarizing myself with a completely new domain for the first time! And just trying to build enough of a foundation that I could eventually start picking up on patterns. And I think that’s what finally happened around week five; I started seeing and anticipating, on a very basic level, some of the patterns in programming.


Back full circle to the present: the halfway point. Halfway into my time at Flatiron (and just a short minute into a much longer lifetime of programming), I know how to use both git and github to maximize not only my individual workflow, but a group workflow; I feel weird if I’m ever using my GUI instead of living and breathing in my Terminal; I’ve scraped various websites including Netflix.com and RottenTomatoes.com for fun projects like a command-line game that I helped present at a NYC Rails Meetup; I know the difference between SQL, Sequel, and Sqlite and that both the Sinatra and Rails frameworks are built on top of Rack; I can build a basic Sinatra application and convert all the code into a Rails version of the application; I have a much better intuition about project directory structures and can thus guess where to find specific files better — i.e I was able to further customize this blog template today by downloading and adding social media icons. Did I mention that I pushed my first gem to rubygems.org this afternoon?

There’s still a lot I have to review, and a lot that I have to practice so that I don’t get rusty. Let alone the vast universe of stuff I still have to learn. But it’s important to remind ourselves of our victories sometimes, too. Because they keep us motivated, and keep us pushing.

These are my reflections on the first six weeks. They were hard as hell.

And I can’t wait for the next six.

Easy Analogies to Demistify Web Application Jargon

I’m starting to think that colorful metaphors and super literal blog post titles pair best together.

With that said (disclaimer: I’m feeling a little dotty on this foggy Halloween day), here are some ‘colorful’ metaphors and analogies to help lift the proverbial fog from some web-application jargon…


1. ERB (Embedded Ruby)

ERB is little more than HTML with superpowers. You know it’s ERB (as opposed to plain old HTML) — largely — when you see these <%= something here %>. And what are those? Interpolation points, much like these in basic Ruby #{}. They’re kind of like little portals through which you can make contact with and access the resources of another planet (i.e language, i.e Ruby). Think Stargate.


2. SQLITE vs. SQL vs. SEQUEL

Seriously, why do they all have to sound the same?! Especially when they’re all such distinct entities. Guess we should start with Sqlite. Thanks to Scott C. Reynolds for the following analogies.

Sqlite

This is a database management system, or DBMS. It like, lets you store and save stuff and delete stuff (also known as ‘data persistence’ and CRUD). In the context of Halloween, since it’s Halloween today, Sqlite is a garage littered with knick knacks that you’re further using to store Halloween decorations. Other similar DBMS’ that fit this analogy include MySQL and PostgreSQL (not a very pretty but still helpful comparison between the two). To make a distinction, however, if Sqlite is a 2-car garage, then MySQL is a 10-car garage.

SQL (Structured Query Language)

As its full name suggests, SQL is a language. Just like HTML and Ruby and Python and Javascript are languages — so is SQL. It is not a gem. It is not the database itself. SQL IS A LANGUAGE. You’re using SQL when you type stuff like SELECT * FROM <table_name>. And to continue the Halloween/garage analogy, hard coding SQL to get stuff in and out of your database is a little like going out of your way to poke around through all the crap sitting in your garage to find and retrieve a ball of tangled Halloween lights. There’s a need to get the lights (i.e the data), yes, but this way of doing it is tedious.

Sequel

And this is where Sequel comes in. Sequel is an ORM, or Object Relational Mapper, which is just a fancy way of saying ‘the common ground between two different languages’ — namely, SQL and Ruby. Other ORMs include ActiveRecord and DataMapper (a helpful comparison between the two). Sequel is just another one of these ORM things. And to beat the Halloween analogy to death, using Sequel in place of SQL is like relaxing on your porch with a pumpkin beer while you get the neighbor kid to go into your garage, find the lights, and bring them out to you nice and untangled. You don’t care how he did it — all you know is you asked the kid to do something, and it was done. Nice.


3. M-V-C (Model View Controller)

I don’t have a Halloween analogy for this.

Jeff Atwood actually has a great explanation of the Model-View-Controller paradigm right here. To summarize his version, the model contains the logic and data of your web application; the view is how you display your data and web application; and the controller, though a little more complicated, is the link between the user and the system behind your web application. How it all works together? I like to think of the M-V-C model as an elaborate and meticulously-arranged domino chain that behaves in an expected way from one trigger or initiation point. If you’ve designed and coded all your moving parts to work properly together, then one file with a single command should be able to kickstart the whole application. Your finger pushing that first domino would be the equivalent of a runner file, or something similar.


I’m going to keep adding to this list as I feel inspired.

At the very least, I hope you’ll come away from this post feeling confident that you’ll never confuse Sqlite, SQL, and Sequel EVER AGAIN!