Question

I am trying to use apotomo for setting up widgets in my app and have been running into a few issues. I've tried researching, but haven't found anything useful yet. Hopefully, someone might have some experience here.

Here is my setup:

  • I have Users model (set up via Devise), who can each create custom pages (Pages model).
  • Each Page can have a number of widgets. The PagesController#show view is used to display a published version of the page or preview the page for the user. The PagesController#edit view is used to display the page in "edit" mode w/ forms for each widget, allowing the user to update them as needed.
  • I have a Widgets model with a serialized "data" field that holds the values for each widget. (Things such as title, url, etc).

The issue I am running into is displaying each user's customized widget.

For the sake of this question, let's assume I have a single widget "PicturesWidget". I've added the widget to the PagesController like so:

class PagesController < ApplicationController
  has_widgets do |root|
    root << widget(:pictures)
  end
  ...
end

I have two views in the Pages controller: "PagesController#Edit" and "PagesController#Show". I also defined two views in the widget controller, one is "PicturesWidget#edit" and the default is "PicturesWidget#display". From the edit and show views, I use something like this to load the widgets:

# In views/pages/show.html.erb:
<%= render_widget :pictures, :display, ... %>
# In views/pages/edit.html.erb:
<%= render_widget :pictures, :edit, ... %>

However, the main issue I am running into is the fact that the user can have multiple widgets per page. In other words, I have to pass in the serialized data field into each widget, so it can display the content in PicturesWidget#display or PicturesWidget#edit views. In the PagesController I do:

def show
  @user = ...
  @page = @user.pages.find(params[:page_id])
  @widgets = @page.widgets
end

And in views/pages/show.html.erb I use the following loop:

<% @widgets.each do |widget| %>
  <%= render_widget :pictures, :display, :widget => widget %>
<% end %>

This ends up passing-in each individual widget ActiveRecord as an argument to the PicturesWidget controller. In the widget controller, I added "args" to both display and edit methods:

def display(args)
  @widget = args[:widget]
  @title = @widget.data[:title]
  @url = @widget.data[:url]
  render
end

This is causing me issues all over the place because when I have to re-render the view or replace it with another, I usually get complaints that "args" is not present, and I have no way to pass it in.

In Apotomo documentation I found that we are supposed to use options instead of args in the newer version of the gem. Options are pulled from the "has_widget" method in the original PagesController:

has_widgets do |root|
  root << widget(:pictures, :data => @data)
end

In this case options[:data] would return @data. However, I need to provide data per each widget, not a global @data var. I wasn't able to find any examples of how others are doing this. Any suggestions? Or should I just scrap the whole thing and write my own Widget Controller? Or downgrade to cells and write my own AJAX handlers?

Sorry for the long write-up. I reckon someone else might run into this issue and hopefully this helps them out.

Thanks, Nick


[Edit] As suggested, I ended up adding unique widgets as so:

@page.widgets.each do |indiv_wid|
  root << widget(indiv_wid.kind.to_sym, indiv_wid.id, data: indiv_wid.data)
end

Had to override one of the modules to allow use of apotomo_root in the controller/views:

module Apotomo
  module Rails    
    module ActionViewMethods
      delegate :render_widget, :apotomo_root, :url_for_event, :to => :controller
    end
  end
end

(Added :apotomo_root above)

Used this in the controller to get a list of all the loaded widgets:

apotomo_root.each do |x|            
  @widget_ids << x.widget_id unless x.widget_id == :root
end

And then I simply iterated over it in the view:

<% @widget_ids.each do |id| %>
  <%= render_widget id %>
<% end %>
Was it helpful?

Solution

you can have separate options per widgets. You should instantiate different widgets for each configuration, anyway. Do so by passing an id the each widget: http://rdoc.info/github/apotonick/apotomo/Apotomo/WidgetShortcuts:widget

class PagesController < ApplicationController
  has_widgets do |root|
    root << widget(:pictures, 'one', :data => ...)
    root << widget(:pictures, 'two', :data => ...)
  end
  ...
end

You can use the widget id in #render_widget, then.

render_widget 'one'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top