Probably an all-round bad example. I made it up on the spot to try and 
demonstrate the use case - contrived examples are not my forte. The plain 
and simple is that it provides a method of validating a field only if that 
field doesn't already have an error. Using the block syntax, a validation 
can depend on the field being in a particular state (i.e valid so far) and 
can make certain assumptions avoiding the repetition of somewhat tedious 
checks, e.g . place && place.parent && place.parent.enabled and so on. I 
would however not expect exceptions raised in the validation block to be 
rescued.

I wasn't referring to any plugin in particular. If the block was added to 
Sequel::Model::Error#add then of course no plugin is involved. If the 
#validates method was used, then I imagine it would be added to the main 
validation plugin (one of the two validation plugins is deprecated isn't 
it?)

Monkey patching this or simply adding a #validates method to a base model 
class is easier enough. I did think however that there'd be quite a number 
of people who have at least a  few times had the same requirement as I.

Tom

On Wednesday, 28 March 2012 01:42:33 UTC+10, Jeremy Evans wrote:
>
> On Tuesday, March 27, 2012 4:26:37 AM UTC-7, Tom Wardrop wrote:
>>
>> I just have a couple of suggestions for Sequel that I'd like to get some 
>> community feedback on, hopefully getting a bit of weight behind them so 
>> there's less debate over implementing these changes.
>>
>> 1) I believe #length should be added to Sequel::Dataset as an alias of 
>> #count / #size? My rationale here is one of principle of least 
>> surprise. Besides Sequel, I don't know of any other library that has an 
>> objects that implements a length-like method but calls it something 
>> different to every other Ruby library. I've been using Sequel for 6 months 
>> now and still make the mistake of calling #length. While I respect the 
>> argument that this helps force people to distinguish between an Array and a 
>> Dataset, I don't think that ideal takes human nature into account.
>>
>
> For background, people should look at 
> https://github.com/jeremyevans/sequel/issues/457 and 
> http://comments.gmane.org/gmane.comp.lang.ruby.sequel/1359.
>
> I'm still against this for reasons I gave earlier.  The main reason is 
> while datasets are enumerable, they are not like arrays.  Datasets don't 
> have a defined size/length.  dataset.count == dataset.count is not 
> necessarily true.
>
> Still, I'm open to adding the alias if the community is strongly in 
> favor.  FWIW, Dataset#size was removed in 3.0.
>  
>
>> 2) While I like the simplicity of the validation implementation, I'd like 
>> so see an alternate "smarter" interface. The problem I have at the moment 
>> is that for a given field, I may have numerous validation checks. 
>> Typically, if a field fails validation once, you don't want all the 
>> validation that apply to that field to be run. I'll present an example 
>> problem scenario below, and then demonstrate how it could be handled more 
>> gracefully if Sequel had a smarter validation syntax.
>>
>> https://gist.github.com/2214994
>>
>> There's a couple of advantages to the new syntax demonstrated in that 
>> example. The first problem with current validation strategy is that if 
>> :place_id is not present, the second validation will continue to run, 
>> raising a method_missing exception as clearly if :place_id is not present, 
>> then the :place association is going to be nil. These circumstances can 
>> sometimes be hard to spot, and may not come pop up in testing for some 
>> time. The second problem is that some validations could be expensive, so 
>> you only want to validate data that hasn't already been deemed invalid. I 
>> may not be checking the parent_id of the associated place, but may instead 
>> be querying an external web service, as you may do if validating an entered 
>> URL or the existence of a remote object. There's also a third advantage, 
>> and that is that the new syntax is more concise. The condition is implied 
>> (no need for "unless" keyword) an a block wraps better than a trailing 
>> condition. You also get a private variable scope which you know what 
>> conflict with any other variable that may be used for other validations.
>>
>> The implementation would be really simple. It's a matter of adding a new 
>> method #validates (or even just allowing Sequel::Model::Errors#add to take 
>> a block). This method checks the Errors hash to see if there are any errors 
>> for the current field. If there isn't, the block is run. A return value 
>> that resolves to true is considered a pass, a value that resolves to false 
>> is considered a fail.
>>
>> Thoughts on those two suggestions?
>>
>
>  Both of the validation syntaxes that Sequel uses are implemented as 
> plugins, the only built-in validation support is using Errors#add.  Are you 
> proposing modifying validation_helpers or adding a new plugin?
>
> In your case, you appear to want to skip running multiple validations on 
> an field if a previous validation on the field has failed.  I'm not sure 
> how common a desire that is.  The main purpose of validations is giving 
> nice error messages to the user (data integrity should be enforced with 
> database constraints), and I would think you would want to report all 
> failing validations to the user.  The alternative is the user submits a 
> form, gets an error, submits the form again, and gets a different error 
> message.  I'm not saying what you want is a bad idea in your case, but I'm 
> not sure it's a good idea in general.
>
> Looking at your gist, you want to change:
>
>   errors.add(:place, "must have a parent") unless place.parent_id
>
> to:
>
>   validates :place, "must have a parent" { place.parent_id }
>
> I find the former syntax more descriptive. You can avoid the 
> NoMethodErrorerror by doing:
>
>   errors.add(:place, "must have a parent") unless place && place.parent_id
> Note that that validation still doesn't do what you want.  It's possible both 
> for place_id and place.parent_id to be present yet not point to an existing 
> object.  A better example would probably be:
>
>   errors.add(:place, "must have a parent") unless place && place.parent
>
>
> I'm not sure how you want your example to work. You don't want multiple 
> validations in the same field, but in your example, you are using two 
> separate fields. So with an implementation like this:
>
> def validates(field, message)
> unless errors.on(field)
> errors.add(field, message) unless yield
> end 
> end
>
>
> yielding to the block may still raise an error in your example.  Are you 
> proposing to rescue such errors?  Or in your example did you mean to do 
> "validates_presence :place"?
>
> Personally, I don't see a need for this.  It should be fairly easy to 
> monkey patch in and unlikely to break things.  However, I'm certainly open 
> to community feedback in this area.
>
> Thanks,
> Jeremy
>

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sequel-talk/-/r-lqO4RVWqgJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sequel-talk?hl=en.

Reply via email to