I have two problems. I have a comment that has_many uploads. Before saving the comment, I want to be sure that the upload(s) has passed validation, but I also need to validate in other ways. For example, I do not want to save the comment if there is no comment or upload. Or, I do not want to save the comment if the image has been uploaded previously (comparing md5s with past upload md5s within the scope of an IP). Previously I had all of the upload attributes combined with my Comments table, which made validation extremely easy. Then when I decided that I would allow multiple uploads per comment, I had to separate the uploads and comments into two different tables, which created the problems I am describing. Models ------ class Comment < ActiveRecord::Base belongs_to :board has_many :uploads, :dependent => :destroy end class Upload < ActiveRecord::Base belongs_to :comment end Controller ---------- def index if request.post? comment = @board.comments.build(params[:comment]) if comment.save upload = comment.uploads.create(params[:upload]) redirect_to "/#{@board.path}" end end end -- Posted via http://www.ruby-forum.com/.
In fact, how the hell am I supposed even theoretically pull this off? The image needs to reference the comment it belongs to during its validation. However, I cannot reference the comment until the comment is saved. But I should not save the comment until the image is validated. Catch 22. Maybe my entire way of going about this is incorrect. -- Posted via http://www.ruby-forum.com/.
Try validates_associated http://api.rubyonrails.com/classes/ActiveRecord/Validations/ ClassMethods.html#M000820 - dan -- Dan Kohn <mailto:dan@dankohn.com> <http://www.dankohn.com/> <tel:+1-415-233-1000> On Jul 22, 2006, at 6:29 PM, Eleo wrote:> In fact, how the hell am I supposed even theoretically pull this off? > > The image needs to reference the comment it belongs to during its > validation. However, I cannot reference the comment until the comment > is saved. But I should not save the comment until the image is > validated. Catch 22. > > Maybe my entire way of going about this is incorrect. > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
I looked at that, but I didn''t really understand it. For example, what if my validation of the Upload object involves looking at the Comment object? I can''t do it, as far as I know, since te association isn''t real until the Comment object is saved and has an ID. So if I need to look at any of the Comment object''s attributes within the Upload model I cannot, since I haven''t saved the Comment object. Dan Kohn wrote:> Try validates_associated > http://api.rubyonrails.com/classes/ActiveRecord/Validations/ > ClassMethods.html#M000820 > > - dan > -- > Dan Kohn <mailto:dan@dankohn.com> > <http://www.dankohn.com/> <tel:+1-415-233-1000>-- Posted via http://www.ruby-forum.com/.
The way to get a feel for this is to create your models, and then run script/console. From there. you can create your objects, and try different combinations of method names to see what works. This will give you the realtime insight into how Rails deals with attributes which you can then use for writing your custom validation. - dan -- Dan Kohn <mailto:dan@dankohn.com> <http://www.dankohn.com/> <tel:+1-415-233-1000> On Jul 22, 2006, at 7:39 PM, Eleo wrote:> I looked at that, but I didn''t really understand it. > > For example, what if my validation of the Upload object involves > looking > at the Comment object? I can''t do it, as far as I know, since te > association isn''t real until the Comment object is saved and has an > ID. > So if I need to look at any of the Comment object''s attributes within > the Upload model I cannot, since I haven''t saved the Comment object. > > Dan Kohn wrote: >> Try validates_associated >> http://api.rubyonrails.com/classes/ActiveRecord/Validations/ >> ClassMethods.html#M000820 >> >> - dan >> -- >> Dan Kohn <mailto:dan@dankohn.com> >> <http://www.dankohn.com/> <tel:+1-415-233-1000> > > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails
I cannot find any documentation on this sort of thing. It seems like an unsaved object does not have an ID when it is built; but at some point between when it is created and saved it gains one. Associations don''t work properly until it has one. My Upload object doesn''t know which Comment object it belongs to until Comment has an ID number; and again, I don''t want to save EITHER object until BOTH are validated, which has led to a headache indeed. I cannot reference an associated comment from my Upload model within the before_validation_on_create method, but I CAN do so within the before_create method. Right now I have something sort-of-working. What I have is like this. I have changed my forms so that my file field is comment[upload] instead of upload[upload]: class Comment < ActiveRecord::Base belongs_to :board has_many :uploads, :dependent => :destroy acts_as_tree :order => "created_on ASC", :dependent => :destroy validates_associated :uploads def upload=(upload) uploads.build({:upload => upload}) if upload.size > 0 end end That catches the uploaded file and sends it to the Upload model -> class Upload < ActiveRecord::Base belongs_to :comment def upload=(upload) @upload = upload end def before_validation_on_create create_image end def create_image #this is some RMagick nonsese. end def before_create @thumbnail = ImageList.new.from_blob(@image.first.to_blob) if !comment.parent_id x = comment.board.setting(:parent_thumbnail_at_width) y = comment.board.setting(:parent_thumbnail_at_height) else x = comment.board.setting(:reply_thumbnail_at_width) y = comment.board.setting(:reply_thumbnail_at_height) end self[:thumbnail_width] = @thumbnail.columns self[:thumbnail_height] = @thumbnail.rows if @thumbnail.columns > x or @thumbnail.rows > y @thumbnail.change_geometry!("#{x}x#{y}") {|cols, rows, img| img.resize!(cols, rows)} end end end As you can see, it was imortant that I could reference the associated comment, because that determined the size of the thumbnail, which I needed to save to the uploads table. So I''m closer than when I was before; but still have a long way to go. For example, I''m only dealing with one uploaded file at a time, when I need to be dealing with multiple uploads :( -- Posted via http://www.ruby-forum.com/.
If you do comment.valid? (and ignore the results), are you then able to do the validations you want? - dan -- Dan Kohn <mailto:dan@dankohn.com> <http://www.dankohn.com/> <tel:+1-415-233-1000> On Jul 22, 2006, at 9:45 PM, Eleo wrote:> I cannot find any documentation on this sort of thing. > > It seems like an unsaved object does not have an ID when it is built; > but at some point between when it is created and saved it gains one. > Associations don''t work properly until it has one. My Upload object > doesn''t know which Comment object it belongs to until Comment has > an ID > number; and again, I don''t want to save EITHER object until BOTH are > validated, which has led to a headache indeed. > > I cannot reference an associated comment from my Upload model > within the > before_validation_on_create method, but I CAN do so within the > before_create method. Right now I have something sort-of-working. > What > I have is like this. I have changed my forms so that my file field is > comment[upload] instead of upload[upload]: > > class Comment < ActiveRecord::Base > belongs_to :board > has_many :uploads, :dependent => :destroy > acts_as_tree :order => "created_on ASC", :dependent => > :destroy > validates_associated :uploads > > def upload=(upload) > uploads.build({:upload => upload}) if upload.size > 0 > end > end > > That catches the uploaded file and sends it to the Upload model -> > class Upload < ActiveRecord::Base > belongs_to :comment > > def upload=(upload) > @upload = upload > end > > def before_validation_on_create > create_image > end > > def create_image > #this is some RMagick nonsese. > end > > def before_create > @thumbnail = ImageList.new.from_blob(@image.first.to_blob) > > if !comment.parent_id > x = comment.board.setting(:parent_thumbnail_at_width) > y = comment.board.setting(:parent_thumbnail_at_height) > else > x = comment.board.setting(:reply_thumbnail_at_width) > y = comment.board.setting(:reply_thumbnail_at_height) > end > > self[:thumbnail_width] = @thumbnail.columns > self[:thumbnail_height] = @thumbnail.rows > > if @thumbnail.columns > x or @thumbnail.rows > y > @thumbnail.change_geometry!("#{x}x#{y}") {|cols, rows, img| > img.resize!(cols, rows)} > end > end > end > > As you can see, it was imortant that I could reference the associated > comment, because that determined the size of the thumbnail, which I > needed to save to the uploads table. > > So I''m closer than when I was before; but still have a long way to go. > For example, I''m only dealing with one uploaded file at a time, when I > need to be dealing with multiple uploads :( > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails