Using Ruby Service Objects To Refactor Your Rails Code Discussion
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.
Can you use active record queries in PORO's i.e. Lead.find in UpdateLead class
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.
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.
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?
If you would like to find out more on Service Objects, check out this blog post: https://selleo.com/blog/essential-rubyonrails-patterns-part-1-service-objects
Hope it helps!