Very nice video Chris! I really like the idea of breaking things out into POROs. I think the next refactoring I would do to this app is making a Subscription class to house the logic for adding and updating the mailchimp list. Since multiple parts of your app could end up needing to add someone to mailchimp. Also feels like its violating SRP there.
Yep! All your classes are available inside your POROs like you would expect. The things you won't have access to are things like "params" that come from inheriting ApplicationController. You'll have to pass those in.
Arent you calling lead_params twice? First, when you call CreateLead.new(lead_params) and then when you call @lead = Lead.new lead_params inside the save method on the CreateLead class ? Couldn't you just do @lead = Lead.new(@params) because we pass lead_params into the @params variable when we instantiate the instance of the PORO class. Or, b/c params is just an attribute on the CreateLead Class, we can't do that.
Good catch! That should actually reference
@params in the PORO because it doesn't have access to
lead_params in there unless you move that code too.
I don't think I've touched that for a bit. If you see it broken, send me a screenshot and I'll make sure to correct it. They should definitely be on the index page.
Hey Chris! I've been trying to "dumb down" service objects with a basic association between blogs and posts. I want to organize my model folder exactly how you have all of your lead related objects under the model / folder but I'm stumped. Can you point me in the right direction?...
Hey James! You can actually generate these types of nested models with Rails:
rails g model Blog::Post title
That will create the Post model nested inside the blog folder. The table name will be "blog_posts" because database tables don't have nesting. They just scope it by prepending "blog_" at the beginning in the database table. I agree with the StackOverflow poster in that you shouldn't try to override the table name to be safe. You can still scope it in your code and so long as you don't also create a "BlogPost" model, you will be fine.
Ok, I guess that works! So does this guys' solution below also require prepending the table like you said?...
Yeah in the database I think you would have both "users" and "something_users" tables.
Very good video Chris. One question, do we have to put this:
config.autoload_paths += Dir[Rails.root.join('app', 'models', '{*/}')]
in order to load the folder Leads inside the model?
The class has to match the filename exactly. If you have app/models/reviews/create_review.rb you need to have a
class Reviews::CreateReview defined in it. It must match the folder and filename for autoloading to work automatically. Folders equate to namespaces, and underscored filenames are converted to cased words.
Mainly it's good convention to keep one class per file, and have the class inside the file named exactly the same.
Rails already does autoloads that path, it's just that it requires the class inside to match the folder+filename. So since it already does that, you might as well just follow the convention.
If you would like to find out more on Service Objects, check out this blog post:
Hope it helps!
Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.