Live data from Hacker News

Where the logic hides in rails apps

gammons.github.com

31–40 of 56 posts

Re: Where the logic hides in rails apps

#31
post #6

Maybe this is naive, but what's wrong with just putting `UserMailer.welcome_email(user).deliver` in the controller, right after the user is created? In my mind, delegating an email to be sent should be a job for the controller. IIRC, the Rails ideology says that "Models should not know about any part of the application except for their own datastore." Even though the :after_create hook is the "Rails way", doesn't thi…

This is pretty much exactly what DHH advocates for, and for a simple case like this (creating a user, sending an email) it works great.

At some point though, your controllers are going to grow. Multiple code paths depending on the data submitted, depending on the current state of the application, etc. At this point, building service classes such as CreatesContact can become very useful, not to mention much easier to test and reuse.

Evan Light's article at http://evan.tiggerpalace.com/articles/2012/11/21/use-rails-u... advocates "Use Rails until it hurts" which I think is a very good mantra to keep in mind when working with Rails.

Re: Where the logic hides in rails apps

#32
post #25

Earlier quoted context omitted.

> give them electric shock even better, force them to use COmmon Business Oriented Language

They should also use principles from the Object Management Group.

and after they finish building the system with separated business logic, suggest their business client to add a formal business requirement that all data should be persistently stored. just in case.

Re: Where the logic hides in rails apps

#33

Anyone intersted in this style of programming needs to read "Clean Ruby" by Jim Gay. (Currently being written with beta access) To be honest; it looks like this post might have been inspired by that book (or the concepts behind it) but I think the book does a better job explaining it (Obviously, a book vs a single blog post.)

I just tore through that book just a few days ago! Definitely a lot of eye-opening things happening in relation to rails and architecture.

I think a lot of people/projects/companies have been burned attempting to upgrade rails, or have a slow test suite, or having a terrible time trying to figure out where to fit core application logic into the rails stack.

And then you have an epiphany and say, wait, rails should not define my app. You say, I should be able to upgrade to rails 4 on day 1. Rails does not define my application, my application defines my application! So if you do just a wee bit of partitioning, it goes a very long way. (much to the chagrin of DHH, who for some reason evangelizes having your core logic in ActiveRecord models, to a fault)

Re: Where the logic hides in rails apps

#34
post #28

Earlier quoted context omitted.

steer clear from most of the entrenched practices and packages (e.g. devise and related trainwrecks) I agree with your sentiment in general, but what do you suggest to use in place of devise? Surely you're not suggesting to write all the code for handling mail confirmation, password changes etc. yourself?

In fact for serious apps that are expected to grow I do recommend to write the auth yourself. It's not a lot of code, from the second time it's mostly copy/paste, and most importantly you'll fully understand what your code does and when, there will be no guesswork in one of the most important areas of your app. Furthermore you usually end up heavily customizing whatever auth-code you start with anyway. The shrinkwrap…

So you're one of those guys. I inherited a Rails app that used roll-your-own auth instead of Devise or similar — it added a significant amount of mental overhead, plus a bunch of additional logic for Facebook login.

Task that with another product I just launched: over 100K users, on Devise, no customization needed, and Login with Facebook took 1 additional library, 3 lines of code and 15 minutes.

I used to be the roll-your-own-everything guy, years ago. After maintaining dozens and dozens of Rails apps, I'm not anymore. I'm much happier when logic is pushed into libraries and I can ignore it until it matters.

> In fact for serious apps that are expected to grow I do recommend to write the auth yourself.

No, no, no, just no. If you don't grow, you just wasted time you should have spent shipping real features. If you do grow, refactor in your own authentication later if you have to.

> you'll fully understand what your code does and when

You will, for sure. When you leave for another project and I'm brought into maintain $app, I won't, straight away.

> there will be no guesswork in one of the most important areas of your app.

There is no guesswork with 3rd-party libraries. `bundle open gem-name` is your friend. If you read through the code, you'll understand what it's doing, just like I'll have to read through your code if you roll-your-own library.

One of the major benefits to standardized libraries is that I only have to read the library for Devise or AuthLogic once across a dozen apps. I have to learn each customized solution 100% of the time.

> It still suffers from a bit of rails-smell (code-generators...)

I get the feeling that you work on really large apps with a lot of custom logic, and end up wishing you had complete control over everything. In such situations I'd probably end up agreeing with you 90% of the time if you suggested throwing out a 3rd-party library and rolling your own.

I just strongly disagree that you should start out that way. Your app should have a single selling point: "Schedule my tweets", "Remind me to pay bills", "keep track of my tasks", or whatever. Not "Log in with our unique authentication code."

No app ever became a million dollar company because a developer thought the most important job was to roll their own authentication scheme before they even scored a thousand users.

Re: Where the logic hides in rails apps

#35
While I don't like the name of the service object "CreatesContact", I disagree with the statement that the sending of an email should reside within the create_contact! method. The author's intent is to shield any new developers from methods that say one thing and do another, yet he adds email delivery into the create_contact! method without informing the developer what may happen (unless some magic flag is set somewhere).

A simpler, more contrived example, would be to create a new function create_and_send_email! and place the creation logic and email sending logic in there. And now, when the developer uses the service object, she has the ability to choose between just creating the contact, or creating it and sending an email.

    class CreatesContact
      def initialize(contact)
        @contact = contact
      end

      def create_contact!
        @contact.save
      end

      def create_contact_and_send_email!
        create_contact!
        deliver_contact_created_email
      end
    end

Re: Where the logic hides in rails apps

#36
post #34
post #28

Earlier quoted context omitted.

In fact for serious apps that are expected to grow I do recommend to write the auth yourself. It's not a lot of code, from the second time it's mostly copy/paste, and most importantly you'll fully understand what your code does and when, there will be no guesswork in one of the most important areas of your app. Furthermore you usually end up heavily customizing whatever auth-code you start with anyway. The shrinkwrap…

So you're one of those guys. I inherited a Rails app that used roll-your-own auth instead of Devise or similar — it added a significant amount of mental overhead, plus a bunch of additional logic for Facebook login. Task that with another product I just launched: over 100K users, on Devise, no customization needed, and Login with Facebook took 1 additional library, 3 lines of code and 15 minutes. I used to be the rol…

I think our opinions are not as far apart as it seems.

You are of course right that rolling your own auth won't be the first priority in your initial PoC. Neither is it needed for very simple apps or when you're dead-certain that you won't need more flexibility than the common gems provide.

However in my experience the latter almost never applies in a commercial app. Suddenly you need OmniAuth in addition to devise, and some form of ACLs. Then you grow an API that also needs some sort of auth-tokens. Then there's this other site you want to interface with which needs yet another bridge. Then one day you run that ad on TV and learn the hard way that those extra-lookups devise makes on every request are not free after all...

So what I'm saying is that the design of (in particular) devise and authlogic is just not a very good one to start from if you can already predict that you'll need customizations (beyond templating) in the future.

A frankensteined devise can be a lot harder to understand than a straightforward impl from scratch - but in the end it of course also boils down to who wrote it and whether he wrote it for the first time.

Re: Where the logic hides in rails apps

#38

While I don't like the name of the service object "CreatesContact", I disagree with the statement that the sending of an email should reside within the create_contact! method. The author's intent is to shield any new developers from methods that say one thing and do another, yet he adds email delivery into the create_contact! method without informing the developer what may happen (unless some magic flag is set somewh…

I agree with your comments on the class name, it should probably be ContactCreator. But I think having a method named create_contact_and_send_email is kind of code-smelly. I'd most likely do something like:

    create_contact!(:send_email => false)
Post reply on HN