0

I've just started to learn Ruby and Ruby on Rails, and this is actually the first time I really have to ask a question on SO, is really making me mad.

I'm programming a REST api where I need to receive an image url and store it in my db.

For this, I've done a model called ImageSet that uses carrierwave to store the uploaded images like this:

class ImageSet < ActiveRecord::Base
  has_one :template

  mount_uploader :icon1, Icon1Uploader
  mount_uploader :icon2, Icon2Uploader

  def icon1=(url)
    super(url)
    self.remote_icon1_url = url
  end

  def icon2=(url)
    super(url)
    self.remote_icon2_url = url
  end
end

This icon1 and icon2 are both received as urls, hence the setter override, and they can't be null. My uploader classes are creating some versions with a whitelist of extensions and a override of full_name.

Then, I have this template class that receives nested attributes for ImageSet.

class Template < ActiveRecord::Base
  belongs_to :image_set

  accepts_nested_attributes_for :image_set

  (other stuff)

  def image_set 
    super || build_image_set
  end
end

This model has a image_set_id that can't be null.

Considering a simple request, like a post with a json:

   {
   "template":
      {
      "image_set_attributes":
         {
         "icon1": "http....",
         "icon2": "http...."
         }
      }
   }

It gives always : ImageSet can't be blank.

I can access temp.image_set from the console,if temp is a Template, and I can set values there too, like, temp.image_set.icon = 'http...' but I can't seem to figure out why is it breaking there. It should create the image_set, set its attributes a save it for the template class, which would assign its id to the respective column in its own model-

My controller is doing:

(...)
def create
 @template = Template.create(params)
 if @template
   render status: 200
 else
   render status: 422
 end
end

private

def params
 params.require(:template).permit(image_set_attributes: [:id, :icon1, :icon2])
end
(...)

Hope you can give me tip on this one.

Thanks!

Afonso Tsukamoto
  • 1,184
  • 1
  • 12
  • 21
  • as far as i can see, you permit parameters including :id but you are not send it with json request, can this give you empty params hash and => empty ImageSet instance? – okliv Sep 03 '13 at 17:25
  • @okliv,that would be right, if permit would stop the attributes from going to create due to a 'not present' error. But that is not the case, since it is permitted, it allows it to be passed when is present on the hash, but once you save it, it will be changed for its real value from the db. So why is it there? Cause, since its a CRUD, I want to allow it for updates, which are necessary for identifying the model to change. Thanks for your comment, though. – Afonso Tsukamoto Sep 04 '13 at 11:30

1 Answers1

0
  1. accepts_nested_attributes doesn't work as expected with belongs_to.

    It can be tricked into working in certain circumstances, but you're better off changing your application elsewhere to do things the "rails way."

  2. Templates validate_presence_of :image_set, right? If so, the problem is that this means ImageSets must always be created before their Templates, but accepts_nested_attributes thinks Template is the parent, and is trying to save the parent first.

    The simplest thing you can do is switch the relationship, so Template has_one :image_set, and ImageSet belongs_to :template. Otherwise you're going to have to write some rather odd controller logic to deal with the params as expected.

Community
  • 1
  • 1
Taavo
  • 2,406
  • 1
  • 17
  • 17
  • not always - http://stackoverflow.com/questions/1313149/getting-fields-for-and-accepts-nested-attributes-for-to-work-with-a-belongs-to-r/2441463#2441463 - see most popular answer – okliv Sep 05 '13 at 14:45