From: The 8472 Date: 2012-12-08T05:28:07+09:00 Subject: [ruby-core:50678] Re: [ruby-trunk - Feature #4085] Refinements and nested methods On 07.12.2012 21:02, rosenfeld (Rodrigo Rosenfeld Rosas) wrote: > > Issue #4085 has been updated by rosenfeld (Rodrigo Rosenfeld Rosas). > > > Aaron, I see your point but often my queries are much more complex than a single mention to some column. So if I have to repeat an unrepresentable column multiple times I'd prefer the block approach. > > When I mentioned the DSL issues I did it from my previous experience with Grails. In Grails you can bind the params arguments as the controller's method's arguments. So, consider this: > > class SomeController { > def someAction(String name) { > MyDomainClass.find { name == name} // WTF?! I want to compare the "name" column to the value of the "name" param > } > } > > I know this isn't possible in Ruby (the params binding feature). But what if you want to compare "name" column to the result of a call to the "name" local (or inherited) method? Named parameters? Depends. If you can splat them I would simply suggest moving the thing to a different method which won't suffer from scoping issues. But really, that's a Groovy-issue in so far that it gives local variable names (method argument names essentially are local vars) a non-local significance which robs you of the freedom of renaming them as you desire without breaking code. But there are solutions. Remember that it's instance_eval'd: MyDomainClass.find { self.name == name} Alternatively you can teach the DSL some smartness and switch between call and instance_eval based on arity: MyDomainClass.find {|d| d.name == name} There are many ways to solve this problem without polluting any external object. > So if I have to repeat an unrepresentable column multiple times I'd prefer the block approach. Block approach is a bad name for this, since both approaches are using blocks ;) Anyway, this problem can be solved too: Foo.dsl do col = __send__("illegal_name") col.eq(coalesce(id,title)) | col.like("%bar%") end In fact, squeel provides an even more elegant solution. Since column names often are escaped with the ` character and that's a valid method name in ruby it provides literals that way: MyModel.where{other_table.`literal_name` == "bar"} You're really bringing up edge cases here for which there are multiple solutions. There is no necessity to monkey-patch Symbol only to build some DSLs, really.