This is a companion discussion topic for the original entry at https://thoughtbot.com/upcase/videos/form_objects
Nice episode! Would it be possible to see a gist of fully production-ready implementation (with the transactions @jferris mentioned)? Thanks!
If anyone is interested in a way to promote errors from component models to your Form model, hereâs one way: thredded/topic_form.rb at main ¡ thredded/thredded ¡ GitHub
I would like to see an example with tests as well.
How would I implement a multi-step form / wizard using form objects? How does Thoughtbot handle those features?
What are peoples thoughts on this presentation from rails conf 2014?
Great episode. How would you handle has_many associations with form objects?
If the user had many companies for example.
Hey guys, thanks for sharing the âform objectâ technique, very cool! You guys mentioned that the form object can cause problems when you need validations like âvalidates uniqueness ofâ because the form object doesnât use active record. However, it didnât sound like you posed a solution for that issue, which I imagine would be a common problem. Do you mind positing a solution on the forum? Thanks!
I happen to maintain an open source app that basically has this exact scenario, weâre creating a User and an Account at the same time, and it was using accepts_nested_attributes_for
. Iâve opened a PR on our app with a bit more full fledged example:
It includes (pretty basic) specs and shows how to promote child errors, allowing you to validate things like uniqueness etc.
Although I do kind of like this approach, it is quite a lot more code (~50 lines without tests)
Iâve used the wicked
gem in production for a post-sign up multi-step form process. Works well.
Nice episode.
But I am not quite sure how many code to put in the save part of the form object.
I have a form that takes a lot of configuration options, the availability of which depending on the permissions of the current user. Upon saving I need to update several models and add notifications to a queue to be picked up by a remote process. I currently use a service to do the updating, but that feels kind of awkward.
How would you go about the combination of the permissions part and the notifications part?
Thanks. Herman
I had a similar question a couple of months ago. If you like, you can add the reform gem, which allows for creating form objects with a DSL for validations, 1-n forms, etc. If youâre just interested for the sake of learning, take a look under the hood of reform to see how has_many is handled.
Hello, this was indeed a very nice episode! I liked it very much, please do more rails intermediate episodes like this one.
One thought: isnât this approach of object form similar to the concept of View Model, which can be known for example in mobile development? I am a beginner in it, but it just seemed to me like a similar concept - to have a object which is only processing the view data and then sending those to the appropriate models to be saved.
One aspect of form objects than can trip people up not mentioned:
if you do create a resource for your form object, which is advised in the episode - switching from UsersController
to SignupsController
- and set it as singular resource ( resource :signup, only: [:new, :create]
to keep the example provided), you do have to pass the url to the form.
Strictly speaking, this isnât unique to form objects, but to any form for a singular resource in Rails. There is an open issue on the Rails repo regarding this.
This is actually used as a form object in the Upcase app: https://github.com/thoughtbot/upcase/blob/master/app/models/checkout.rb
@benorenstein That link 404âs for me.
If youâre on our $29/month plan, head here for repo access: https://thoughtbot.com/upcase/repositories.
I wish this episode went into more details in implementation such as if user had many companies, or the user has a uniqueness validation on the email etc. This was a way too simple example
I like your episodes, but is there any way you can show the code for longer and not switch to you two talking so quickly. Not that youâre not beautiful. : )
Great video, I will like to know how can I edit and update, any ideas or examples?
Sorry for replying much later than your original post. Not sure if youâve already solved this but the way I see it you have a few approaches:
-
Leave the validation in the models and populate the errors up into the form object as @aaronmcadam mentioned.
-
Looking specifically at Thoughtbotâs post on uniquness validations you could have a unique index on the field which would raise an
ActiveRecord::RecordNotUnique
error which you could then rescue in the save methoddef save
if valid?
# Other code
end
rescue ActiveRecord::RecordNotUnique
errors.add(:user_email, âis not uniqueâ)
end
The main issue with this approach being that itâll only appear if everything else is valid.
-
Have a custom validation method for it, something like
validate :unique_user_email
def unique_user_email
if User.exists?(email: user_email)
errors.add(:user_email, âis not uniqueâ)
end
end
If you wanted to check it on editing youâd need to check if itâs persisted and include something to ensure you check any records where the email isnât user_email
and the id isnât the userâs id
I think the best solution then would be either using 1 or a mixture of 2 and 3 really.
@christoomey Hi Chris! Quick question about this topic if you donât mind. These Form Objects seem a lot like Presenters. Since the terminology on these is still a bit fuzzy to me, I was wondering if they really are one and the same in such a case?