jckly
jckly

Reputation: 851

undefined method 'original_filename' for String?

I'm sending a base64 encoded image string to my rails server via my ios app. I'm trying to take the image in rails and save it to the database. The file is a header_img which I'm adding to my model Group.

I have been following this tutorial.

I get an undefined method error 'original_filename' but as I'm unfamiliar with the process am struggling to what it is I'm doing wrong.

The error is occuring on two lines according to the heroku log. The lines are:

Create Method: upload_header_img(header_img)

Upload_header_img Method: extension = File.extname(header_img_io.original_filename)

Here is my full code:

Private function at the bottom of groups_controller:

 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"+icon_url,'wb') do |file|
      file.write(header_img_io.read)
      end

      @group.update_attribute(:header_img_url, header_img_url)
   end

My create groups function in the groups_controller:

  def create
      @group = Group.new(params[:group])
      @group.owner_id = @user.id
      header_img = @group.header_img || @group.decode_header_img_image_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

Group Model :

class Group < ActiveRecord::Base

      attr_accessible :description, :name, :user_id, :private, :header_img_url, :header_img_data, :header_img
      attr_accessor :header_img_data, :header_img
      has_many :posts
      has_many :memberships 
      has_many :users, :through => :memberships
      acts_as_followable 

      def decode_header_img_data
      # if the icon_image_data is set
      # decode it and handle by controller method

        if self.header_img_data.present?
          data = StringIO.new(Base64.decode64(self.header_img_data))
          data.class.class_eval {attr_accessor :original_filename, :content_type}
          data.original_filename = self.id.to_s+".png"
          data.content_type = "image/png"

          return data
        end
      end
    end

Here is my heroku log (didn't include base64 string data as it's huge):

2014-04-04T21:30:40.892198+00:00 app[web.1]: Completed 500 Internal Server Error in 31.4ms
2014-04-04T21:30:40.922539+00:00 app[web.1]: 
2014-04-04T21:30:40.922539+00:00 app[web.1]: NoMethodError (undefined method `original_filename' for #<String:0x007fa84e4c8648>):
2014-04-04T21:30:40.922539+00:00 app[web.1]:   app/controllers/groups_controller.rb:91:in `upload_header_img'
2014-04-04T21:30:40.922539+00:00 app[web.1]:   app/controllers/groups_controller.rb:44:in `create'

Any help is massively appreciated. Thanks.

Upvotes: 1

Views: 3037

Answers (1)

rb512
rb512

Reputation: 6948

The problem is with your header_img_url variable:

header_img_url = "/header_img/"[email protected]_s + extension

      # open in binary mode
      File.open("public"+icon_url,'wb') do |file|
      file.write(header_img_io.read)
      end

You changed the variable from icon_url to header_img_url but missed updating this snippet:

File.open("public"+icon_url,'wb') do |file|

Change it to header_img_url and you'll be good.

Also move this code:

header_img = @group.header_img || @group.decode_header_img_data
    if header_img.present?
      upload_header_img(header_img)
    end

after if @group.save in your create action.

Since your @group object is not saved in the database yet, @group.id will be nil and when you call to_s on it, it will return "". Now, your header_img_url is set as "/header_img/public/", which is a directory and you'll end up reading a directory instead of a file.

Upvotes: 1

Related Questions