Outpost::Aggregator
Provides UI and server-side handling for building associations between any two objects.
Installation
gem 'outpost-aggregator'
Dependencies
This is a pretty simple gem... you can probably get away with using this gem without Outpost. Just be sure you have a few things setup:
- A client-side
window.outpost
object for the javascript. -
Outpost.obj_by_key
- to find an object by the passed-in object key. This is defined in outpost. - The join model must respond to
position
andobj_key
if you want to use the SimpleJson module. This module is dead-simple, so you definitely could just copy and paste its contents into your model and customize it there.
Usage
The aggregator writes a JSON string to a hidden input, and that's what gets submitted to and parsed by the server.
In your model:
class Post < ActiveRecord::Base
has_many :related_posts, order: "position", dependent: :destroy
accepts_json_input_for :related_posts
end
In the form, you need to provide a div for the aggregator to be built in, the hidden input for the JSON string, and then initialize the Aggregator with bootstrapped content. Using simple_form, and assuming the record's association is called "content" (which is the default), it might look like this:
<div id="aggregator" class="aggregator"></div>
<%= f.input :related_posts_json, as: :hidden, input_html: { id: "related_posts_json" } %>
<script>
aggregator = new outpost.Aggregator(
"#aggregator", "#related_posts_json",
<%= j record.related_posts.includes(:post).map(&:post).to_json.html_safe %>,
<%= raw options.to_json %>);
</script>
You should also define an outpost.ContentAPI
, to tell the Aggregator how to get in touch with your server.
class outpost.ContentAPI
#-----------------------------
class @Content extends Backbone.Model
#----------
# simpleJSON is an object of just the attributes
# we care about for SCPRv4. Everything else will
# filled out server-side.
simpleJSON: ->
{
id: @get 'id'
position: @get 'position'
}
#-----------------------------
class @ContentCollection extends Backbone.Collection
url: "/api/content/"
model: ContentAPI.Content
#----------
# Sort by position attribute
comparator: (model) ->
model.get 'position'
#----------
# An array of content turned into simpleJSON. See
# Content#simpleJSON for more.
simpleJSON: ->
contents = []
@each (content) -> contents.push(content.simpleJSON())
contents
#-----------------------------
class @PrivateContentCollection extends @ContentCollection
url: "/api/private/content"
#-----------------------------
Your API should have a by_url
path, and should accept query params for
the search and URL import to work.
See the content_full
and content_small
templates to see what the aggregator
expects the response object to look.
TODO
- Write tests
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request