【问题标题】:Using Apotomo gem to build a user-driven widget page使用 Apotomo gem 构建用户驱动的小部件页面
【发布时间】:2013-08-13 00:22:41
【问题描述】:

我正在尝试使用 apotomo 在我的应用程序中设置小部件,但遇到了一些问题。我试过研究,但还没有发现任何有用的东西。希望有人在这里有一些经验。

这是我的设置:

  • 我有用户模型(通过 Devise 设置),每个人都可以创建自定义页面(页面模型)。
  • 每个页面可以有多个小部件。 PagesController#show 视图用于显示页面的发布版本或为用户预览页面。 PagesController#edit 视图用于以“编辑”模式显示页面,并为每个小部件提供表单,允许用户根据需要对其进行更新。
  • 我有一个带有序列化“数据”字段的小部件模型,该字段保存每个小部件的值。 (例如titleurl 等)。

我遇到的问题是显示每个用户的自定义小部件。

为了这个问题,假设我有一个小部件“PicturesWidget”。我已将小部件添加到 PagesController,如下所示:

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

我在 Pages 控制器中有两个视图:“PagesController#Edit”和“PagesController#Show”。我还在小部件控制器中定义了两个视图,一个是“PicturesWidget#edit”,默认是“PicturesWidget#display”。从编辑和显示视图中,我使用类似这样的东西来加载小部件:

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

但是,我遇到的主要问题是用户每页可以有多个小部件。换句话说,我必须将序列化的data 字段传递给每个小部件,以便它可以在PicturesWidget#displayPicturesWidget#edit 视图中显示内容。在PagesController我做:

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

views/pages/show.html.erb 中,我使用以下循环:

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

这最终将每个单独的小部件 ActiveRecord 作为参数传递给PicturesWidget 控制器。在小部件控制器中,我在 displayedit 方法中添加了“args”:

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

这给我带来了很多问题,因为当我必须重新渲染视图或将其替换为另一个视图时,我通常会抱怨“args”不存在,而且我无法传递它。

在 Apotomo 文档中,我发现我们应该在新版本的 gem 中使用选项而不是 args。选项是从原始PagesController中的“has_widget”方法中提取的:

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

在这种情况下,options[:data] 将返回 @data。但是,我需要为每个小部件提供数据,而不是全局 @data var。我找不到任何其他人如何做到这一点的例子。有什么建议么?还是我应该放弃整个事情并编写自己的小部件控制器?还是降级到单元格并编写我自己的 AJAX 处理程序?

很抱歉写了这么长的文章。我认为其他人可能会遇到这个问题,希望这可以帮助他们。

谢谢, 尼克


[编辑] 正如建议的那样,我最终添加了独特的小部件:

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

必须覆盖其中一个模块以允许在控制器/视图中使用 apotomo_root:

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

(在上面添加了:apotomo_root

在控制器中使用它来获取所有加载的小部件的列表:

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

然后我只是在视图中对其进行了迭代:

<% @widget_ids.each do |id| %>
  <%= render_widget id %>
<% end %>

【问题讨论】:

    标签: ruby-on-rails widget cells apotomo


    【解决方案1】:

    您可以为每个小部件设置单独的选项。无论如何,您应该为每个配置实例化不同的小部件。通过向每个小部件传递一个 id 来做到这一点: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
    

    然后,您可以使用#render_widget 中的小部件 id。

    render_widget 'one'
    

    【讨论】:

    • 啊,有趣的方法。我如何找到“已加载”小部件的列表?我不能在控制器和视图中使用find_widget(:root)。顺便感谢您的回复。
    • 我最终覆盖了其中一个模块以使 apotomo_root 在视图中可用。不确定这是否是最好的路线。 (在原帖中添加了相关代码)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    相关资源
    最近更新 更多