Multiple conditions on filters

Is there a more efficient way of coding this?

before_filter :f1, unless: :test? before_filter :f2, only: :show, unless: :test?

I don't want to call test? twice as it is not trivial.

Colin

can you memoize the result of test? assuming it wouldn’t change between callbacks? otherwise, write one callback and perform all the tests, including the action check for only show inside it?

can you memoize the result of test? assuming it wouldn't change between callbacks? otherwise, write one callback and perform all the tests, including the action check for only show inside it?

Yes I could do either of those but neither is aesthetically pleasing, which is why I wondered whether there was a better solution. Will probably plump for the first as the second filter would have to be called something like f1_unless_test_and_f2_if_show_unless_test for it to make any sense when read as f1 and f2 are unrelated.

Colin

What may be more aesthetically pleasing to you is the structure. although I am not certain:

before_filter :f2, :only => :show do |c|   unless c.this.test? end

Totally not certain about the syntax, but I think that the spirit of what I am offering may be helpful

Thanks for the suggestion, but I am not sure how that helps with the f1 filter and the repeated call of test?()

Colin

> can you memoize the result of test? assuming it wouldn't change between > callbacks? otherwise, write one callback and perform all the tests, > including the action check for only show inside it?

Yes I could do either of those but neither is aesthetically pleasing, which is why I wondered whether there was a better solution. Will probably plump for the first as the second filter would have to be called something like f1_unless_test_and_f2_if_show_unless_test for it to make any sense when read as f1 and f2 are unrelated.

I completely agree with the lack of aesthetics.

Since f1 and f2 are completely unrelated, except for being gated by test?, I'd opt for keeping their invocation separate. Temporal coupling isn't useful coupling.

Sorry, I've got nothing else. :frowning:

Tamara

> can you memoize the result of test? assuming it wouldn't change between > callbacks? otherwise, write one callback and perform all the tests, > including the action check for only show inside it?

Yes I could do either of those but neither is aesthetically pleasing, which is why I wondered whether there was a better solution. Will probably plump for the first as the second filter would have to be called something like f1_unless_test_and_f2_if_show_unless_test for it to make any sense when read as f1 and f2 are unrelated.

I completely agree with the lack of aesthetics.

Since f1 and f2 are completely unrelated, except for being gated by test?, I'd opt for keeping their invocation separate. Temporal coupling isn't useful coupling.

Sorry, I've got nothing else. :frowning:

OK, thanks. I have gone for memorising the intermediate values in the test filter as I know they are not going to change within a request. I had hoped there might be some clever way of massaging the before_filter syntax that would provide a solution but I suspect that is not possible.

Cheers

Colin

I don’t see any reason why not to wrap something like this in a before_filter block/lambda. That way you avoid the silly function name, and I wouldn’t consider that coupling.

Also, Liz, I think he means “record or store the relevant information in another format”, such if the response was a large object or collection and Colin only needed to know that there were more than ten, Colin might set @morethanten to true.

I don't see any reason why not to wrap something like this in a before_filter block/lambda. That way you avoid the silly function name, and I wouldn't consider that coupling.

I am not entirely sure what you mean, can you show how my code

before_filter :f1, unless: :test? before_filter :f2, only: :show, unless: :test?

would look in that case please

Also, Liz, I think he means "record or store the relevant information in another format", such if the response was a large object or collection and Colin only needed to know that there were more than ten, Colin might set @morethanten to true.

Correct

Colin

As you read through Ruby code, you may see this construction:

@foo ||= some_expensive_operation(parameters)

That’s known as memoizing (take a memo) or memorizing (or memorising if you’re in England).

What it does is take the existing value if the expensive operation has already run once, or return and store for later the result of the expensive operation. It’s a one-liner in-memory cache.

Walter

Like:

before_filter do

result = test?

unless result

return f1 && ( action_name !=“show” || f2 )

end

end

The test filter (which is not actually called that of course, it has a name meaningful in the context of my application) does a fair amount of db lookup, based on the request params, and comes up with a true or false answer. My mod is, in the test filter, to test a class variable (lets call it @test_answer) and if it is nil then to run the db lookups, caculate the answer true or false, save it in @test_answer and return that value. If it is not nil then I just return the value. The result is that the first time it runs it does the lookup, the second time it just returns the answer

In practice that just turns into something like def test?   @test_answer ||= do_the_lookup_and_calcs() end

Colin

Very nice! The all important ||=

Now if I could just convince you of the benefits of inline posting rather than top posting then I would feel my life was worth while after all :slight_smile:

Colin

Like:

before_filter do

    result = test?

    unless result       return f1 && ( action_name !="show" || f2 )     end

end

That's playing some "ruby golf" , you can pull that apart to make it as readable as you want ( honestly I actually perfer 'and' and 'or' but that would result in some more ()s ).

Yes I see, thanks for the explanation.

Colin

Liz, are you stuck in the G-jail web interface, or the web view of Google Groups? Your desktop mail app can connect to Gmail easily, and this is a mailing list, first and foremost, and e-mail etiquette rules apply!

Walter

No disrespect meant here, Liz — seriously, you do good work and have solved many problems for others on this list. I do not want to knock anything about your input here.

What Colin is saying (and I am echoing) is that when you reply to an e-mail, it is considered good “netiquette” to hit Reply, then move your cursor to below the previous poster’s message body (or within it, if you need to reply to multiple points within that message body) and insert your reply inline with the part of the message you are replying to.

Since individual e-mail messages are normally read from top to bottom, yet each message piles up at the top of your inbox list (or Google Groups interface), there is a serious disconnect between what was asked and what was answered. Keeping the order of the previous thread linear within each message, like this:

[>>> Original question ]

[>> First reply ]

[> Follow-up question ]

[ Second reply ]

…maintains the flow of conversation and preserves context for those who are reading this entire thread later, and will naturally start with the last message first. Otherwise people have to scroll to the bottom and read upward to gain any hope of understanding what the conversation is about. It is also a good idea to snip out trailing auto-footers and extraneous materials, but at a minimum, resisting the urge (or technological imperative, in the case of Gmail’s poorly-designed quoting tools) to top-post a reply should be considered the minimum. I realize I don’t always do this properly myself, but I want to do better, and I hope to help others understand the reasoning behind that as well.

Thanks again for your efforts to answer questions on this list. I do appreciate it, and I am sure that others do as well.

Walter

+1 to that. Liz, in case you are using the web interface to gmail, when you click Reply you should see see three little dots in the bottom left of the window (as your sight is impaired this may not be at all obvious, in fact it is not at all obvious to those lucky enough to have good eyesight). If you click the dots it will expand the previous message so you can insert your reply at appropriate point(s).

Also, though likely you know this already, in the browser you should be able to increase the text size using something like View > Zoom or Ctrl +

Cheers

Colin