I''m developing a site that contains houses. Each house contains one main image, and a couple additional images. I''m having difficulties coming up with the correct way to let the user create new houses and upload the multiple images. I have an image table in the database, containing columns for id, filename, and the binary picture. I have a corresponding controller for this image table. Now, how should I do the AR modeling? Each house belongs_to an image (the main image), but then each house also is related to multiple images. And I''m also having problems with how to detect whether the user has uploaded one or more image and how to correctly insert them into the database. I can do it fine if just one image is associated with a house (and insert the image data directly into the house table), but struggling with multiple images associated with a house. Thanks, Joe
I have a very similar situation in an app I''m building. I have parts (like for machinery) and part_images tables. a PartImage belongs_to :part and a Part belongs_to :part_image and has_many :part_images. That way I can get at the primary image using Part#image and all images (including primary) using Part#images. Look at the file upload howto on the Wiki. If you use a multipart form, you can include as many files as you want (within reason). If you need to insert lots from one page, you can make a little javascript that adds fields to a table/div and name them, for instance, image[0], image[1], image[2], etc. And then pull them out of your hash in the controller and do whatever you need to them. There''s probably a better naming scheme out there if you think about it a little bit with reference to your app/model, but that will work. If you use that approach, then @params[''image''] will be a hash associating "1","2","3",etc. with the form data (temfile objects, etc.) associated with those upload fields. Regards, Brian On Thu, 17 Feb 2005 19:01:12 -0800, Joe Van Dyk <joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I''m developing a site that contains houses. > > Each house contains one main image, and a couple additional images. > > I''m having difficulties coming up with the correct way to let the user > create new houses and upload the multiple images. > > I have an image table in the database, containing columns for id, > filename, and the binary picture. I have a corresponding controller > for this image table. > > Now, how should I do the AR modeling? Each house belongs_to an image > (the main image), but then each house also is related to multiple > images. > > And I''m also having problems with how to detect whether the user has > uploaded one or more image and how to correctly insert them into the > database. > > I can do it fine if just one image is associated with a house (and > insert the image data directly into the house table), but struggling > with multiple images associated with a house. > > Thanks, > Joe > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- The years ahead pick up their dark bags. They move closer. There''s a slight rise in the silence then nothing. -- (If you''re receiving this in response to mail sent to bluczkie-OM76b2Iv3yLQjUSlxSEPGw@public.gmane.org, don''t be concerned This is my new address, but mail will be forwarded here indefinitely)
On 18/02/2005, at 2:01 PM, Joe Van Dyk wrote:> Now, how should I do the AR modeling? Each house belongs_to an image > (the main image), but then each house also is related to multiple > images.Shouldn''t it be something more like: class House < ActiveRecord::Base has_one :main_image, :class_name => "Image" has_and_belongs_to_many :images end class Image < ActiveRecord::Base belongs_to :house end -- tim lucas
On Fri, 18 Feb 2005 15:15:09 +1100, Tim Lucas <t.lucas-l/qNJNvq70OzaBltdDZI6w@public.gmane.org> wrote:> On 18/02/2005, at 2:01 PM, Joe Van Dyk wrote: > > Now, how should I do the AR modeling? Each house belongs_to an image > > (the main image), but then each house also is related to multiple > > images. > > Shouldn''t it be something more like: > > class House < ActiveRecord::Base > has_one :main_image, :class_name => "Image" > has_and_belongs_to_many :images > end > > class Image < ActiveRecord::Base > belongs_to :house > end > > -- tim lucasShould it be? I''m all confused now.
On Thu, 17 Feb 2005 22:28:03 -0500, Brian L. <zorander-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I have a very similar situation in an app I''m building. I have parts > (like for machinery) and part_images tables. a PartImage belongs_to > :part and a Part belongs_to :part_image and has_many :part_images. > That way I can get at the primary image using Part#image and all > images (including primary) using Part#images. > > Look at the file upload howto on the Wiki. If you use a multipart > form, you can include as many files as you want (within reason). If > you need to insert lots from one page, you can make a little > javascript that adds fields to a table/div and name them, for > instance, image[0], image[1], image[2], etc. And then pull them out of > your hash in the controller and do whatever you need to them. There''s > probably a better naming scheme out there if you think about it a > little bit with reference to your app/model, but that will work. > > If you use that approach, then @params[''image''] will be a hash > associating "1","2","3",etc. with the form data (temfile objects, > etc.) associated with those upload fields. > > Regards, > > Brian >Thanks! I went with a scheme like this. I''ve got the main image working fine, but I''m having problems getting the additional images in the database. Any chance you could post the relevant part of your controller that does this? Thanks, Joe> > On Thu, 17 Feb 2005 19:01:12 -0800, Joe Van Dyk <joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > I''m developing a site that contains houses. > > > > Each house contains one main image, and a couple additional images. > > > > I''m having difficulties coming up with the correct way to let the user > > create new houses and upload the multiple images. > > > > I have an image table in the database, containing columns for id, > > filename, and the binary picture. I have a corresponding controller > > for this image table. > > > > Now, how should I do the AR modeling? Each house belongs_to an image > > (the main image), but then each house also is related to multiple > > images. > > > > And I''m also having problems with how to detect whether the user has > > uploaded one or more image and how to correctly insert them into the > > database. > > > > I can do it fine if just one image is associated with a house (and > > insert the image data directly into the house table), but struggling > > with multiple images associated with a house. > > > > Thanks, > > Joe > > _______________________________________________ > > Rails mailing list > > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > > http://lists.rubyonrails.org/mailman/listinfo/rails > > > > -- > The years ahead pick up their dark bags. > They move closer. There''s a slight rise in the silence > > then nothing. > -- > (If you''re receiving this in response to mail sent to > bluczkie-OM76b2Iv3yLQjUSlxSEPGw@public.gmane.org, don''t be concerned This is my new address, > but mail will be forwarded here indefinitely) >
On Thu, 17 Feb 2005 20:53:52 -0800, Joe Van Dyk <joevandyk@gmail.com> wrote:> On Thu, 17 Feb 2005 22:28:03 -0500, Brian L. <zorander@gmail.com> wrote: > > I have a very similar situation in an app I''m building. I have parts > > (like for machinery) and part_images tables. a PartImage belongs_to > > :part and a Part belongs_to :part_image and has_many :part_images. > > That way I can get at the primary image using Part#image and all > > images (including primary) using Part#images. > > > > Look at the file upload howto on the Wiki. If you use a multipart > > form, you can include as many files as you want (within reason). If > > you need to insert lots from one page, you can make a little > > javascript that adds fields to a table/div and name them, for > > instance, image[0], image[1], image[2], etc. And then pull them out of > > your hash in the controller and do whatever you need to them. There''s > > probably a better naming scheme out there if you think about it a > > little bit with reference to your app/model, but that will work. > > > > If you use that approach, then @params[''image''] will be a hash > > associating "1","2","3",etc. with the form data (temfile objects, > > etc.) associated with those upload fields. > > > > Regards, > > > > Brian > > > > Thanks! I went with a scheme like this. I''ve got the main image > working fine, but I''m having problems getting the additional images in > the database. > > Any chance you could post the relevant part of your controller that does this? > > Thanks, > Joe >Here''s my save method, in it''s entirety. Please laugh at it and make suggestions. Currently, the main picture is being saved in the Image table correctly, but the additional pictures are not. This function works for both adding and saving a house. Also currently, I haven''t come up with a good scheme of how to avoid overwriting photos (say the user created a new house and uploaded pictures of it, but then decided that he wanted to edit the house later -- I don''t want to erase the old pictures, unless he provided new ones). Also, amenities is a has_and_belongs_to_many relationship. That''s the best way I could think of to do it. def save @house = House.find_first "id = ''#{@params["house"]["id"]}''" if @house == nil # create a new house @house = House.new end # saved until after we save the house, need to get the image out # of @param image_filename @params[''house''][''image''].original_filename.gsub(/[^a-zA-Z0-9.]/, ''_'') image_data = @params[''house''][''image''].read @params[''house''].delete(''image'') @house.attributes = @params["house"] if @house.save @house.amenities.clear @house.amenities << Amenity.find(@params["amenities"]) if @params["amenities"] if @params[''house''][''image''] != "" @house.image = Image.new @house.image.filename = image_filename @house.image.data = image_data @house.image.save @house.image_id = @house.image.id @house.save end @house.images.clear images_array = [] 1.upto(5) do |i| if @params[''images''][i.to_s] image_filename @params[''images''][i.to_s].original_filename.gsub(/[^a-zA-Z0-9.]/, ''_'') image_data = @params[''images''][i.to_s].read image = Image.new image.data = image_data image.filename = image_filename images_array << image end end #@house.images << image_array flash["notice"] = "House Saved" redirect_to(:action => "display", :id => @house.id) else flash["notice"] = "Could not save house" end end
On 18/02/2005, at 3:51 PM, Joe Van Dyk wrote:> On Fri, 18 Feb 2005 15:15:09 +1100, Tim Lucas <t.lucas@toolmantim.com> > wrote: >> On 18/02/2005, at 2:01 PM, Joe Van Dyk wrote: >>> Now, how should I do the AR modeling? Each house belongs_to an image >>> (the main image), but then each house also is related to multiple >>> images. >> >> Shouldn''t it be something more like: >> >> class House < ActiveRecord::Base >> has_one :main_image, :class_name => "Image" >> has_and_belongs_to_many :images >> end >> >> class Image < ActiveRecord::Base >> belongs_to :house >> end >> >> -- tim lucas > > Should it be? I''m all confused now.Well AFAIK this would lead to a DB structure like: TABLE house { id image_id # for the main_image association } TABLE houses_images { house_id image_id } TABLE image { id house_id } -- tim lucas http://www.toolmantim.com
On 18.2.2005, at 07:02, Tim Lucas wrote:> On 18/02/2005, at 3:51 PM, Joe Van Dyk wrote: >> On Fri, 18 Feb 2005 15:15:09 +1100, Tim Lucas >> <t.lucas-l/qNJNvq70OzaBltdDZI6w@public.gmane.org> wrote: >>> On 18/02/2005, at 2:01 PM, Joe Van Dyk wrote: >>>> Now, how should I do the AR modeling? Each house belongs_to an >>>> image >>>> (the main image), but then each house also is related to multiple >>>> images. >>> >>> Shouldn''t it be something more like: >>> >>> class House < ActiveRecord::Base >>> has_one :main_image, :class_name => "Image" >>> has_and_belongs_to_many :images >>> end >>> >>> class Image < ActiveRecord::Base >>> belongs_to :house >>> end >>> >>> -- tim lucas >> >> Should it be? I''m all confused now.There''s no need for this if one image can only belong to one house. I think in Joe''s current situation a has_many - belongs_to relationship (one-to-many) is quite enough, since the file upload process is always tied to a single house. The Brian''s scheme Joe went with is just fine. //jarkko> > Well AFAIK this would lead to a DB structure like: > > TABLE house { > id > image_id # for the main_image association > } > > TABLE houses_images { > house_id > image_id > } > > TABLE image { > id > house_id > } > > -- tim lucas > > http://www.toolmantim.com > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Jarkko Laine http://jlaine.net http://odesign.fi _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails
what''s the advantage of storing pictures in the DB itself? Why not store it on the filesystem (which is optimised for storing such data)? (The oly advantage I could see is that it is available from a server, but a filesystem can be shared on the netword too). Please enlighten me. Thanks. Raph On Thu, 17 Feb 2005 21:00:27 -0800, Joe Van Dyk <joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Thu, 17 Feb 2005 20:53:52 -0800, Joe Van Dyk <joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > On Thu, 17 Feb 2005 22:28:03 -0500, Brian L. <zorander-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > I have a very similar situation in an app I''m building. I have parts > > > (like for machinery) and part_images tables. a PartImage belongs_to > > > :part and a Part belongs_to :part_image and has_many :part_images. > > > That way I can get at the primary image using Part#image and all > > > images (including primary) using Part#images. > > > > > > Look at the file upload howto on the Wiki. If you use a multipart > > > form, you can include as many files as you want (within reason). If > > > you need to insert lots from one page, you can make a little > > > javascript that adds fields to a table/div and name them, for > > > instance, image[0], image[1], image[2], etc. And then pull them out of > > > your hash in the controller and do whatever you need to them. There''s > > > probably a better naming scheme out there if you think about it a > > > little bit with reference to your app/model, but that will work. > > > > > > If you use that approach, then @params[''image''] will be a hash > > > associating "1","2","3",etc. with the form data (temfile objects, > > > etc.) associated with those upload fields. > > > > > > Regards, > > > > > > Brian > > > > > > > Thanks! I went with a scheme like this. I''ve got the main image > > working fine, but I''m having problems getting the additional images in > > the database. > > > > Any chance you could post the relevant part of your controller that does this? > > > > Thanks, > > Joe > > > > Here''s my save method, in it''s entirety. Please laugh at it and make > suggestions. Currently, the main picture is being saved in the Image > table correctly, but the additional pictures are not. This function > works for both adding and saving a house. Also currently, I haven''t > come up with a good scheme of how to avoid overwriting photos (say the > user created a new house and uploaded pictures of it, but then decided > that he wanted to edit the house later -- I don''t want to erase the > old pictures, unless he provided new ones). > > Also, amenities is a has_and_belongs_to_many relationship. That''s the > best way I could think of to do it. > > def save > @house = House.find_first "id = ''#{@params["house"]["id"]}''" > if @house == nil > # create a new house > @house = House.new > end > > # saved until after we save the house, need to get the image out > # of @param > image_filename > > @params[''house''][''image''].original_filename.gsub(/[^a-zA-Z0-9.]/, ''_'') > image_data = @params[''house''][''image''].read > @params[''house''].delete(''image'') > > @house.attributes = @params["house"] > > if @house.save > @house.amenities.clear > @house.amenities << Amenity.find(@params["amenities"]) if > @params["amenities"] > > if @params[''house''][''image''] != "" > @house.image = Image.new > @house.image.filename = image_filename > @house.image.data = image_data > @house.image.save > @house.image_id = @house.image.id > @house.save > end > > @house.images.clear > images_array = [] > 1.upto(5) do |i| > if @params[''images''][i.to_s] > image_filename > > @params[''images''][i.to_s].original_filename.gsub(/[^a-zA-Z0-9.]/, ''_'') > image_data = @params[''images''][i.to_s].read > image = Image.new > image.data = image_data > image.filename = image_filename > images_array << image > end > end > #@house.images << image_array > flash["notice"] = "House Saved" > redirect_to(:action => "display", :id => @house.id) > else > flash["notice"] = "Could not save house" > end > > end > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
On Fri, 18 Feb 2005 15:30:09 +0100, Raphael Bauduin <rblists-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> what''s the advantage of storing pictures in the DB itself? > Why not store it on the filesystem (which is optimised for storing such data)? > (The oly advantage I could see is that it is available from a server, > but a filesystem can be shared on the netword too). > > Please enlighten me. > > Thanks. > > Raph > >Hi, There''s tradeoffs to storing files in the DB and on the filesystem. I''ll list the pros/cons of storing them in the DB from my perspective. Pros: Easy backup -- all site data is in one place No permission issues Don''t have to do any filename tricks to store images Cons: Could be slower -- but the sites I''m make don''t get 1000 hits a second (yet) Maybe somewhat more tricky to store/load files into the DB Logs become ugly -- how can I fix this?
On 19/02/2005, at 1:36 AM, Joe Van Dyk wrote:> There''s tradeoffs to storing files in the DB and on the filesystem. > I''ll list the pros/cons of storing them in the DB from my perspective. > > Pros: > Easy backup -- all site data is in one place > No permission issues > Don''t have to do any filename tricks to store imagesAlso another major pro is the free transaction support. - tim lucas
On Sat, 19 Feb 2005 02:03:40 +1100, Tim Lucas <t.lucas-l/qNJNvq70OzaBltdDZI6w@public.gmane.org> wrote:> On 19/02/2005, at 1:36 AM, Joe Van Dyk wrote: > > There''s tradeoffs to storing files in the DB and on the filesystem. > > I''ll list the pros/cons of storing them in the DB from my perspective. > > > > Pros: > > Easy backup -- all site data is in one place > > No permission issues > > Don''t have to do any filename tricks to store images > > Also another major pro is the free transaction support. > > - tim lucas >Can you expand on this? You mean if two people try to modify/delete the file at the same time?>
On Thu, 17 Feb 2005 21:00:27 -0800, Joe Van Dyk <joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Thu, 17 Feb 2005 20:53:52 -0800, Joe Van Dyk <joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > On Thu, 17 Feb 2005 22:28:03 -0500, Brian L. <zorander-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > I have a very similar situation in an app I''m building. I have parts > > > (like for machinery) and part_images tables. a PartImage belongs_to > > > :part and a Part belongs_to :part_image and has_many :part_images. > > > That way I can get at the primary image using Part#image and all > > > images (including primary) using Part#images. > > > > > > Look at the file upload howto on the Wiki. If you use a multipart > > > form, you can include as many files as you want (within reason). If > > > you need to insert lots from one page, you can make a little > > > javascript that adds fields to a table/div and name them, for > > > instance, image[0], image[1], image[2], etc. And then pull them out of > > > your hash in the controller and do whatever you need to them. There''s > > > probably a better naming scheme out there if you think about it a > > > little bit with reference to your app/model, but that will work. > > > > > > If you use that approach, then @params[''image''] will be a hash > > > associating "1","2","3",etc. with the form data (temfile objects, > > > etc.) associated with those upload fields. > > > > > > Regards, > > > > > > Brian > > > > > > > Thanks! I went with a scheme like this. I''ve got the main image > > working fine, but I''m having problems getting the additional images in > > the database. > > > > Any chance you could post the relevant part of your controller that does this? > > > > Thanks, > > Joe > > > > Here''s my save method, in it''s entirety. Please laugh at it and make > suggestions. Currently, the main picture is being saved in the Image > table correctly, but the additional pictures are not. This function > works for both adding and saving a house. Also currently, I haven''t > come up with a good scheme of how to avoid overwriting photos (say the > user created a new house and uploaded pictures of it, but then decided > that he wanted to edit the house later -- I don''t want to erase the > old pictures, unless he provided new ones). > > Also, amenities is a has_and_belongs_to_many relationship. That''s the > best way I could think of to do it. ><my bad code snipped> I would love to see more examples of how other people do multiple file uploads that are associated with some object. If I get an idea of a good way to do this, I''ll update the FileUpload section in the Howtos.
I believe he''s referring to the fact that you can wrap transactional logic around it, so unless the file upload stores completely (and appropriately) in the database, the house won''t store and vice-versa. Just helps with data integrity when using multiple tables to start information related to a single idea. On Fri, 18 Feb 2005 07:14:02 -0800, Joe Van Dyk <joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Sat, 19 Feb 2005 02:03:40 +1100, Tim Lucas <t.lucas-l/qNJNvq70OzaBltdDZI6w@public.gmane.org> wrote: > > On 19/02/2005, at 1:36 AM, Joe Van Dyk wrote: > > > There''s tradeoffs to storing files in the DB and on the filesystem. > > > I''ll list the pros/cons of storing them in the DB from my perspective. > > > > > > Pros: > > > Easy backup -- all site data is in one place > > > No permission issues > > > Don''t have to do any filename tricks to store images > > > > Also another major pro is the free transaction support. > > > > - tim lucas > > > > Can you expand on this? You mean if two people try to modify/delete > the file at the same time? > > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
On 19/02/2005, at 2:56 AM, Ben Schumacher wrote:> I believe he''s referring to the fact that you can wrap transactional > logic around it, so unless the file upload stores completely (and > appropriately) in the database, the house won''t store and vice-versa. > Just helps with data integrity when using multiple tables to start > information related to a single idea. > > On Fri, 18 Feb 2005 07:14:02 -0800, Joe Van Dyk <joevandyk-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > wrote: >> Can you expand on this? You mean if two people try to modify/delete >> the file at the same time?Yep, I was just referring to data integrity -- that your data is not created/deleted/modified in an undesired way (whilst also staying platform agnostic). - tim lucas