0

I want to save images from a url via a form that populates a "Select" field with a number of options. When the form is submitted, the selected image should be saved with the Paperclip gem.

Here is the html select code block:

<select id="story_medium" name="story[medium]">
    <option data-img-src="http://www.somedomain.com/image0.jpg" value="0">http://www.somedomain.com/image0.jpg</option>
    <option data-img-src="http://www.somedomain.com/image1.jpg" value="1">http://www.somedomain.com/image1.jpg</option>
    <option data-img-src="http://www.somedomain.com/image2.jpg" value="2">http://www.somedomain.com/image2.jpg</option>
</select>

The problem is that when I set the form input as you would usually do with Paperclip, in this case as ":medium", I get an error that says "ActiveRecord::AssociationTypeMismatch at /stories Medium expected, got String". This seems to be because I am passing the option value as a string, rather than an integer.

Parameters: { "story"=>
    {"url"=>"http://www.somedomain.com/image2.jpg", 
    "title"=>"Title of Image", 
    "medium"=>"2", 
    "commit"=>"Submit"}

If I change ":medium" to ":medium_id", the form saves without an error, however, only the key value is saved, and Paperclip does not save the image from the specified url.

How can I pass the value of the image url in the form action so that it properly saves with Paperclip?

Rails 4.1.8, Paperclip 4.2.1, ruby 2.1.5p273

alphaleonis
  • 1,329
  • 11
  • 18

2 Answers2

0

Select list pass the value corresponding the selected option. So you first need to change those as :

<select id="story_medium" name="story[medium]">
    <option data-img-src="http://www.somedomain.com/image0.jpg" value="http://www.somedomain.com/image0.jpg">image0.jpg</option>
    //.. same for all.
</select>

Now inside the controller.

class StoryController < ApplicationController
  # ... code
  before_action :set_current_story
  after_action :set_image, only: [ :update, :create ] 

  def create
    # ..
  end

  private

  def set_image
    @story.picture = open(story_create_params[:medium])
    @story.save!
  end

  def story_create_params
    params.require(:story).permit(:medium)
  end

  def set_current_story
    @story = Story.find params[:id]
  end
end
Arup Rakshit
  • 116,827
  • 30
  • 260
  • 317
  • This looks promising..but now I'm seeing "undefined local variable or method `params' for # – alphaleonis Jun 04 '15 at 18:54
  • wait...forgot to change the value to the url – alphaleonis Jun 04 '15 at 18:56
  • @alphaleonis see now! – Arup Rakshit Jun 04 '15 at 18:57
  • @R_O_R you took `params` into the model. It won't work that way. At that point it's `self.picture = open(medium)` – rkamun1 Jun 04 '15 at 18:57
  • If I change the value to the url, I get "Medium expected, got String" error – alphaleonis Jun 04 '15 at 18:59
  • Thanks to the both of you for helping with this. I have to step away from this for a few hours, but I'll look at it again this evening and see if I can get it going with your suggestions. – alphaleonis Jun 04 '15 at 19:03
  • @R_O_R I'm curious, why would you do it in the controller rather than in the model thus removing the code from the controller into the model? – rkamun1 Jun 04 '15 at 19:07
  • I had to remove the set_current_story method, and I'm still getting the same error that says "Medium expected, got String". I removed the method because I was getting an error that said, "Couldn't find Story without an ID". As far as I understand it, there is no id yet, because the story won't be created until the form is submitted. – alphaleonis Jun 05 '15 at 06:50
  • @SirBertly - how would you suggest doing this differently in the model? – alphaleonis Jun 05 '15 at 06:55
  • @alphaleonis can you show me your project if possible ? – Arup Rakshit Jun 05 '15 at 06:58
  • Sure. What do you want to see? Does this help... http://stackoverflow.com/questions/30630601/how-do-i-save-images-via-options-for-select-with-paperclip-and-image-picker-on-r – alphaleonis Jun 05 '15 at 07:02
  • @alphaleonis I think I can't help as it is a lot of code which need debugging with data.. Only looking at the code like yours and giving advice is hard for me.. – Arup Rakshit Jun 05 '15 at 07:10
  • I get that - I appreciate you taking the time to help me along so far. I was hoping it was something easy I was just overlooking. It seems like Rails doesn't like when you pass the value option as anything but an integer, and paperclip doesn't like the integer. Maybe there's more to it. – alphaleonis Jun 05 '15 at 07:17
  • @alphaleonis it seems you messed up with 2 different ways.. You used there `accept_nested_atrributes_.` with some other technique... BTW, I am open to get hire for part time ROR job if any you have to offer.. – Arup Rakshit Jun 05 '15 at 07:19
0

Looks like you're not making use of paperclip. Do you have your has_attached_file :url in the model? Once that part is set up, you'll probably need a setter which means

#setter
def url_path=(val)
 url = File.open(val)
end

#getter
def url_path
 self.url
end

Then your form will look something like

<select id="story_medium_url_path" name="story[medium][url_path]">
    <option data-img-src="http://www.somedomain.com/image0.jpg" value="http://www.somedomain.com/image0.jpg">image0.jpg</option>
    //.. same for all.
</select>

And in your controller, white-list :url_path

rkamun1
  • 338
  • 1
  • 2
  • 15
  • @alphaleonis this is what I was talking about. – rkamun1 Jun 05 '15 at 11:14
  • I think I have everything set up properly, but I'm getting "undefined method 'url' for # – alphaleonis Jun 10 '15 at 06:11
  • Success! I was able to get this working using your suggestion, with some modification. Turns out I didn't need the `#getter` method. I also added `require "open-uri"` to the model and changed the setter method to `self.image = open(val)`. – alphaleonis Jun 11 '15 at 19:33
  • Fantastic! I'm glad I could point you in the right direction. The getter method is used when you want to display the image in the form. ie; `f.url_path`. This is only if you want to display it in the form in a DRY manner. Please upvote post or mark as correct if you find it satisfactory of such an action. :-) – rkamun1 Jun 14 '15 at 15:37