【问题标题】:How to manage multiple Subscriptions using one controller action?如何使用一个控制器操作管理多个订阅?
【发布时间】:2012-11-06 18:14:32
【问题描述】:

我有以下订阅创建系统,现在当我选择可用订阅组(营销、销售)时,Save Subscription 创建这两个订阅:

@apps = App.all
if request.post?
  if params[:subscription] and params[:subscription][:app_id]                       
    params[:subscription][:app_id].each do |app_id|                
      Subscription.create_unique({user_id: current_user.id, app_id: app_id, approved: true})
    end
    redirect_to root_path
  end
end
@subscriptions = current_user.subscriptions 

所以我只能添加新的Subscriptions(在这个特定的例子中我只能添加Engineering

如何重构该操作,以便能够通过取消选中订阅组来销毁订阅组(例如,我想从营销组取消订阅)?

因此,当我选择 MarketingEngineering 时,params[:subscription][:app_id] 将等于 [marketing.id, engineering.id]

  # app_menu.html.erb
  <%= form_for :subscription do |f| %> # this form goes to app_menu action above
    <ul>
        <% @apps.each do |app| %>
        <li>
            <%= check_box_tag app.id, current_user.access?(app) %><span><%= app.name %></span>
        </li>
        <% end %>
    </ul>
    <%= f.submit %>
    <% end %>
  <% end %>

关系:

App
  has_many :subscriptions
  has_many :users, through: :subscriptions
User
  belongs_to :app
  has_many :subscriptions, :dependent => :destroy
Subscription
  belongs_to :user
  belongs_to :app

  def self.create_unique(p)
    s = Subscription.find :first, :conditions => ['user_id = ? AND app_id = ?', p[:user_id], p[:app_id]]
    Subscription.create(p) if !s
  end

架构

# == Schema Information
#
# Table name: subscriptions
#
#  admin      :boolean
#  app_id     :integer
#  created_at :datetime
#  id         :integer          not null, primary key
#  updated_at :datetime
#  user_id    :integer
#
# Table name: apps
#
#  created_at :datetime
#  id         :integer          not null, primary key
#  name       :string(255)
#  updated_at :datetime
#  user_id    :integer
#
# Table name: users
#
#  app_id     :integer
#  created_at :datetime
#  id         :integer          not null, primary key
#  updated_at :datetime

所以问题是如何找到哪些应用程序未被选中?

然后删除他们的订阅并使用Feed.app_destroy_items(app)删除Feed

【问题讨论】:

  • 您需要显示更多代码。 (1) 创建复选框的视图代码。 (2) 订阅查看表&params[:subscription]
  • 只添加表单代码就够了吗?
  • 您需要添加模型以及关系是什么。看起来你有UserAppSubscription,这些有什么关系?
  • 刚刚添加了关系和更多操作代码。
  • 好吧,根据您所展示的内容,我想我已经为您找到了答案(如下)。试试看会发生什么。

标签: ruby-on-rails ruby-on-rails-3 model-view-controller


【解决方案1】:

好的,所以在您的情况下,订阅是应用程序和用户之间的连接模型。这意味着您可以像这样看到用户的应用程序:

user.apps # returns array of apps

这意味着您也可以以相同的方式设置它们。所以这样的事情应该可以工作:

if params[:subscription] and params[:subscription][:app_ids] #call it app_ids since you're getting an array of them.                   
  apps = App.find(params[:subscription][:app_ids])
  current_user.apps = apps
else
  current_user.apps = []
end
current_user.save

因为订阅是一个连接模型,并且您已经在两端链接了它,所以在大多数情况下,您真的不需要直接加载模型。


以上更新显示处理取消选中所有应用程序。

回应cmets:

如果您需要了解新旧应用之间的区别,您可以执行以下操作:

original_apps = current_user.apps

... the code from above ...

deleted_apps = original_apps - current_user.apps
deleted_apps.each do |app|

  ... whatever ...

end

但是,在我看来,您的控制器在这里变得愚蠢。为什么不在模型层处理更多的这些?

比如Feed.app_destroy_items(app),为什么不在销毁后订阅回调呢?

after_destroy :destroy_app_from_feed
def destroy_app_from_feed
  Feed.app_destroy_items(app)
end

至于设置approved=true ...用户如何获得未批准的订阅?这样想吧。他们没有选择单击未显示的选项,对吗?这是他们必须付费才能获得某些东西的问题吗?

几乎不应该在控制器级别决定用户是否能够订阅某些内容。所以,我会说在订阅中放置一个回调,不允许为未经授权的用户保存它,然后你可以响应用户是否保存,如果没有,你会显示用户错误。

【讨论】:

  • 谢谢,我会检查一下,如果我还必须为每个未检查的应用手动删除 Feed.app_destroy_items(app) 怎么办?我正在使用 Redis。这也是因为为什么我需要指定哪些应用没有被选中。
  • 好的,我检查并工作了,但除非上面的评论中还有一件事。当我在操作 app_menu:Subscription.create_unique({user_id: current_user.id, app_id: app_id, approved: true}) 中创建订阅时,我必须将已批准的属性设置为 true。有没有比添加到该操作的底部更好的选择:current_user.subscriptions.each{|s| s.approved = true}
  • 我也无法取消选中所有应用程序!因为那么params[:subscription] 就是nil
猜你喜欢
  • 1970-01-01
  • 2020-07-07
  • 2019-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
相关资源
最近更新 更多