Search code examples
ruby-on-rails-4nested-attributesassigncocoon-gem

Assign nested attributes records to current user when using Cocoon gem


In my application I have models Post & Slides & I have:

class Post < ActiveRecord::Base
   has_many :slides, inverse_of: :post
   accepts_nested_attributes_for :slides, reject_if: :all_blank, allow_destroy: true

Everything works fine, only thing I need (because of how my application will work), is when a slide is created, I need to assign it to current_user or user that is creating the record.

I already have user_id in my slides table and:

class User < ActiveRecord::Base
  has_many :posts
  has_many :slide
end

class Slide < ActiveRecord::Base
  belongs_to :user
  belongs_to :post
end

My PostsController looks like this:

  def new
    @post = current_user.posts.build

    // This is for adding a slide without user needing to click on link_to_add_association when they enter new page/action
    @post.slides.build
  end


  def create
    @post = current_user.posts.build(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Was successfully created.' }
      else
        format.html { render :new }
      end
    end
  end

Any help is appreciated!


Solution

  • There are two ways to accomplish this:

    First option: when saving the slide, fill in the user-id, but this will get pretty messy quickly. You either do it in the model in a before_save, but how do you know the current-user-id? Or do it in the controller and change the user-id if not set before saving/after saving.

    There is, however, an easier option :) Using the :wrap_object option of the link_to_add_association (see doc) you can prefill the user_id in the form! So something like:

    = link_to_add_association ('add slide', @form_obj, :slides,
          wrap_object: Proc.new {|slide| slide.user_id = current_user.id; slide })
    

    To be completely correct, you would also have to change your new method as follows

    @post.slides.build(user_id: current_user.id)
    

    Then of course, we have to add the user_id to the form, as a hidden field, so it is sent back to the controller, and do not forget to fix your strong parameters clause to allow setting the user_id as well :)