Search code examples
ruby-on-rails-4nested-formsnested-attributescocoon-gem

Ruby on Rails - Cocoon gem, Don't Pre-populate existing/added posts in edit action


My application has models Campaign & Post, I have:

class Campaign < ActiveRecord::Base
  has_many :posts, inverse_of: :campaign
  accepts_nested_attributes_for :posts, reject_if: :all_blank, allow_destroy: true

class Post < ActiveRecord::Base
  belongs_to :campaign

My form:

= simple_form_for(@campaign) do |f|
  = f.error_notification
  = f.input :title
  #posts
    = f.simple_fields_for :posts do |post|
      = render 'post_fields', f: post
    .links
      = link_to_add_association 'Add Post', f, :posts, wrap_object: Proc.new {|post| post.user_id = current_user.id; post }

I use Cocoon gem for nested_forms.

When I go to my campaigns#edit view, I can see all posts that were already added to a campaign (natural behavior of the gem), and I can add new posts to my campaign and/or edit existing posts .

I have also a button that has this param: add_to: 'existing_campaign' and what I am trying to achieve is, if my link has ?add_to=existing_campaign, I don't want to show/Pre-populate any of the posts that were already added to campaign, so user can only add new posts to the campaign

My link_to looks like: = link_to 'Add Post', edit_campaign_path(campaign, add_to: 'existing_campaign'),

short explain: if edit link has param ?add_to=existing_campaign, I don't Pre-populate already added posts, if param doesn't exists, I Pre-populate posts

How can I achieve this?


Solution

  • Set up an attr_accessor in campaign to control whether or not existing posts should be seen...

    class Campaign < ActiveRecord::Base
      attr_accessor hide_posts
      ...
    end
    

    Set the value in your edit method

    class CampaignsController < ApplicationController
    
      def edit
        @campaign.hide_posts = params[:add_to] == 'existing_campaign'
        ...
      end
    

    Ensure the temporary variable is in your strong parameters (so that redisplay after failed update remembers to hide posts)

    def campaign_params
      params.require(:campaign).permit( :hide_posts, ...
    

    Now on your view you can do...

    = f.hidden_field :hide_posts
    = f.simple_fields_for :posts do |post|
      = render('post_fields', f: post) unless @campaign.hide_posts && post.object.persisted?