2
votes

I've attempted to use the paperclip gem to add attachments to my contact model. It looks as though I can add an attachment - I can select the file without a problem. However when I then create the contact, the attachment is not saved. I know this because I can see in the rails console that the document_id is 'nil'.

In the _form.html.erb for creating a new contact, I have:

<%= simple_form_for(@contact, html: {class: "form-inline well", multipart: true}, role: "form") do |f| %>
        <% if @contact.errors.any? %>
          <div id="error_explanation">
            <h2><%= pluralize(@contact.errors.count, "error") %> prohibited this contact from being saved:</h2>

            <ul>
            <% @contact.errors.full_messages.each do |msg| %>
              <li><%= msg %></li>
            <% end %>
            </ul>
          </div>
        <% end %>

        <div class="form-group">

          <%= f.input :name %>
          <%= f.input :category %>
          <%= f.input :area %>
          <%= f.input :phone %>
          <%= f.input :website %>
          <%= f.input :email %>

          <%= f.fields_for :document do |document_fields| %>
            <%= document_fields.input :attachment, as: :file %>
          <% end %>

          <%= f.button :submit, class: "btn-success" %>
        </div>
      <% end %>

my db migration for this was:

class CreateDocuments < ActiveRecord::Migration
  def change
    create_table :documents do |t|

        t.integer :user_id
        t.timestamps
    end

    add_index :documents, :user_id
    add_attachment :documents, :add_attachment
    add_column :contacts, :document_id, :integer
  end
end

My model for document.rb is:

class Document < ActiveRecord::Base

    has_attached_file :attachment, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
    validates_attachment_content_type :attachment, :content_type => /\Aimage\/.*\Z/
end

and for contact.rb is:

class Contact < ActiveRecord::Base
    belongs_to :user
    belongs_to :document

    accepts_nested_attributes_for :document

    validates :name, presence: true,
                        length: { minimum: 2}

    validates :user_id, presence: true
end

and my actions in the contacts_controller.rb are:

    def create
    @contact = current_user.contacts.new(contact_params)

    respond_to do |format|
      if @contact.save
        format.html { redirect_to @contact, notice: 'Contact was successfully created.' }
        format.json { render action: 'show', status: :created, location: @contact }
      else
        format.html { render action: 'new' }
        format.json { render json: @contact.errors, status: :unprocessable_entity }
      end
    end
  end
  def contact_params
    params.require(:contact).permit(:name, :email, :category, :area, :organisation, :website, :phone, :user_id, document_attributes: [:id, :attachment])
   end

  # PATCH/PUT /contacts/1
  # PATCH/PUT /contacts/1.json
  def update

    @contact = current_user.contacts.find(params[:id])
    if params[:contact] && params[:contact].has_key?(:user_id)
      params[:contact].delete(:user_id) 
    end
    respond_to do |format|
      if @contact.update((contact_params))
        format.html { redirect_to @contact, notice: 'Contact was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @contact.errors, status: :unprocessable_entity }
      end
    end

  end

When I try to create a new contact with an attachment, here is my heroku log:

2014-03-10T23:41:49.594786+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"FGitLGkHzfw15yksCusGDvwdb//CgMyOMFh4SS4l63Y=", "contact"=>{"name"=>"Oliver OT", "category"=>"OT", "area"=>"Rockdale", "phone"=>"", "website"=>"", "email"=>"", "document_attributes"=>{"attachment"=>#, @original_filename="Screen Shot 2014-03-03 at 9.24.40 pm.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"contact[document_attributes][attachment]\"; filename=\"Screen Shot 2014-03-03 at 9.24.40 pm.png\"\r\nContent-Type: image/png\r\n">}}, "commit"=>"Create Contact"} 2014-03-10T23:41:49.594786+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"FGitLGkHzfw15yksCusGDvwdb//CgMyOMFh4SS4l63Y=", "contact"=>{"name"=>"Oliver OT", "category"=>"OT", "area"=>"Rockdale", "phone"=>"", "website"=>"", "email"=>"", "document_attributes"=>{"attachment"=>#, @original_filename="Screen Shot 2014-03-03 at 9.24.40 pm.png", @content_type="image/png", @headers="Content-Disposition: form-data; name=\"contact[document_attributes][attachment]\"; filename=\"Screen Shot 2014-03-03 at 9.24.40 pm.png\"\r\nContent-Type: image/png\r\n">}}, "commit"=>"Create Contact"}

I'm not sure how get the attachment to save correctly?

2

2 Answers

0
votes

Move the contact_params method outside of the update action so it can be accessed by the create action and change it to the following code.

def contact_params
  params.require(:contact).permit(:name, :email, :category, :area, :organisation, :website, :phone, :user_id, document_attributes: [:id, :attachment])
end

The code above allows the id and attachment params for document_attributes.

0
votes

Your migration has a problem:

add_attachment :documents, :add_attachment

This will mean your database table will have the attachment columns as add_attachment instead, thus causing Paperclip not to work

You'll need to change the columns in your db with a migration like this:

class Migration < ActiveRecord::Migration
  def change
    rename_column :documents, :add_attachment_file_name, :attachment_file_name
    rename_column :documents, :add_attachment_content_type, :attachment_content_type
    rename_column :documents, :add_attachment_file_size, :attachment_file_size
    rename_column :documents, :add_attachment_updated_at, :attachment_updated_at
  end
end