2006 - Klein, Michael Patrick
2005-Jun-14 02:20 UTC
Uploading Files - The classic problem once again
To all those feeling very charitable today, please read ahead - I need some help! Later this week I am receiving a digital camera and I would love to have a up and running photoblog when it arrives. I''m sure this seems rather self-centered/unimportant/"why should i care?" but never the less I request your help. For months I have struggled with file uploading and have avoided it in any way possible in other simple Rails applications I have written. Now there is no real way to avoid it other than uploading images via an ftp and just submitting the link to this uploaded image for the image_url and embedding that in each view with <img src="<%= @photo.image_url" > or something like that. This seems to completely rebuke my effort in making a dynamic web application. Right now I am at the beginning just trying to upload the file and save it on the filesystem. I know many people favor blobs and the database, but I am very reluctant to store anything but text inside a database. So right now I have a form that uploads the text parts of each photo and the image. I have tried to make a method in the model Photo to save the actual photo file onto the filesystem, then save the text information and its location in the database. I am guessing there is a better way but I am struggling to find one. This is what I have so far. Right now it gives me an error that ''save_photo'' is an undefined method in Photo#create. It seriously isn''t complicated at all, because I am an amateur at Ruby and Rails, but please take a look. I would seriously appreciate anything that you can offer, I am losing my mind over this problem. Right now it looks to me as if I have some serious problems with self.save in photo.rb and there must be something wrong with self.save_photo in photo.rb. If you could help in any way I would appreciate it. I will be frantically checking for updates so I will definitely get back to any answers. photoblog.sql: CREATE TABLE photos ( id int not null auto_increment primary key, title tinytext not null, description text not null, image_url tinytext not null, date_available datetime not null ); photo.rb: class Photo < ActiveRecord::Base def self.save_photo(photo) photo[''image_url''] = sanitize_filename(photo[''image'']) File.open( (File.expand_path(RAILS_ROOT) + "/public/images/#{photo[''image_url'']}"), "wb") { |f| f.write(photo[''image''].read) } end def self.save photo[''image_url''] = sanitize_filename(photo[''image'']) photo.save end private def sanitize_filename(value) #get only the filename, not the whole path just_filename = File.basename(value) #replace all erroneous junk filename = just_filename.gsub(/[^\w\.\-]/,''_'') end end photo_controller.rb: class PhotoController < ApplicationController model :photo def index end def new @photo = Photo.new end def create @photo.save_photo(@params[''photo''][''image'']) if @photo.save redirect_to :action => ''show'', :id => Photo end end end and finally - new.rhtml: <%= form_tag({:action => ''create''}, :multipart => ''true'') %> Title: <%= text_field("photo", "title") %><br /> Description: <%= text_area("photo", "description") %><br /> Image: <%= file_field("photo", "image") %><br /> Date/Time to publish: <%= select_datetime(Time.now, :include_blank => true, :add_month_numbers => 1) %><br /> <%= submit_tag("Upload file") %> <%= end_form_tag %>
You have save_photo defined as a class method (self.save_photo), when you call it, you call it as an instance method (@photo = Photo.new; @photo.save_photo) Get rid of ''self.'' at the beginning of your method definition to make it an instance method. As for you overloading of the save instance method - this will not work -> you need to rename the current save method, write over it, and then call the overridden method. e.g. alias :old_save, :save def save photo[''image_url''] = sanitize_filename(photo[''image'']) old_save end -----Original Message----- From: rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org [mailto:rails-bounces-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org] On Behalf Of 2006 - Klein, Michael Patrick Sent: Tuesday, 14 June 2005 12:20 PM To: rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org Subject: [Rails] Uploading Files - The classic problem once again To all those feeling very charitable today, please read ahead - I need some help! Later this week I am receiving a digital camera and I would love to have a up and running photoblog when it arrives. I''m sure this seems rather self-centered/unimportant/"why should i care?" but never the less I request your help. For months I have struggled with file uploading and have avoided it in any way possible in other simple Rails applications I have written. Now there is no real way to avoid it other than uploading images via an ftp and just submitting the link to this uploaded image for the image_url and embedding that in each view with <img src="<%= @photo.image_url" > or something like that. This seems to completely rebuke my effort in making a dynamic web application. Right now I am at the beginning just trying to upload the file and save it on the filesystem. I know many people favor blobs and the database, but I am very reluctant to store anything but text inside a database. So right now I have a form that uploads the text parts of each photo and the image. I have tried to make a method in the model Photo to save the actual photo file onto the filesystem, then save the text information and its location in the database. I am guessing there is a better way but I am struggling to find one. This is what I have so far. Right now it gives me an error that ''save_photo'' is an undefined method in Photo#create. It seriously isn''t complicated at all, because I am an amateur at Ruby and Rails, but please take a look. I would seriously appreciate anything that you can offer, I am losing my mind over this problem. Right now it looks to me as if I have some serious problems with self.save in photo.rb and there must be something wrong with self.save_photo in photo.rb. If you could help in any way I would appreciate it. I will be frantically checking for updates so I will definitely get back to any answers. photoblog.sql: CREATE TABLE photos ( id int not null auto_increment primary key, title tinytext not null, description text not null, image_url tinytext not null, date_available datetime not null ); photo.rb: class Photo < ActiveRecord::Base def self.save_photo(photo) photo[''image_url''] = sanitize_filename(photo[''image'']) File.open( (File.expand_path(RAILS_ROOT) + "/public/images/#{photo[''image_url'']}"), "wb") { |f| f.write(photo[''image''].read) } end def self.save photo[''image_url''] = sanitize_filename(photo[''image'']) photo.save end private def sanitize_filename(value) #get only the filename, not the whole path just_filename = File.basename(value) #replace all erroneous junk filename = just_filename.gsub(/[^\w\.\-]/,''_'') end end photo_controller.rb: class PhotoController < ApplicationController model :photo def index end def new @photo = Photo.new end def create @photo.save_photo(@params[''photo''][''image'']) if @photo.save redirect_to :action => ''show'', :id => Photo end end end and finally - new.rhtml: <%= form_tag({:action => ''create''}, :multipart => ''true'') %> Title: <%= text_field("photo", "title") %><br /> Description: <%= text_area("photo", "description") %><br /> Image: <%= file_field("photo", "image") %><br /> Date/Time to publish: <%= select_datetime(Time.now, :include_blank => true, :add_month_numbers => 1) %><br /> <%= submit_tag("Upload file") %> <%= end_form_tag %> _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
2006 - Klein, Michael Patrick
2005-Jun-14 03:37 UTC
RE: Uploading Files - The classic problem once again
Wayne Robinson <wayner@...> writes:> > You have save_photo defined as a class method (self.save_photo), when > you call it, you call it as an instance method ( <at> photo = Photo.new; > <at> photo.save_photo) > > Get rid of ''self.'' at the beginning of your method definition to make it > an instance method. As for you overloading of the save instance method - > this will not work -> you need to rename the current save method, write > over it, and then call the overridden method. > > e.g. > > alias :old_save, :save > def save > photo[''image_url''] = sanitize_filename(photo[''image'']) > old_save > end >Thank you for your help. That makes sense to me why I wouldn''t want self.save there, I checked back up with my Rails Beta Book and now I understand the problem with that. I have changed my photo.rb to look like this: class Photo < ActiveRecord::Base def save_photo(photo) photo[''image_url''] = sanitize_filename(photo[''image'']) File.open( (File.expand_path(RAILS_ROOT) + "/public/images/#{photo[''image_url'']}"), "wb") { |f| f.write(photo[''image''].read) } end alias :old_save :save def save photo[''image_url''] = sanitize_filename(photo[''image'']) old_save end private def sanitize_filename(value) #get only the filename, not the whole path just_filename = File.basename(value) #replace all erroneous junk filename = just_filename.gsub(/[^\w\.\-]/,''_'') end end Now that this change has been made I still do not write the file to the hard drive. There continues to be a " NoMethodError in Photo#create" for the "undefined method `save_photo'' for nil:NilClass". I''m still not understanding why this is not able to be found. I added "@photo = Photo.new" into Photo#create but this gives me what looks like a very similar error with the message: "undefined method `[]'' for #<File:C:/DOCUME~1/Michael/LOCALS~1/Temp/CGI3976.2>". I am still trying to work things out and struggle to understand the problem. Testing around some more I commented out the save_photo method call in the photo_controller.rb and it still gave me an error, but this time on the "save" method. It stumbles on the undefined local variable of photo, which I was worried about earlier. I''m not sure what kind of variable to use here, or what to use at all. If I make it an instance variable it gives me the "undefined method `[]'' for nil:NilClass" error again. Using "@params([''photo''][''image_url'']) sanitize_filename(@params([''photo''][''image'']))" gives even worse errors. Thanks for your help so far!
> Now that this change has been made I still do not write the file to the hard > drive. There continues to be a " NoMethodError in Photo#create" for the > "undefined method `save_photo'' for nil:NilClass". I''m still not understanding > why this is not able to be found. I added "@photo = Photo.new" into Photo#create > but this gives me what looks like a very similar error with the message: > "undefined method `[]'' for #<File:C:/DOCUME~1/Michael/LOCALS~1/Temp/CGI3976.2>". > I am still trying to work things out and struggle to understand the problem.You were headed in the right direction with the @photo = Photo.new; you definitely need that in there. The weird error you got there was caused by this: in the controller: @photo.save_photo(@params[''photo''][''image'']) in save_photo: photo[''image_url''] = sanitize_filename(photo[''image'']) You need to change the save_photo call to @photo.save_photo(@params[''photo'']) Tyler
Julian ''Julik'' Tarkhanov
2005-Jun-18 17:51 UTC
Re: Uploading Files - The classic problem once again
On 14-jun-2005, at 16:00, Tyler Kiley wrote:>> Now that this change has been made I still do not write the file >> to the hard >> drive. There continues to be a " NoMethodError in Photo#create" >> for the >> "undefined method `save_photo'' for nil:NilClass". I''m still not >> understanding >> why this is not able to be found. I added "@photo = Photo.new" >> into Photo#create >> but this gives me what looks like a very similar error with the >> message: >> "undefined method `[]'' for #<File:C:/DOCUME~1/Michael/LOCALS~1/ >> Temp/CGI3976.2>". >> I am still trying to work things out and struggle to understand >> the problem. >>The(yet unfinished) aproach I''ve taken for this problem for now - http://rafb.net/paste/results/U6xfGG50.html but you will need to refine it well -- Julian "Julik" Tarkhanov