Reputation: 12663
I am trying to add a loop within a method in a Rails app. It looks something like this
Parent.do_something(
attribute: "a string",
parameter: "a string",
child[0]: "child_url"
)
Sometimes a parent will have no children. Sometime a parent will have x children. How can I create a loop within a function that will cycle through all these children.
I want something like
i=0
children=Child.all
Parent.do_something(
attribute: "a string",
parameter: "a string",
for child in children
child[i]: "child_url"
i= i + 1
end
)
That will generate
Parent.do_something(
attribute: "a string",
parameter: "a string",
child[0]: "child_0_url",
child[1]: "child_1_url",
child[2]: "child_2_url"
)
If I have not explained this problem very clearly, I will update my question based on comments.
Upvotes: 0
Views: 138
Reputation: 7409
If you're trying to pass a variable number of arguments to a method, you're probably looking for the splat (*) operator.
Upvotes: 1
Reputation: 2631
If you want the urls like you typed them, try this:
children = Child.all
Parent.do_something(
attribute: "a string",
parameter: "a string",
child: something
)
def something
child = []
children.length.times { |index| child << "child_#{index}_url"}
return child
end
You could also replace children.length with Child.count if you don't need the children elsewhere, but I'm assuming you do.
Edit: I think this may be more what you are looking for:
children = Child.all
Parent.do_something(
attribute: "a string",
parameter: "a string",
child: children.each_with_index.map { |child,i| "child_#{i}_#{child.url}"}
)
This takes advantage of the fact that each_with_index returns an Enumerator if no block is given.
Upvotes: 0
Reputation: 3963
As others have suggested, it might be better to redesign your method to expect an array of children, rather than lots of single parameters :
Parent.do_something(
attribute: "a string",
parameter: "a string",
children: ["child_0_url", "child_1_url", "child_2_url"]
)
But if you have to do it the way you said (for instance, if you're constrained by someone else's poor API):
children = Child.all
Parent.do_something(
{attribute: "a string",
parameter: "a string"}.merge Hash[*(children.each_with_index.map { |child, i| ["child[#{i}]", child.url] }.flatten)]
)
Ugly, huh?
As the saying goes; if it's hard to do, you're probably doing it wrong. The nice flat map of Ismael Abreu's answer is much prettier.
Upvotes: 1
Reputation: 16730
You might just want to do this:
children = Child.all
Parent.do_something(
attribute: "a string",
parameter: "a string",
child: children.map { |child| child.url }
)
Upvotes: 2
Reputation: 4880
Might be easier to extract that part into a different method:
Parent.do_something(
attribute: "a string",
parameter: "a string",
children: children_method
)
def children_method
Parent.children.map do |child|
# whatever needs to be done
end
end
Upvotes: 1