Reputation: 851
I have an iOS api linking to a rails app. I have sent the rails app an iOS image which I'm trying to store as header_img but am getting an error that they're is no public directory. What is a good path to specify for images in my heroku api?
Here is the heroku error:
2014-04-04T21:51:47.179916+00:00 app[web.1]:
2014-04-04T21:51:47.179916+00:00 app[web.1]: Errno::EISDIR (Is a directory - public/header_img/):
2014-04-04T21:51:47.179916+00:00 app[web.1]: app/controllers/groups_controller.rb:98:in `initialize'
2014-04-04T21:51:47.179916+00:00 app[web.1]: app/controllers/groups_controller.rb:98:in `open'
2014-04-04T21:51:47.179916+00:00 app[web.1]: app/controllers/groups_controller.rb:98:in `upload_header_img'
2014-04-04T21:51:47.179916+00:00 app[web.1]: app/controllers/groups_controller.rb:44:in `create'
Here is my Groups Controller:
class GroupsController < ApplicationController
# GET /groups
# GET /groups.json
before_filter :require_auth
def index
@privategroups = @user.groups
@publicgroups = @user.followees(Group)
@groups = (@privategroups + @publicgroups).sort_by( &:created_at ).reverse
end
# GET /groups/1
# GET /groups/1.json
def show
@group = Group.find(params[:id])
@posts = @group.posts
end
# GET /groups/new
# GET /groups/new.json
def new
@group = Group.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @group }
end
end
# GET /groups/1/edit
def edit
@group = Group.find(params[:id])
end
# POST /groups
# POST /groups.json
def create
@group = Group.new(params[:group])
@group.owner_id = @user.id
header_img = @group.header_img || @group.decode_header_img_data
if header_img.present?
upload_header_img(header_img)
end
respond_to do |format|
if @group.save
@membership = @user.memberships.build(group_id: @group.id)
@membership.save
format.html { redirect_to @group, notice: 'Group was successfully created.' }
format.json { render json: @group, status: :created, location: @group }
else
format.html { render action: "new" }
format.json { render json: @group.errors, status: :unprocessable_entity }
end
end
end
# PUT /groups/1
# PUT /groups/1.json
def update
@group = Group.find(params[:id])
respond_to do |format|
if @group.update_attributes(params[:group])
format.html { redirect_to @group, notice: 'Group was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @group.errors, status: :unprocessable_entity }
end
end
end
# DELETE /groups/1
# DELETE /groups/1.json
def destroy
@group = Group.find(params[:id])
@group.destroy
respond_to do |format|
format.html { redirect_to groups_url }
format.json { head :no_content }
end
end
private
def upload_header_img(header_img_io)
# upload to the exact location account id and extension
extension = File.extname(header_img_io.original_filename)
# rails take public as root directory
# under the root directory (public)
# there are a icon directory
header_img_url = "/header_img/"[email protected]_s + extension
# open in binary mode
File.open("public"+header_img_url,'wb') do |file|
file.write(header_img_io.read)
end
@group.update_attribute(:header_img_url, header_img_url)
end
end
Upvotes: 1
Views: 132
Reputation: 76774
Although I can't provide a direct answer, I have some ideas which may help:
According to Heroku, they run a read-only filesystem:
Your app is compiled into a slug for fast distribution by the dyno manager. The filesystem for the slug is read-only, which means you cannot dynamically write to the filesystem for semi-permanent storage. The following types of behaviors are not supported:
- Caching pages in the public directory
- Saving uploaded assets to local disk (e.g. with attachment_fu or paperclip)
- Writing full-text indexes with Ferret Writing to a filesystem database like SQLite or GDBM
- Accessing a git repo for an app like git-wiki
CORRECTION
Have since found the above is for their Bamboo
stack (old). The cedar
stack (new) supports temporary file writing:
Each dyno gets its own ephemeral filesystem, with a fresh copy of the most recently deployed code. During the dyno’s lifetime its running processes can use the filesystem as a temporary scratchpad, but no files that are written are visible to processes in any other dyno and any files written will be discarded the moment the dyno is stopped or restarted.
We do use Paperclip & upload to Heroku (when in test), it's generally not supported and any files will be overwritten each time you redeploy your app
Storage
ChrisBarthol
gave a good suggestion - store any user-submitted
assets on S3
or another third party system. I would go further and say that you'll probably benefit profusely from using Paperclip
to save the files:
#app/models/group.rb
Class Group < ActiveRecord::Base
has_attached_file :header_img
:storage => :s3,
:s3_credentials => Proc.new{|a| a.instance.s3_credentials }
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end
Upvotes: 1