Created
November 1, 2011 23:40
-
-
Save stevenharman/1332290 to your computer and use it in GitHub Desktop.
Proof of Concept: create multiple, identical, AR models from a single form.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div> | |
<h1>Add a thing to your box</h1> | |
<%= form_for @thing, html: { class: "form-stacked" } do |f| %> | |
<label>Name: <%= f.collection_select :widget_id, @widgets, :id, :name, | |
{include_blank: true}, autofocus: true %></label> | |
<label>Blah: <%= f.text_field :blah %></label> | |
<label>Other stuff: <%= f.text_field :other %></label> | |
<label>Count: <%= text_field_tag :count, @thing_count %></label> | |
<%= f.submit "Add them!" %> | |
<% end %> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ThingController < ApplicationController | |
def new | |
@thing = Thing.new | |
@thing_count = 1 | |
@widgets = Widget.all | |
end | |
def create | |
@thing_count = params[:count].to_i | |
widget = Widget.find_by_id(params[:thing][:widget_id]) | |
new_things = (0...@thing_count).collect do |i| | |
Thing.create(params[:thing]) { |t| t.widget = widget } | |
end | |
if new_things.all?(&:valid?) | |
redirect_to(things_path, notice: "Things with #{widget.name} have been added to the box!") | |
elsif | |
@thing = new_things.find(&:invalid?) | |
@widgets = Widget.all | |
flash.now[:alert] = "Oops! #{@thing.errors.full_messages.join(", ")}" | |
new_things.map { |t| t.delete } | |
render :new | |
end | |
end | |
end |
What about the following API?
# things_controller.rb
def create
@thing_count = params[:count].to_i
adds_things = AddsThingsToBox.new
adds_things.add(@thing_count, params[:thing])
if adds_things.success?
redirect_to(things_path, notice: "Things with #{adds_things.widget.name} have been added to the box!")
else
@thing = adds_things.invalid_thing
@widgets = Widget.all
flash.now[:alert] = "Oops! #{@thing.errors.full_messages.join(", ")}"
render :new
end
end
Where most of the gunk of knowing how many Thing
s to create, how to build them, and how to roll them back, is pushed off into the AddsThingsToBox
object.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is JUST a POC, but it can be done. Is there a more idiomatic, or Rails-y way of doing this?
My instinct is to throw this away and start again, test-driving from the outside. I'd like to push all of the crazy into an object, perhaps an AddsThingsToBox object, that can act in isolation, and delegate to that from this controller action. I'll still have to solve issues of Rails-specific stuff like validation methods, etc., but I think some sort of presenter might be nice for that.
Thoughts?