Skip to content

Instantly share code, notes, and snippets.

@brainwire
Created February 8, 2015 07:02
Show Gist options
  • Select an option

  • Save brainwire/a8ae7f3fb152f3a3187b to your computer and use it in GitHub Desktop.

Select an option

Save brainwire/a8ae7f3fb152f3a3187b to your computer and use it in GitHub Desktop.
Coocon: Allow to use with simple arrays without AR
I'm using my branch now in the project which works perfectly fine so far.
The only additional glue to use it with fully transient models are those few methods: new_record?, marked_for_destruction? and _destroy.
I'm not sure why cocoon touches the _destroy method.
The example above allows using fully transient models (non-ActiveRecord) with cocoon and any form builder.
I'll put everything together for a comprehensive example:
Model:
Requirements are:
all objects must be ActiveModel-compliant (eg, plain ActiveModel, Virtus, ActiveAttr etc)
implement the new_record?, marked_for_destruction? and _destroy methods on the nested object
implement build_<nested_name> (as in, build_user) to return a new template
implement <nested_nameS>_attribtues= (as in, users_attribtues=) to parse the POSTed data and update the nested items appropriately.
Full implementation:
class User
include ActiveAttr::Model
attribute :email
end
class Company
include ActiveAttr::Model
attribute :name
def users
@users ||= []
end
def users_attributes=(attrs)
@users = attrs.map { |key, params| User.new(params) }
end
def build_user
User.new # blank state for new template
end
def new_record?
true
end
def marked_for_destruction?
false
end
def _destroy
false
end
end
Views
The view will look like a regular one that uses ActiveModel (in my case, it's a simple form builder):
= simple_form_for @company, as: :company, url: company_path(@company), method: :put do |f|
= f.input :name
%h2 Users
= link_to_add_association '+', f, :users , 'data-association-insertion-node' => '#users', 'data-association-insertion-method' => 'append'
#users
= f.simple_fields_for :users, @company.users do |user_form|
= render 'user_fields', f: user_form
where user_fields may look like:
%h3 User details
f.input :name
= link_to_remove_association "X", f
____
<% @server.interfaces.each do |interface| %>
<div>
<%= f.fields_for :interfaces, OpenStruct.new(interface), index: "" do |interface_form| %>
<%= render "interface_fields", f: interface_form %>
<% end %>
</div>
<% end %>
____
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment