0

I have such models:

Class User
  has_many :comments
  # have field 'name' in DB
end

Class Comment
  belongs_to :user
end

And i have very complex and very hard for understand admin backend, which gets all models and allows to control it from Admin Interface. It gets all associations and processes it with evals.

And such eval works fine:

eval("comment." + o[0][:object])

where o[0][:object] = "user.name"

But i wanna make it without eval. This approach works, but it's not very universal:

comment.send("user").send("name")

And in real code it looks very ugly:

(o[0][:object].split(".").count < 2) ? h(object.send(o[0][:object])) : h(object.send(o[0][:object].split(".")[0]).send(o[0][:object].split(".")[1]))

So, what's the best way to get eval's univesality for such contructions, if i wanna show more nested calls, like:

comment.user.first_friend.haters.count

???

2
  • Named scopes are pretty popular for creating complicated finders. As for refactoring eval away, it looks like you might be able to do it with single table inheritance. Commented Dec 12, 2011 at 14:36
  • 1
    It looks ugly because you're inlining it--in real life you'd write a method, either recursive or iterative, that calls the next method on the current object, sets the current object, and continues until done or an error. That aside, your purpose isn't clear--are you just trying to avoid writing an admin page for each model? Commented Dec 12, 2011 at 14:36

2 Answers 2

2

I'm not sure why you don't want to use eval in this case. Sometimes it's the best solution.

Here you could do this simply:

o[0][:object].split('.').reduce(object){|method, obj| obj.send method }
Sign up to request clarification or add additional context in comments.

3 Comments

Here it is the shortest solution (definitely not the best), but even that is because he has another code smell: the content of o[0][:object]. How did that (a list of method names separated by dots) get there? eval seems to be the least problem here.
@MladenJablanović Well definitely this question is missing context. I'm not trying to second guess the OP here.
BTW, it seems that this also works: o[0][:object].split('.').reduce(object, :send)
0

And what about this ?

class Object # or just ActiveRecord::Base
  def multiple_send(methods)
    first_method, remaining_methods = methods.split(".", 2)
    ret = __send__(first_method) # I use __send__ to prevent from classes overwriting send() method

    remaining_methods.nil? ? ret : ret.multiple_send(remaining_methods)
  end
end

Then you can write something like comment.multiple_send("user.name").

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.