Using attachment_fu in existing user model with edit/update

Hi all,

I currently have a working development site with the user model already
setup. I did however hold out on user images/avatars until the end and
am now thinking it wasn't such a good idea.

I'm using attachment_fu with imagescience to do the uploads. I have
installed everything and setup a test scaffold following the screencast
at
http://www.rubyplus.org/episodes/31-How-to-upload-images-in-Rails-2-.html
and got that up and running without a problem.

My issue is this:

I have a user model which when a user registers (new/create action) I
want to just set his account up with the least amount of information
(username, email, and password). I don't want the user to worry about
uploading the image at the time of registration. I've been trying to set
up the code so that the user can upload the image when editing his/her
profile but I'm getting different errors even though I'm following the
same logic as the screencast I previously mentioned (same exact editing
code actually). I've also added the necessary fields for the database
fields to the user table. But I've had no luck.

Does attachment_fu only work if you upload the images at the time of
using the new/create actions? There must be a way to make this work by
just editing a user. I'm sure I'm just overlooking something, any help
is appreciated!!

Let me know if there is something else you need to know. Thank you for
your time!

Best regards,
Tony

Tony -

Hi all,

I currently have a working development site with the user model already
setup. I did however hold out on user images/avatars until the end and
am now thinking it wasn't such a good idea.

I'm using attachment_fu with imagescience to do the uploads. I have
installed everything and setup a test scaffold following the screencast
at
http://www.rubyplus.org/episodes/31-How-to-upload-images-in-Rails-2-.html
and got that up and running without a problem.

My issue is this:

I have a user model which when a user registers (new/create action) I
want to just set his account up with the least amount of information
(username, email, and password). I don't want the user to worry about
uploading the image at the time of registration. I've been trying to set
up the code so that the user can upload the image when editing his/her
profile but I'm getting different errors even though I'm following the
same logic as the screencast I previously mentioned (same exact editing
code actually). I've also added the necessary fields for the database
fields to the user table. But I've had no luck.

Does attachment_fu only work if you upload the images at the time of
using the new/create actions? There must be a way to make this work by
just editing a user. I'm sure I'm just overlooking something, any help
is appreciated!!

Let me know if there is something else you need to know. Thank you for
your time!

best to place your images in a separate model.

has_many :images

but best if images has a polymorphic relationship - that way you can add images to other models

Class User < ActiveRecord::Base

   has_many :images, :as => :attacheable, :dependent => :destroy

end

Class Image < ActiveRecord::Base

   belongs_to :attacheable, :polymorphic => true
   has_attachment :storage => :file_system, ...

end

Jodi

Jodi Showers wrote:

Tony -

installed everything and setup a test scaffold following the
uploading the image at the time of registration. I've been trying to
just editing a user. I'm sure I'm just overlooking something, any help
is appreciated!!

Let me know if there is something else you need to know. Thank you for
your time!

best to place your images in a separate model.

has_many :images

but best if images has a polymorphic relationship - that way you can
add images to other models

Class User < ActiveRecord::Base

   has_many :images, :as => :attacheable, :dependent => :destroy

end

Class Image < ActiveRecord::Base

   belongs_to :attacheable, :polymorphic => true
   has_attachment :storage => :file_system, ...

end

Jodi

Hi Jodi,

Thanks for the reply. I tried adding the additional table relationships
as you suggested but I'm getting an error on the user update action:
undefined local variable or method `filename' for #<User:0x2564508>

I have the standard update code in my controller:

def update
    @user = User.find(params[:id])

    respond_to do |format|
      if @user.update_attributes(params[:user])
        flash[:notice] = 'User was successfully updated.'
        format.html { redirect_to(@user) }
        format.xml { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml { render :xml => @user.errors, :status =>
:unprocessable_entity }
      end
    end
  end

and the view code for the upload is:
<%= file_field_tag :uploaded_data %>

Any help is appreciated! Thanks.

-Tony

Hi Tony,
The problem is you're using the user's form and including attributes
of another model in it. I guess your params look like 'user' =>
{ 'name' => 'something', ..., 'filename' => 'image.jpg'}, but filename
is not an attribute of User model but of Image model.

Jodi's tip of creating a separate model has more implications than
just setting up the relationship: You should create a separate
controller for creating the image: In your user's form, surely when he
wants to add an image, he gets to an image upload view. This would
call a create action in the ImageController:
def create # in ImageController, not UserController
  @user = current_user # or User.find(params[:user_id]) if you post
the user_id in the form for the image.
  @image = Image.new(params[:image]) #this is where the filename
attribute gets set
  if @image.save
      @user.image << @image #associate image to the user
      ...
   else
       ...
   end
end

If you prefer to do the association only when the user saves his
profile, you could just pass the image_id back to the form for the
user's profile and then add the association with the UserController
update action. As image_id is an attribute of user, you can just mass-
assign it like you show in @user.update_attributes(params[:user]).

Thanx for jumping in Degee -

Hi Tony,
The problem is you're using the user's form and including attributes
of another model in it. I guess your params look like 'user' =>
{ 'name' => 'something', ..., 'filename' => 'image.jpg'}, but filename
is not an attribute of User model but of Image model.

Jodi's tip of creating a separate model has more implications than
just setting up the relationship: You should create a separate
controller for creating the image: In your user's form, surely when he
wants to add an image, he gets to an image upload view. This would
call a create action in the ImageController:
def create # in ImageController, not UserController
@user = current_user # or User.find(params[:user_id]) if you post
the user_id in the form for the image.
@image = Image.new(params[:image]) #this is where the filename
attribute gets set
if @image.save
     @user.image << @image #associate image to the user
     ...
  else
      ...
  end
end

If you prefer to do the association only when the user saves his
profile, you could just pass the image_id back to the form for the
user's profile and then add the association with the UserController
update action. As image_id is an attribute of user, you can just mass-
assign it like you show in @user.update_attributes(params[:user]).

Jodi Showers wrote:

Tony -

installed everything and setup a test scaffold following the
uploading the image at the time of registration. I've been trying to
just editing a user. I'm sure I'm just overlooking something, any help
is appreciated!!

Let me know if there is something else you need to know. Thank you for
your time!

best to place your images in a separate model.

has_many :images

but best if images has a polymorphic relationship - that way you can
add images to other models

Class User < ActiveRecord::Base

   has_many :images, :as => :attacheable, :dependent => :destroy

end

Class Image < ActiveRecord::Base

   belongs_to :attacheable, :polymorphic => true
   has_attachment :storage => :file_system, ...

end

Jodi

Hi Jodi,

Thanks for the reply. I tried adding the additional table relationships
as you suggested but I'm getting an error on the user update action:
undefined local variable or method `filename' for #<User:0x2564508>

I have the standard update code in my controller:

def update
    @user = User.find(params[:id])

    respond_to do |format|
      if @user.update_attributes(params[:user])
        flash[:notice] = 'User was successfully updated.'
        format.html { redirect_to(@user) }
        format.xml { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml { render :xml => @user.errors, :status =>
:unprocessable_entity }
      end
    end
  end

and the view code for the upload is:
<%= file_field_tag :uploaded_data %>

Any help is appreciated! Thanks.

-Tony
--
Posted viahttp://www.ruby-forum.com/.

I prefer to create images within the (in this case) the UserController.

ripped out of a project

View - <multipart form tag here>

<%= file_field_tag "photo[]", :id => "photo_image", :class => "attach_photo" %>
<%= text_field_tag "caption[]", nil, {:id => "photo_title", :class => "attach_photo"} %>

User controller - after @user object is valid + saved

     #attached uploaded pics - an array of photos + captions
     if params[:photo]
       params[:photo].each_with_index do |image, caption_index|
         caption = ''
         caption = params[:caption][caption_index] if params[:caption] && params[:caption][caption_index]

         @user.images.create!(:uploaded_data => image, :caption => caption) if image.size != 0
       end
     end

Jodi

Jodi Showers wrote:

Thanx for jumping in Degee -

wants to add an image, he gets to an image upload view. This would
      ...

is appreciated!!

add images to other models
   has_attachment :storage => :file_system, ...

undefined local variable or method `filename' for #<User:0x2564508>
        format.xml { head :ok }

Any help is appreciated! Thanks.

-Tony
--
Posted viahttp://www.ruby-forum.com/.

I prefer to create images within the (in this case) the UserController.

ripped out of a project

View - <multipart form tag here>

<%= file_field_tag "photo[]", :id => "photo_image", :class =>
"attach_photo" %>
<%= text_field_tag "caption[]", nil, {:id => "photo_title", :class =>
"attach_photo"} %>

User controller - after @user object is valid + saved

     #attached uploaded pics - an array of photos + captions
     if params[:photo]
       params[:photo].each_with_index do |image, caption_index|
         caption = ''
         caption = params[:caption][caption_index] if params[:caption]
&& params[:caption][caption_index]

         @user.images.create!(:uploaded_data => image, :caption =>
caption) if image.size != 0
       end
     end

Jodi

Thanks for all the help guys.

I finally got back to work after being busy from my day job. I got the
filename situation cleared but now I get the following error:

undefined method `content_type' for
[#<ActionController::UploadedStringIO:0x23f8e1c>, 0]:Array

I'm doing things the "Jodi way". Maybe I'm just tired and can't see the
obvious solution but any advice is really appreciated as always.

And yes, I realize that this info is being spoon fed to me and I STILL
can't get it. Trust me, it's more frustrating to me than it is to anyone
else! :-\

Thanks again all!!!

-Tony

It's a bit difficult to help you without the code here. Looks like
you're not performing the correct assignment in your controller.
content_type is a method that can only be called on a UploadedStringIO
object and somehow you're typecasting it to Array it seems.

Please show us the code for your controller update action and your
edit view. And it also helps to tell us which params are being passed
when you call the action (from your development.log).

Hi Jodi,

Thanks for the reply. I tried adding the additional table relationships
as you suggested but I'm getting an error on the user update action:
undefined local variable or method `filename' for #<User:0x2564508>

I have the standard update code in my controller:

def update
    @user = User.find(params[:id])

    respond_to do |format|
      if @user.update_attributes(params[:user])
        flash[:notice] = 'User was successfully updated.'
        format.html { redirect_to(@user) }
        format.xml { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml { render :xml => @user.errors, :status =>
:unprocessable_entity }
      end
    end
  end

and the view code for the upload is:
<%= file_field_tag :uploaded_data %>

Any help is appreciated! Thanks.

-Tony

I know this is an old post, but I was trying to find the solution to:
undefined local variable or method `filename'
and I arrived here.

I got this error because I made a mistake creating the table. I used
"file_name" instead of "filename". Changing this solved the problem for
me.

Cheers
Aukan