-1

I need a function to get something in according to check if they meet some judgment, the judgement is some function which require parameters. such as:

Something.is_close_to?(:sky)

I already made one, with to what I learned in here.

def get_somethings(options = {})
  somethings = []
  Something.all.each do |something|
    this_is_it = true

    options.each_pair do |key, value|
      expected_result = value.pop
      this_is_it = false if !(Something.first.send(key, *value) == expected_result)
    end

    somethings << something if this_is_it
  end
  return somethings
end

and I can call this function via using someway like this:

options = {is_close_to?: ["sky", true], is_higher_than?: [2000, true]}
get_somethings()

I think my way is twisted, so I wonder if there are better way to do this.

Community
  • 1
  • 1
  • sorry about the typo, the last line of code is: get_somethings(options) – Zephyr Sails Nov 28 '15 at 03:08
  • I'm voting to close this question as off-topic because it is about how to better structure working code. This is not a good topic for SO. However, it might be good a good question for http://codereview.stackexchange.com/ – Wayne Conrad Nov 28 '15 at 12:07

2 Answers2

0

Let's split this in a few steps:

  1. Select items from a collection that match a condition
  2. Match all conditions from your condition
  3. Extract the elements from the hash (called destructuring)
  4. Call the check method on the object

The code

def get_somethings(collection, conditions = {})
  # Step 1
  collection.find_all do |item|
    matches_conditions item, conditions
  end
end

# Step 2
def matches_conditions(item, conditions)
  # Step 2           Step 3
  conditions.all? do |predicate, (argument, expected)|
    # Step 4
    item.public_send(predicate, argument) == expected
  end
end

conditions = {is_close_to?: ["sky", true], is_higher_than?: [2000, true]}
get_somethings(Something.all, conditions)
monkbroc
  • 808
  • 9
  • 13
  • Thanks, I will split it to two part, but I think shouldn't used: conditions.all? do |predicate, (argument, expected)|here, what if there are more than one argument here? such as: conditions = {is_height_between?: [100, 200, true]} |predicate, (argument, expected)| could not split [100, 200] out – Zephyr Sails Nov 28 '15 at 03:55
0

The code in question has some mistake, sorry about that, the working edition should be like the following:

def get_somethings(options = {})
  somethings = []
  Something.all.each do |something|
    found_one = true
    options.each_pair do |key, value|
      expected_result = value.first

      if something.send(key, *value.drop(1)) != expected_result
        found_one = false
      end

    end
    somethings << something if found_one
  end
  return somethings
end
  • Hello, welcome to SO! On your question above, there is a link named "edit." Clicking that link will allow you to edit the question in order to fix mistakes or otherwise improve the question. – Wayne Conrad Nov 28 '15 at 12:23