I have following subscription creating system, right now when I`m selection available subscription groups(Marketing, Sales) action Save Subscription create this two subscriptions:
@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
So I can only add new Subscriptions(in this particular example i can only add Engineering)

How to refactor that action to be able also destroy subscription groups by uncheck them(ex. I want to unsubscribe from Marketing group) ?
So when I choose Marketing and Enginnering then params[:subscription][:app_id] will be equal [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 %>
Relations:
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
# == 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
So the issue is how to find which apps has been unchecked?
Then remove subscription for them and remove Feeds using Feed.app_destroy_items(app)
Ok, so in your case Susbcription is a join model between App and User. That means you can see a User’s apps like so:
That means you can also set them in the same fashion. So something like this should work:
Because subscription is a join model and you’ve got it linked on both ends, you don’t really need to bother loading the model directly in most cases.
Updated above to show handling unchecking all apps.
Responding to comments:
If you need to know the difference between the old and new apps, you could do something like:
However, it looks to me like your controller is getting stupid fat here. Why isn’t more of this being handled at the model layer?
For instance, for
Feed.app_destroy_items(app), why not have a callback in subscription for after destroy?As for setting
approved=true… how would a user get a subscription that is not approved? Think about it that way. They don’t get the option to click on ones they aren’t shown, right? Is this an issue where they have to pay to get certain things?Pretty much deciding whether or not a user is able to subscribe to something should not be happening at the controller level. So, I would say put a callback in subscription that won’t allow it to be saved for a user who isn’t authorized, then you can respond if the user saves or not, and if not you show the user errors.