Skip to content

Instantly share code, notes, and snippets.

@luxerama
Created March 14, 2012 11:48
Show Gist options
  • Save luxerama/2035968 to your computer and use it in GitHub Desktop.
Save luxerama/2035968 to your computer and use it in GitHub Desktop.
Many-to-Many association support with batman.js
<div>
<div data-addclass-error="channel.errors['name'].length">
<label for="channel_title">Name:</label>
<div class="input">
<input data-bind="channel.name" name="channel[name]" id="channel_title"/>
</div>
</div>
<div>
<ul>
<li data-foreach-category="categories">
<label class="checkbox">
<input type="checkbox" data-bind="channel | hasCategory category "/>
<span data-bind="category.name"></span>
</label>
</li>
</ul>
</div>
</div>
# Run the Batman app
$(document).ready ->
Ems.run()
class Ems.Category extends Batman.Model
@storageKey: 'categories'
@persist Batman.RestStorage
@url = "/ems/categories"
@hasMany 'channels'
@encode 'id', 'slug', 'name', 'strapline', "created_at", "updated_at"
@encode "created_at", "updated_at", Batman.Encoders.railsDate
@validate 'name', 'strapline', presence: yes
class Ems.Channel extends Batman.Model
@storageKey: 'channels'
@persist Batman.RestStorage
@url = "/ems/channels"
@hasMany 'categories' #, { autoLoad: true }
@encode 'id', 'slug', 'name', "created_at", "updated_at"
@encode "created_at", "updated_at", Batman.Encoders.railsDate
@validate 'name', presence: yes
# Should this static function really be here? This to me is something that should not be handled by the model, I think it would be more
# suitable to a helper, however using a helper in the data-event-change is not stable enough.
# I find the whole concept a little off, as this toggleCategory function can only really be used with a checkbox. Is there a better way
# of doing this?
@toggleCategory: (node, event) ->
category_id = node.getAttribute('id')
# get channel and categories from the controller
channel = Ems.controllers.get('channels').channel
categories = Ems.controllers.get('channels').categories
# retrive the category that was selected/deselected
category = categories.indexedByUnique('id').get(parseInt(category_id))
# first we need to check if we actually have the category with the given ID. If we do, let go ahead and add it, or
# remove it from the channel categories association set.
if category
if node.checked
channel.get("categories").add category
else
channel.get("categories").remove category
else
throw "No category found with ID: " + category_id
# Channels helper file
Batman.mixin Batman.Filters,
# Method for identifying which category has an association with which channel
# This is used in the channel/_form.html as a way to check/uncheck the checkboxes.
hasCategory: (channel, category) ->
category.get('channels').indexedByUnique('id').get(channel.get('id'))
class Ems.ChannelsController extends Batman.Controller
channels: null
categories: null
index: (params) ->
show: (params) ->
new: (params) ->
@set 'channel', new Ems.Channel
Ems.Category.load (err, cats) =>
throw err if err
categories = new Batman.Set
for i, category of cats
categories.add category
@set 'categories', categories
create: (params) ->
@get('channel').save (err) =>
if err
throw err unless err instanceof Batman.ErrorsSet
else
Ems.flashSuccess "Channel #{@get('channel.name')} created successfully!"
@redirect '/tags'
edit: (params) ->
@set 'channel', Ems.Channel.find parseInt(params.id), (err) ->
throw err if err
Ems.Category.load (err, cats) =>
throw err if err
categories = new Batman.Set
for i, category of cats
categories.add category
@set 'categories', categories
# This console log should print out a set containing 1 category object. However it unfortunately returns an empty
# AssociationSet. When looking at the XHR return from the server I can clearly see the JSON object being returned
# It just doesn't seem to be added the the channels association set of categories.
console?.log @get('channel').get('categories')
# This console log should print out a set containing 1 category object. However it unfortunately returns an empty
# AssociationSet. When looking at the XHR return from the server I can clearly see the JSON object being returned
# It just doesn't seem to be added the the categories association set of channels.
console?.log category.get('channels')
update: ->
@get('channel').save (err) =>
if err
throw err unless err instanceof Batman.ErrorsSet
else
Ems.flashSuccess "Channel #{@get('channel.title')} updated successfully!"
@redirect '/channels'
# Create our application and namespace.
class Ems extends Batman.App
@global yes
# channel routes
@resources 'channels'
# category routes
@resources 'categories'
@flash: Batman()
@flash.accessor
get: (key) -> @[key]
set: (key, value) ->
@[key] = value
if value isnt ''
setTimeout =>
@set(key, '')
, 2000
value
@flashSuccess: (message) -> @set 'flash.success', message
@flashError: (message) -> @set 'flash.error', message
<div id="new-channel" class="row">
<div id="content" class="span16">
<form accept-charset="UTF-8" class="new_channel" id="new_channel" data-formfor-channel="channel" data-event-submit="create">
<div data-partial="channels/_form"></div>
<input type="submit" />
</form>
</div>
</div>
@scottkf
Copy link

scottkf commented Jul 7, 2012

Did you ever figure out the problem with the empty association set?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment