$30 off During Our Annual Pro Sale. View Details »

Commit.where.not(liked_by: ‘DHH’).reject!

Claudio B.
December 13, 2012

Commit.where.not(liked_by: ‘DHH’).reject!

Presented at the L.A. Ruby meetup, December 2012

Claudio B.

December 13, 2012
Tweet

More Decks by Claudio B.

Other Decks in Programming

Transcript

  1. Commit.where.not(liked_by: ‘DHH’).reject!
    A story about open source, ideas, smells and tastes
    [github.com/claudiob]
    I’m a Senior Software Engineer at GOOD and I’m going to to tell you a story about what I learned from contributing to Rails.

    View Slide

  2. TL;DR
    Commit.where(“liked_by <> ‘DHH’”)
    Commit.where.not(liked_by: ‘DHH’)
    Rails 3
    Rails 4
    So since this is a story, I’m going to spoil it and tell you how it ends.
    In Rails 3, ActiveRecord cannot specify negative conditions in a query, so you have to use SQL operators.
    In Rails 4, ‘where’ becomes a chainable method that can be followed by a new not operator to write a negation

    View Slide

  3. Now that you know the end of the story, let’s rewind to its inception.
    Most people don’t listen when you say something is annoying, even more if you are a stranger.
    But programmers can be more heartful and kind than normal people.
    We actually listen to complaints, even when they come from strangers. We empathize!

    View Slide

  4. Commit.where(:liked_by ^ ‘DHH’)
    Someone else had a similar feeling and created a gem to avoid SQL fragments.
    What’s cool about gems is that you decide if you want to use them or not.

    View Slide

  5. But suggesting this syntax in Rails core… gets rejected: it doesn’t smell or taste right.
    DHH may sound harsh but he is telling the truth.
    He is inviting us to try harder, to make a better coding world for everyone.
    This is the main reason I love open source, because you can follow your instincts and feel human again!

    View Slide

  6. Commit.where_not_like(sha: ‘2F%’)
    So a new option came up: introducing where_not.
    Well then, why not where_like, where_not_like, where_union etc?
    But this would pollute ActiveRecord, a lot!

    View Slide

  7. Commit.where.like(author: ‘cla%’)
    Commit.where.not(liked_by: ‘DHH’)
    Finally, the best idea arrives: keept only one ‘where’ and make it chainable.

    View Slide

  8. where(“author <> ‘DHH’”)
    where.not(author: ‘DHH’)
    @de75af7
    where.not(‘author = “DHH”’)
    where.not(‘author = ?’, ‘DHH’)
    Rails 3
    where(“author like ‘DH%’”)
    where.like(author: ‘DH%’)
    @de75af7
    Rails 3
    where(“author not like ‘DH%’”)
    where.not_like(author: ‘DH%’)
    @de75af7
    Rails 3
    Initially implemented by @amatsuda. Smells almost right…

    View Slide

  9. where(“id <> 42”).order(:id)
    where.not(id: 42).order(:id)
    @de75af7
    Rails 3
    …but here’s a gotcha. Using mixins does not smell right.
    Mixins delegate the responsibility to another module instead of making sure the code does what we want.
    And you can write “smelly code” like the where.order(…).not(…) statement.

    View Slide

  10. where(“id <> 42”).order(:id)
    where.not(id: 42).order(:id)
    @de75af7
    where.order(:id).not(id: 42)
    Rails 3
    …but here’s a gotcha. Using mixins does not smell right.
    Mixins delegate the responsibility to another module instead of making sure the code does what we want.
    And you can write “smelly code” like the where.order(…).not(…) statement.

    View Slide

  11. So I made a pull request to use a builder class rather than a module.

    View Slide

  12. where(“id <> 42”)
    where.not(id: 42)
    @de75af7
    Rails 3
    where(“id > 42”)
    where.gt(id: 42)
    ???
    Rails 3
    where(“id <= 42”)
    where.lte(id: 42)
    ???
    Rails 3
    where.greater_than(id: 42)
    ???
    where.less_than_or_equal(id: 42)
    ???
    Moreover, if we start adding inequalities, than why not adding ALL of them?

    View Slide

  13. Sounds right, but it’s not powerful enough, because they only apply to numeric types, while not has more uses.
    Funny how a discussion started with “all SQL fragments are annoying” and took us to really understand their power one by one.

    View Slide

  14. where(“author <> ‘DHH’”)
    where.not(author: ‘DHH’)
    @de75af7
    where.not(‘author = “DHH”’)
    where.not(‘author = ?’, ‘DHH’)
    Rails 3
    where(“author like ‘DH%’”)
    where.like(author: ‘DH%’)
    @de75af7
    Rails 3
    where(“author not like ‘DH%’”)
    where.not_like(author: ‘DH%’)
    @de75af7
    Rails 3
    Which brings us back to evaluate this commit: in this light, where.like and where.not_like look very similar to inequalities: only apply to strings, do not reduce the code.

    View Slide

  15. where(“author <> ‘DHH’”)
    where.not(author: ‘DHH’)
    @de75af7
    where.not(‘author = “DHH”’)
    where.not(‘author = ?’, ‘DHH’)
    Rails 3
    where(“author like ‘DH%’”)
    where.like(author: ‘DH%’)
    @de75af7
    Rails 3
    where(“author not like ‘DH%’”)
    where.not_like(author: ‘DH%’)
    @de75af7
    Rails 3
    Which brings us back to evaluate this commit: in this light, where.like and where.not_like look very similar to inequalities: only apply to strings, do not reduce the code.

    View Slide

  16. Therefore, not powerful enough to belong to the core!

    View Slide

  17. TL;DR
    Commit.where(“liked_by <> ‘DHH’”)
    Commit.where.not(liked_by: ‘DHH’)
    Rails 3
    Rails 4
    In the end, Rails 4 will have where chainable only with .not.
    Contributing to Rails is fun, you learn a lot from the process, not only about source code, but about communities and the impact you can make following your instincts and listening to people who express feelings like “being annoyed”.
    So, join the movement and contribute to open source!

    View Slide