Search code examples
ruby-on-railspostherokucarrierwaverails-postgresql

Postgres + Heroku Ruby Creation


I have an app running fine on Heroku and I am attempting to connect the app to Amazon's S3 service with Carrierwave. I thought that I had the config files all working for everything, however I am running into an issue when I am creating a picture instance. I think it has to do with Postgres and some of its specific formatting etc. but here is the main issue.

I am getting a TypeError (can't convert nil into String): on what seems like the POST to the database (specifically on the create method). The error looks as follows:

app/controllers/pictures_controller.rb:62:in `create'

TypeError (can't convert nil into String):
POST xxxxxxxx.herokuapp.com/684-536-025/pictures dyno=web.1 queue=0 wait=0ms service=510ms status=500 bytes=643

Here is the Start of the POST as well:

#<Picture id: nil, description: nil, image: nil, gallery_id: 15, gallery_url_id: "a432b35_21cc", original_filename: "Sunflower.gif", order_number: nil, created_at: nil, updated_at: nil>

I am assuming that the issue here is that Postgres does not allow starting a POST when there are fields that are nil. Oddly enough sqlite does just fine with this which is why I am guessing the issue is Postgres and unfortunately I'll be using Postgres for production. I don't know enough about Postgres to really narrow down this issue, so I figured I would ask here to see if I could get any help/advice!

Thanks!

EDIT: Here is the create method for extra help

def create
# Creates a picture class instance based on the json objects being passed in from 
# Carrierwave
p_attr = params[:picture]
p_attr[:image] = params[:picture][:image].first if params[:picture][:image].class == Array

# Gets the gallery vai the uuid gallery url
@gallery = Gallery.where(:url_id => params[:url_id]).first
# Builds the picture based on the attributes passed in above from the json
@picture = @gallery.pictures.build(p_attr)
# Assigns the gallery_url_id attribute
@picture.gallery_url_id = @gallery.url_id

puts @picture.inspect

# Handle the picture save according to success or not
LINE 62 -> if @picture.save
  respond_to do |format|
    format.html {
      # Calls the method in the model to format the json repsonse
      render :json => [@picture.to_jq_upload].to_json,
      :content_type => 'text/html',
      :layout => false
    }
    format.json {
      render :json => [@picture.to_jq_upload].to_json
    }
  end
else
  render :json => [{:error => "custom_failure"}], :status => 304
end

end

Line 62 is marked in the code.

EDIT 2: Here is the model as requested...

class Picture < ActiveRecord::Base

  # The attributes accesible via an @picture
  attr_accessible :gallery_id, :description, :image, :gallery_url_id, :original_filename, :order_number
  belongs_to :gallery

  # Attatches the carrierwave uploader to the picture class
  mount_uploader :image, ImageUploader

  # Referenced when each picture is created, the json is formatted as the following form
  def to_jq_upload
    {
      "name" => read_attribute(:image),
      "size" => image.size,
      "url" => image.url,
      "thumbnail_url" => image.thumb.url,
      "delete_url" => id,
      "picture_id" => id,
      "delete_type" => "DELETE",
      "url_id" => read_attribute(:gallery_url_id),
      "original_filename" => read_attribute(:original_filename),
      "order_number" => ""
    }
  end

end

Solution

  • I ended up using this as the config/initilizers/fog.rb

    CarrierWave.configure do |config|
      config.fog_credentials = {
        :provider               => 'AWS',
        :aws_access_key_id      => 'asdf',
        :aws_secret_access_key  => 'asdfadsf',
        :region                 => 'us-east-1'
      }
      config.fog_directory  = 'modea-design-comp-viewer'
    end
    

    Also, in the controller I had to manually set the two fields that were being POSTed as nil in the database to an empty string as such:

    def create
        # Creates a picture class instance based on the json objects being passed in from 
        # Carrierwave
        p_attr = params[:picture]
        p_attr[:image] = params[:picture][:image].first if params[:picture][:image].class == Array
    
        # Gets the gallery vai the uuid gallery url
        @gallery = Gallery.where(:url_id => params[:url_id]).first
        # Builds the picture based on the attributes passed in above from the json
        @picture = @gallery.pictures.build(p_attr)
        # Assigns the gallery_url_id attribute
        @picture.gallery_url_id = @gallery.url_id
    
        @picture.order_number = ""
        @picture.description = ""
    
        # Handle the picture save according to success or not
        if @picture.save
          puts @picture.inspect
          respond_to do |format|
            format.html {
              # Calls the method in the model to format the json repsonse
              render :json => [@picture.to_jq_upload].to_json,
              :content_type => 'text/html',
              :layout => false
            }
            format.json {
              render :json => [@picture.to_jq_upload].to_json
            }
          end
        else
          render :json => [{:error => "custom_failure"}], :status => 304
        end
      end
    

    That did it for me!