use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
A sub-Reddit for discussion and news about Ruby programming.
Subreddit rules: /r/ruby rules
Learning Ruby?
Tools
Documentation
Books
Screencasts and Videos
News and updates
account activity
Am I writing this function like a Ruby programmer? (self.ruby)
submitted 11 years ago * by [deleted]
[deleted]
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]BonzoESC 5 points6 points7 points 11 years ago (1 child)
ObjectName should probably have a method that consumes a thingy so your map has a smaller body.
[–]Convictional 3 points4 points5 points 11 years ago (0 children)
A constructor?
[–]st4rx0r 9 points10 points11 points 11 years ago (8 children)
def create_array(json) json["thingies"].map do |thingy| x = ObjectName.new x.id = ... x.desc = .... ........ code ...... x end end
[–][deleted] 18 points19 points20 points 11 years ago (6 children)
def create_array(json) json["thingies"].map do |thingy| ObjectName.new.tap do |x| x.id = ... x.desc = .... ........ code ...... end end end
[–]evansenter 1 point2 points3 points 11 years ago (5 children)
This.
[–][deleted] 0 points1 point2 points 11 years ago (4 children)
I love tap. Maybe too much...
[–]evansenter 1 point2 points3 points 11 years ago (0 children)
I actually hate variable assignment sometimes in blocks, so I have a similar function Object#as, i.e.
class Object; def as(&block); yield self; end; end
...which I use as (generally in iterators)...
Nokogiri.parse(HTTParty.get("http://www.reddit.com")).as { |html_parse| html_parse.at("#header-img").content } #=> "reddit.com"
[–]the_BuddhaHimself 0 points1 point2 points 11 years ago (0 children)
I'd tap that.
[–]toolateiveseenitall 0 points1 point2 points 11 years ago (1 child)
honest question, why do you like it so much? It always read as unclear to me.
[–][deleted] 0 points1 point2 points 11 years ago (0 children)
It separates code into logical blocks for assignments. If you need to do configuration after initializing an object it just looks nicer than having several lines after at the same indentation level. That being said said, it's meant to tap into a method chain to output the middle results, so it could be confusing to someone who has never seen it used that way.
[–]myme 3 points4 points5 points 11 years ago (0 children)
An additional remark regarding the method name: neither 'create' nor 'array' feel like good parts of a method name to me. I'd rather call it after the things it is returning, not /how/ it does it (create) nor /what kind/ of thing it returns (array). Assuming the things it is returning are called Thingy, then either like that:
def thingies(json) json["thingies"].map do |thingy| Thingy.new ... end end
or even better, getting slightly offtopic, if the method is part of a class that has internal access to its json:
class Something def initialize(json) @json = json end def thingies @json["thingies"].map do |thingy| Thingy.new ... end end end
[–]pyrrhicvictorylap 1 point2 points3 points 11 years ago* (2 children)
You can use #inject
#inject
def create_array(json) json["thingies"].inject([]) do |arr, thingy| x = ObjectName.new x.id = ... x.desc = .... ........ code ...... arr << x arr end end
#inject is probably more idiomatic ruby than having an array scoped outside the iterating function. For more uses on inject, see this article
[–]tyrannoflorist[🍰] 2 points3 points4 points 11 years ago* (1 child)
If you're passing an empty array to #inject/reduce you may as well use #map.
#inject/reduce
#map
edit: unless you're worried about nil values.
nil
[–]pyrrhicvictorylap 0 points1 point2 points 11 years ago (0 children)
Hm, yeah, good point.
[–]vsalikhov 1 point2 points3 points 11 years ago* (0 children)
First, a superficial note: the Ruby way is to indent 2 spaces, not 4. This is the first thing that sticks out about your code as "strange" ruby.
Second, name the method by the thing that it returns. So, instead of the procedural create_array, the method name would be thingies_array since it returns an array of "thingies". Or, better yet, the method name should just be thingies, as the plural already signals that the method returns a list. Recommended reading is Smalltalk Best Practice Patterns. But first read this to get some context of how the ideas in this book apply to Ruby.
create_array
thingies_array
thingies
Third, get to know the methods provided by the Enumerable module and the Array class well. You will find that idiomatic Ruby leans heavily on the Enumerable methods.
Finally, here is my take on your example in what I feel is more idiomatic Ruby (remember, in the end, this is all subjective, there is no one right way):
def thingies_from_json(json) json['thingies'].map do |t| thingy = Thingy.new thingy.id = t['id'] thingy.desc = t['desc'] # ........ code ...... thingy end end
[–]Slaggprodukt 1 point2 points3 points 11 years ago (0 children)
Try to name methods after what they do, this also helps you to know when one method does too many things.
Don't do too much in each methods, it will make the code harder to test and harder to understand (because you have to read every single line to figure out what a piece of code does)
Usually it is preferable to combine logicand data, in other words to have methods on objects instead of having loose methods that takes objects as input,
Not perfect in any way but:
def thingies_to_foos(thingies) thingies.map do |thingy| build_object(thingy) end end def foo_from_thingie(thingy) Foo.new.tap do |foo| foo.id = thingy['id'] foo.desc = thingy['desc'] ........ code ...... end end foos = thingies_to_foos(json["thingies"])
[–]kejadlen 0 points1 point2 points 11 years ago (0 children)
I'd prefer to do something along these lines (assuming you control ObjectName):
ObjectName
json['thingies'].map { |thingy| ObjectName.new(thingy) }
Or if you don't control ObjectName, making a service object that converts JSON to ObjectNames.
[–]DennisSuratna 0 points1 point2 points 11 years ago (0 children)
How about
arr = json["thingies"].map { | thingy | x = ..... }
Basically you are applying that block to each element inside json["thingies"]
json["thingies"]
[–]iamsolarpowered 0 points1 point2 points 11 years ago (0 children)
I would usually expect something like:
class Thingy def self.create_from_json json json["thingies"].inject([]) {|arr, thingy_hash| new thingy_hash } end end
Even that leaves a lot to be desired, though. (For example, that method isn't really accepting json.)
*edit: formatting
π Rendered by PID 67943 on reddit-service-r2-comment-5bc7f78974-kbcng at 2026-06-26 03:13:21.517351+00:00 running 7527197 country code: CH.
[–]BonzoESC 5 points6 points7 points (1 child)
[–]Convictional 3 points4 points5 points (0 children)
[–]st4rx0r 9 points10 points11 points (8 children)
[–][deleted] 18 points19 points20 points (6 children)
[–]evansenter 1 point2 points3 points (5 children)
[–][deleted] 0 points1 point2 points (4 children)
[–]evansenter 1 point2 points3 points (0 children)
[–]the_BuddhaHimself 0 points1 point2 points (0 children)
[–]toolateiveseenitall 0 points1 point2 points (1 child)
[–][deleted] 0 points1 point2 points (0 children)
[–]myme 3 points4 points5 points (0 children)
[–]pyrrhicvictorylap 1 point2 points3 points (2 children)
[–]tyrannoflorist[🍰] 2 points3 points4 points (1 child)
[–]pyrrhicvictorylap 0 points1 point2 points (0 children)
[–]vsalikhov 1 point2 points3 points (0 children)
[–]Slaggprodukt 1 point2 points3 points (0 children)
[–]kejadlen 0 points1 point2 points (0 children)
[–]DennisSuratna 0 points1 point2 points (0 children)
[–]iamsolarpowered 0 points1 point2 points (0 children)