398 Matching Annotations
  1. Last 7 days
  2. Aug 2022
    1. You can pass any options to puma via the server setting Capybara.server = :puma, { queue_requests: true }
    2. This very much appears to be a bug or design flaw in puma - The fact that a persistent connection ties up a thread on the chance a request might come over that connection seems like not great behavior. This would really only be an issue when puma is run with no workers (which wouldn't be done in production) but it still seems a little nuts.
  3. Jul 2022
    1. Create a new controller to override the original: app/controllers/active_storage/blobs_controller.rb

      Original comment:

      I've never seen monkey patching done quite like this.

      Usually you can't just "override" a class. You can only reopen it. You can't change its superclass. (If you needed to, you'd have to remove the old constant first.)

      Rails has already defined ActiveStorage::BlobsController!

      I believe the only reason this works:

      class ActiveStorage::BlobsController < ActiveStorage::BaseController

      is because it's reopening the existing class. We don't even need to specify the < Base class. (We can't change it, in any case.)

      They do the same thing here: - https://github.com/ackama/rails-template/pull/284/files#diff-2688f6f31a499b82cb87617d6643a0a5277dc14f35f15535fd27ef80a68da520

      Correction: I guess this doesn't actually monkey patch it. I guess it really does override the original from activestorage gem and prevent it from getting loaded. How does it do that? I'm guessing it's because activestorage relies on autoloading constants, and when the constant ActiveStorage::BlobsController is first encountered/referenced, autoloading looks in paths in a certain order, and finds the version in the app's app/controllers/active_storage/blobs_controller.rb before it ever gets a chance to look in the gem's paths for that same path/file.

      If instead of using autoloading, it had used require_relative (or even require?? but that might have still found the app-defined version earlier in the load path), then it would have loaded the model from activestorage first, and then (possibly) loaded the model from our app, which (probably) would have reopened it, as I originally commented.

    1. meat: https://github.com/musaffa/file_validators/blob/master/lib/file_validators/validators/file_content_type_validator.rb

      Compared to https://github.com/aki77/activestorage-validator, I slightly prefer this because - it has more users and has been battle tested more - is more flexible: can specify exclude as well as allow - has more expansive Readme documentation - is mentioned by https://github.com/thoughtbot/paperclip/blob/master/MIGRATING.md#migrating-from-paperclip-to-activestorage - mentions security: whether or not it's needed, at least this makes extra attempt to be secure by using external tool to check content_type; https://github.com/aki77/activestorage-validator/blob/master/lib/activestorage/validator/blob.rb just uses blob.content_type, which I guess just trusts whatever ActiveStorage gives us (which seems fair too: perhaps this should be kicked up to them to be their concern)

      In fact, it looks like ActiveStorage does do some kind of mime type checking...

      activestorage-6.1.6/app/models/active_storage/blob/identifiable.rb ``` def identify_without_saving unless identified? self.content_type = identify_content_type self.identified = true end end

      def identify_content_type
        Marcel::MimeType.for download_identifiable_chunk, name: filename.to_s, declared_type: content_type
      end
      

      ```

  4. Jun 2022
    1. Symbols are an interesting twist on the idea of a string. The full explanation can be a bit long, but here’s the short version:Strings can be changed, so every time a string is used, Ruby has to store it in memory even if an existing string with the same value already exists. Symbols, on the other hand, are stored in memory only once, making them faster in certain situations.One common application where symbols are preferred over strings are the keys in hashes. We’ll cover this in detail in the hashes lesson later in the course.You won’t need to use symbols much in the beginning, but it’s good to get familiar with what they are and what they look like so that you can recognize them.

      symbols

    1. As a documentation convention, methods are listed out with either a :: or a # to indicate two different kinds of publicly accessible methods. Methods denoted by :: are considered class methods, while methods denoted by # are considered instance methods.

      In documentation (not actual code):

      :: -> class methods

      # -> instance methods

  5. May 2022
    1. before(:all) do @fiber = Fiber.new do Benchmark.ips do |benchmark| @benchmark = benchmark Fiber.yield benchmark.compare! end end @fiber.resume end
    2. does the microgem I published work for your use case?
    3. We actually already use this patch: http://myronmars.to/n/dev-blog/2012/03/building-an-around-hook-using-fibers
    1. I’ve been looking everywhere for examples of how to use Fibers that are complicated enough to do something useful but simple enough to understand. For an older feature it’s one of the least documented.
    2. I haven't done a lot with Fibers,so having you point out a potential use for them and then walk through it was great.
  6. Apr 2022
    1. Caution: + continues the statement but not the string. puts "foo"+"bar".upcase gives you fooBAR, whereas puts ("foo"+"bar").upcase gives you FOOBAR. (Whether or not there's a newline after the +.) But: if you use a backslash instead of the plus sign, it will always give you FOOBAR, because combining lines into one statement, and then combining successive strings into one string, happen before the string method gets called.
    1. It is very important that your gem reopens the modules ActiveJob and ActiveJob::QueueAdapters instead of defining them. Because their proper definition lives in Active Job. Furthermore, if the project reloads, you do not want any of ActiveJob or ActiveJob::QueueAdapters to be reloaded. Bottom line, Zeitwerk should not be managing those namespaces. Active Job owns them and defines them. Your gem needs to reopen them.
    1. export RUBY_THREAD_VM_STACK_SIZE=2000000

      This example is how to make stack size larger, but my use case is actually needing to make it smaller.

      Why? Because I was debugging a bug that was causing a SystemStackError and it took a long time to hit the stack size limit. In order to iterate more quickly (run my test that exercised the problem code), I wanted to set the stack size smaller, so I did:

      export RUBY_THREAD_VM_STACK_SIZE=200

    1. I'm a big fan of refinements (yes, I am), and that's what I did to make this code look simpler and more beautiful:
  7. Mar 2022
    1. # Allows you to just run "pry" inside a Rails app directory and get # everything loaded as rails c does. Inside a Bundler directory does # what bundle console does.
    1. Ruby Object Mapper (rom-rb) is a fast ruby persistence library with the goal of providing powerful object mapping capabilities without limiting the full power of the underlying datastore.
  8. Feb 2022
    1. There are two pairs of methods for sending/receiving messages: Object#send and ::receive for when the sender knows the receiver (push); Ractor.yield and Ractor#take for when the receiver knows the sender (pull);
    1. I am using them in a real life application. I am calculating the available tables for a full calendar with many time slots and with respect to many configurable business rules for restaurants. Using callcc this feature got blazingly fast and very nicely readable. Also we use it to optimise table arrangements with respect to complex restaurant business rules (even something like: Guest A doesn't like to sit near Guest B). Please just have a look at these resources: https://github.com/chikamichi/amb/tree/master/examples http://web.archive.org/web/20151116124853/http://liufengyun.chaos-lab.com/prog/2013/10/23/continuation-in-ruby.html Please help me to keep Guest A away from Guest B. Bad things might happen.
    2. "Context" manipulation is one of big topic and there are many related terminologies (academic, language/implementation specific, promotion terminologies). In fact, there is confusing. In few minutes I remember the following related words and it is good CS exam to describe each :p Thread (Ruby) Green thread (CS terminology) Native thread (CS terminology) Non-preemptive thread (CS terminology) Preemptive thread (CS terminology) Fiber (Ruby/using resume/yield) Fiber (Ruby/using transfer) Fiber (Win32API) Generator (Python/JavaScript) Generator (Ruby) Continuation (CS terminology/Ruby, Scheme, ...) Partial continuation (CS terminology/ functional lang.) Exception handling (many languages) Coroutine (CS terminology/ALGOL) Semi-coroutine (CS terminology) Process (Unix/Ruby) Process (Erlang/Elixir) setjmp/longjmp (C) makecontext/swapcontext (POSIX) Task (...)
  9. Jan 2022
    1. Ruby 2.6 introduces an initial implementation of a JIT (Just-In-Time) compiler. The JIT compiler aims to improve the performance of Ruby programs. Unlike traditional JIT compilers which operate in-process, Ruby’s JIT compiler writes out C code to disk and spawns a common C compiler to generate native code. For more details about it, see the MJIT organization by Vladimir Makarov.
  10. Dec 2021
    1. How to Create a Micro-Job Marketplace Like Fiverr: Features, Cost, TimelineTimurTech JournalistMarketplaceProduct GuideHomeBlogEntrepreneurshipHow to Create a Micro-Job Marketplace Like Fiverr: Features, Cost, TimelinePublishedNov 19, 2021UpdatedNov 19, 202120 min readIt’s no secret that the COVID-19 pandemic has led many people to reconsider their jobs. Now, freelance as an alternative career path steadily becomes a reality. 50.9% of the U.S. workforce will be freelancing by 2027, a Statista survey shows. Businesses like Fiverr and fellow gig-focused companies rode the wave. To be more precise, they adopted a model allowing the hire of independent contractors without any legwork. How do such tools set the new trend in powering freelancers? In this article, we share proven methods geared towards freelance website growth. Moreover, you will get a glimpse of how to create a micro-job marketplace like Fiverr of your own.

      It’s no secret that the COVID-19 pandemic has led many people to reconsider their jobs. Now, freelance as an alternative career path steadily becomes a reality. 50.9% of the U.S. workforce will be freelancing by 2027, a Statista survey shows.

      Businesses like Fiverr and fellow gig-focused companies rode the wave. To be more precise, they adopted a model allowing the hire of independent contractors without any legwork. How do such tools set the new trend in powering freelancers?

      In this article, we share proven methods geared towards freelance website growth. Moreover, you will get a glimpse of how to create a micro-job marketplace like Fiverr of your own.

  11. Nov 2021
    1. How to Choose a Reliable SaaS Application Development CompanyKateCloud & SaaS Product ResearcherDmitryCEOSaaSHomeBlogEntrepreneurshipHow to Choose a Reliable SaaS Application Development CompanyPublishedAug 5, 2020UpdatedAug 5, 202012 min readCurrently, SaaS is the largest segment of the global public cloud services market. The growing SaaS industry provides an equal-opportunity atmosphere for businesses. It concerns enterprises from startups to tech giants – and any size in between. It explains why traditional software companies, like Microsoft and Adobe, decided to look into that direction too. Indeed, the time is ripe for developing a SaaS application now. But however tempting it may be, do not dive in headfirst with launching a SaaS product, because sometimes, it can be very challenging. That is why we have prepared a guide on finding a SaaS application development company that will be your best bet.

      Looking to build a SaaS app? You will need help of a reliable development team. Check our advice on how to choose a SaaS development company.

    1. SaaS Product Development: Why Choose Ruby on Rails Framework?KateCloud & SaaS Product ResearcherRuby/RailsSaaSHomeBlogTechnologySaaS Product Development: Why Choose Ruby on Rails Framework?PublishedSep 10, 2020UpdatedSep 10, 202013 min readWhich technology to pick for your SaaS business to succeed? This question is not uncommon in our days. In fact, quite the opposite because the SaaS model has become a meaningful part of every business domain. And the demand for SaaS product development is higher than ever and still increasing. This article will discuss the essential factors you need to consider when selecting a framework for your SaaS project. Also, we will introduce the top 3 frameworks for building a SaaS product with their pros and cons. Read on to see the best examples of SaaS applications.

      Choosing the right tech stack can help you save costs and make your app stand out in the saturated market. Let’s discuss why Ruby on Rails can be your best choice.

    1. What Makes Ruby on Rails Perfect for Marketplace Development?AlinaE-Commerce & SaaS StrategistMarketplaceRuby/RailsHomeBlogEntrepreneurshipWhat Makes Ruby on Rails Perfect for Marketplace Development?PublishedJul 13, 2020UpdatedJul 13, 202012 min readThe last several years have been marked with the rise of different marketplaces. Airbnb, AliExpress, Etsy, Booking.com are on everyone’s lips. That's not surprising that the idea of launching a second Amazon or eBay seems so appealing. To win the e-commerce race, entrepreneurs focus on providing excellent customer experience and build fast-loading and scalable websites. Besides, business owners take various security measures to protect their customers’ sensitive information. This way, they can gain clients’ trust and boost sales. When building a custom marketplace, what technology stack is best to achieve all these goals? Our answer is simple: Ruby on Rails. In this article, we will fill you in on the Ruby on Rails marketplace development. At Codica, we are passionate fans of this framework and have built numerous e-commerce platforms with its help. Based on our experience, we will discuss the key reasons to choose RoR for building a successful marketplace.

      The last several years have been marked with the rise of different marketplaces. Airbnb, AliExpress, Etsy, Booking.com are on everyone’s lips. That's not surprising that the idea of launching a second Amazon or eBay seems so appealing.

      To win the e-commerce race, entrepreneurs focus on providing excellent customer experience and build fast-loading and scalable websites. Besides, business owners take various security measures to protect their customers’ sensitive information. This way, they can gain clients’ trust and boost sales.

      When building a custom marketplace, what technology stack is best to achieve all these goals? Our answer is simple: Ruby on Rails.

      In this article, we will fill you in on the Ruby on Rails marketplace development. At Codica, we are passionate fans of this framework and have built numerous e-commerce platforms with its help. Based on our experience, we will discuss the key reasons to choose RoR for building a successful marketplace.

  12. Oct 2021
    1. Collapsing directories Say some directories in a project exist for organizational purposes only, and you prefer not to have them as namespaces. For example, the actions subdirectory in the next example is not meant to represent a namespace, it is there only to group all actions related to bookings: booking.rb -> Booking booking/actions/create.rb -> Booking::Create
  13. Sep 2021
    1. Thanks to Rack Middleware and Rails 3 you can output pretty JSON for every request without changing any controller of your app. I have written such middleware snippet and I get nicely printed JSON in browser and curl output.
    1. The important thing to understand is that there is no such thing as a class method in Ruby. A class method is really just a singleton method. There is nothing special about class methods. Every object can have singleton methods. We just call them "class methods" when the object is a Class because "singleton method of an instance of Class" is too long and unwieldy.
    2. Class methods are actually instance methods defined on the singleton class of a class.
  14. Aug 2021
    1. What if I told you there was a way to do this in Ruby?:destructure def adds(a: 1, b: 2) a + bendadds(a: 1, b: 2)# => 3adds(OpenStruct.new(a: 1, b: 2))# => 3Foo = Struct.new(:a, :b)adds(Foo.new(1,2))# => 3
    2. def destructure(method_name) meta_klass = class << self; self end method_proc = method(method_name) unless method_proc.parameters.all? { |t, _| t == :key } raise "Only works with keyword arguments" end arguments = method_proc.parameters.map(&:last) destructure_proc = -> object { values = if object.is_a?(Hash) object else arguments.map { |a| [a, object.public_send(a)] }.to_h end method_proc.call(values) } meta_klass.send(:define_method, method_name, destructure_proc) method_nameend
    1. this kind of run-time code generation is certainly more natural in Ruby, it's one of its Lispish elements
    2. Rubyists don't call these things annotations. One of the things I like doing is to find common techniques that cross languages, for me this is a common technique and 'annotation' seems like a good generic word for it. I don't know if Rubyists will agree.
    1. An internal DSL (often called an Embedded DSL) is a DomainSpecificLanguage that is written inside an existing host language. It's a common way of thinking in a number of programming language communities - particularly the Lisp community. It's now gaining a lot of attention as DSLs are a common way of thinking in the rapidly growing Ruby community.
    1. # And standalone like a case:Qo.match(people.first, Qo.m(age: 10..19) { |person| "#{person.name} is a teen that's #{person.age} years old" }, Qo.m(:*) { |person| "#{person.name} is #{person.age} years old" })
    2. # How about some "right-hand assignment" pattern matchingname_longer_than_three = -> person { person.name.size > 3 }people_with_truncated_names = people.map(&Qo.match_fn( Qo.m(name_longer_than_three) { |person| Person.new(person.name[0..2], person.age) }, Qo.m(:*) # Identity function, catch-all))
    1. 3. The no-keyword-arguments syntax (**nil) is introduced You can use **nil in a method definition to explicitly mark the method accepts no keyword arguments. Calling such methods with keyword arguments will result in an ArgumentError. (This is actually a new feature, not an incompatibility)
    2. This is useful to make it explicit that the method does not accept keyword arguments. Otherwise, the keywords are absorbed in the rest argument in the above example.
    3. If you extend a method to accept keyword arguments, the method may have incompatibility as follows: # If a method accepts rest argument and no `**nil` def foo(*args) p args end # Passing keywords are converted to a Hash object (even in Ruby 3.0) foo(k: 1) #=> [{:k=>1}] # If the method is extended to accept a keyword def foo(*args, mode: false) p args end # The existing call may break foo(k: 1) #=> ArgumentError: unknown keyword k
    4. If your code doesn’t have to run on Ruby 2.6 or older, you may try the new style in Ruby 2.7. In almost all cases, it works. Note that, however, there are unfortunate corner cases as follows:
    5. Ruby 2.6 or before themselves have tons of corner cases in keyword arguments.
    6. You need to explicitly delegate keyword arguments. def foo(*args, **kwargs, &block) target(*args, **kwargs, &block) end
    7. you can use the new delegation syntax (...) that is introduced in Ruby 2.7. def foo(...) target(...) end
    8. ruby2_keywords allows you to run the old style even in Ruby 2.7 and 3.0.
    9. Will my code break on Ruby 2.7? A short answer is “maybe not”. The changes in Ruby 2.7 are designed as a migration path towards 3.0. While in principle, Ruby 2.7 only warns against behaviors that will change in Ruby 3, it includes some incompatible changes we consider to be minor. See the “Other minor changes” section for details. Except for the warnings and minor changes, Ruby 2.7 attempts to keep the compatibility with Ruby 2.6. So, your code will probably work on Ruby 2.7, though it may emit warnings. And by running it on Ruby 2.7, you can check if your code is ready for Ruby 3.0.
    10. However, this style is not recommended in new code, unless you are often passing a Hash as a positional argument, and are also using keyword arguments
  15. Jul 2021
    1. You can do this elegantly with throw/catch, like this:
    2. In most languages, there is no clean equivalent for breaking out of a recursive algorithm that uses a recursive function. In Ruby, though, there is!
    3. it's much faster—the stack frame does not have to be carried along the "thrown symbol", and no object is created. Lightweight nonlinear flow control.
    4. Throw it's a more elegant way to use an exception-like system as a control flow.
  16. Jun 2021
    1. With GraphQL-Ruby, it’s possible to hide parts of your schema from some users. This isn’t exactly part of the GraphQL spec, but it’s roughly within the bounds of the spec.
    1. prepend(Module.new do
    2. A lot of projects leveraging CDP appeared since then, including the most well-known one—Puppeteer, a browser automation library for Node.js. What about the Ruby world? Ferrum, a CDP library for Ruby, although being a pretty young one, provides a comparable to Puppeteer experience. And, what’s more important for us, it ships with a companion project called Cuprite—a pure Ruby Capybara driver using CDP.
    1. Same feature in TypeScript¶ It's worth mentioning that other languages have a shortcut for assignment var assignment directly from constructor parameters. So it seems especially painful that Ruby, despite being so beautifully elegant and succinct in other areas, still has no such shortcut for this. One of those other languages (CoffeeScript) is dead now, but TypeScript remains very much alive and allows you to write this (REPL): class Foo { constructor(public a:number, public b:number, private c:number) { } } instead of this boilerplate: class Foo { constructor(a, b, c) { this.a = a; this.b = b; this.c = c; } } (The public/private access modifiers actually disappear in the transpiled JavaScript code because it's only the TypeScript compiler that enforces those access modifiers, and it does so at compile time rather than at run time.) Further reading: https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties https://basarat.gitbook.io/typescript/future-javascript/classes#define-using-constructor https://kendaleiv.com/typescript-constructor-assignment-public-and-private-keywords/ I actually wouldn't mind being able to use public/private modifiers on instance var parameters in Ruby, too, but if we did, I would suggest making that be an additional optional shortcut (for defining accessor methods for those instance vars) that builds on top of the instance var assignment parameter syntax described here. (See more detailed proposal in #__.) Accessors are more of a secondary concern to me: we can already define accessors pretty succinctly with attr_accessor and friends. The bigger pain point that I'm much more interested in having a succinct shortcut for is instance var assignment in constructors. initialize(@a, @b, @c) syntax¶ jsc (Justin Collins) wrote in #note-12: jjyr (Jinyang Jiang) wrote: I am surprised this syntax has been repeatedly requested and rejected since 7 years ago. ... As someone who has been writing Ruby for over 10 years, this syntax is exactly that I would like. I grow really tired of writing def initialize(a, b, c) @a = a @b = b @c = c end This would be perfect: def initialize(@a, @b, @c) end I'm a little bit sad Matz is against this syntax, as it seems so natural to me. Me too!! I've been writing Ruby for over 15 years, and this syntax seems like the most obvious, simple, natural, clear, unsurprising, and Ruby-like. I believe it would be readily understood by any Rubyist without any explanation required. Even if you saw it for the first time, I can't think of any way you could miss or misinterpret its meaning: since @a is in the same position as a local variable a would normally be, it seems abundantly clear that instead of assigning to a local variable, we're just assigning to the variable @a instead and of course you can reference the @a variable in the constructor body, too, exactly the same as you could with a local variable a passed as an argument. A workaround pattern¶ In the meantime, I've taken to defining my constructor and list of public accessors (if any) like this: attr_reader \ :a, :b def new( a, b) @a, @b = a, b end ... which is still horrendously boilerplatey and ugly, and probably most of you will hate — but by lining up the duplicated symbols into a table of columns, I like that I can at least more easily see the ugly duplication and cross-check that I've spelled them all correctly and handled them all consistently. :shrug: Please??¶ Almost every time I write a new class in Ruby, I wish for this feature and wonder if we'll ever get it. Can we please?
    2. I am not sure if this is an improvement. To me it does not seem very pretty. Of course I am biased since I also prefer () in method definitions if they have arguments; although I think it is fine that ruby does not mind omitting the (). For my brain, I like the () for visual separation.
    1. When defining accessors in Ruby, there can be a tension between brevity (which we all love) and best practice.
    2. in languages (like JavaScript and Java) where external objects do have direct access to instance vars
    3. But what's the matter with "raw" instance variables? They are internal to your instance; the only code that will call them by name is code inside pancake.rb which is all yours. The fact that they start with @, which I assume made you say "blech", is what makes them private. Think of @ as shorthand for private if you like.

      I agree / like that: @ is just shorthand for private.

      But OP clarified in a comment that the @ itself is not what they disliked: it was the accessing data directly instead of going through an accessor method.

      The raw variable is the implementation, the accessor is the interface. Should I ignore the interface because I'm internal to the instance?

    4. class << Object def private_accessor(*names) names.each do |name| attr_accessor name private "#{name}=" end end end
    5. Setting an instance variable by going through a setter is good practice, and using two access modifiers is the way to accomplish that for a read-only instance variable
    1. I don't think this warrants adding to the Array class, since it's not generalizable to all the types that Arrays can contain.

      You could say the same thing about Array#sort. It can cause an error if elements of the array aren't all of the same type/shape. Just make sure it's safe to use first, and thenArray#sort, Array#sum, Array#average, ... are all quite handy and useful to have on Array class.

    2. That's not exactly Symbol#to_proc conversion — it's part of the inject interface, mentioned in the documentation. The to_proc operator is &
    3. instance_eval { reduce(:+) / size.to_f }
    4. I don't think it is too clever. I think it solves the problem idiomatically. I.e., it uses reduce, which is exactly correct. Programmers should be encouraged to understand what is correct, why it is correct, and then propagate. For a trivial operation like average, true, one doesn't need to be "clever". But by understanding what "reduce" is for a trivial case, one can then start applying it to much more complex problems. upvote.
    5. Thanks, this was just what I was looking for! This is a perfect appropriate use of instance_eval. I do not understand the nay-sayers. If you already have your array in a variable, then sure, a.reduce(:+) / a.size.to_f is pretty reasonable. But if you want to "in line" find the mean of an array literal or an array that is returned from a function/expression — without duplicating the entire expression ([0,4,8].reduce(:+) / [0,4,8].length.to_f, for example, is abhorrent) or being required to assign to a local, then instance_eval option is a beautiful, elegant, idiomatic solution!!
    6. instance_eval is analogous to using tap, yield_self, … when you are dealing with a chain of method calls: do use it whenever it's appropriate and helpful! And in this case, I absolutely believe that it is.
    7. instance_eval lets you run the code while only specifying a once, so it can be chained with other commands. I.e. random_average = Array.new(10) { rand(10) }.instance_eval { reduce(:+) / size.to_f } instead of random = Array.new(10) { rand(10) }; random_average = random.reduce(:+) / random.size
    8. I don't know, using instance_eval this way just seems weird, and it has a lot of gotchas associated with it that make this approach a bad idea, IMO. (For example, if you tried to access and instance variable or a method on self inside that block, you'd run into problems.) instance_eval is more for metaprogramming or DSL.

      But that's exactly when/why you'd use it: to make self refer to the instance! Just learn that and you'll be fine. You can still access locals from outside the block. And if you need to access instance variables/methods of a different instance, then sure, it's probably a sign you shouldn't be using instance_eval here.

    9. Or if you're looking for a core extension that adds this to the Array class, I'd recommend the facets gem (require 'facets/array/average'). Then you can just do array.average. And, from looking at the source, it turns out they do the exact same thing as the instance_eval approach above. The only difference is that it's implemented as a method—which of course already has self pointing to itself—instead of a block): def average; return nil if empty?; reduce(:+) / length.to_f; end Main advantage of this is that it's even more concise/readable and it handles the empty? case.
  17. May 2021
    1. Because constants in Ruby aren't meant to be changed, Ruby discourages you from assigning to them in parts of code which might get executed more than once, such as inside methods.
  18. Apr 2021
    1. It seems inelegant to me to split this into two different modules, one to include, the other to extend.

      the key thing (one of them) to understand here is that: class methods are singleton methods

    2. Another possible solution would be to use a class Common instead of a module. But this is just a workaround.
    3. Trust this answer. This is a very common idiom in Ruby, solving precisely the use case you ask about and for precisely the reasons you experienced. It may look "inelegant", but it's your best bet.
    1. Apparently when you create a subclass, that subclass's singleton class has # its superclass's singleton class as an ancestor.

      This is a good thing. It allows class methods to be inherited by subclasses.

    2. at least in recent versions of Ruby, calling ancestors on the singleton class does show the other singleton classes.
    3. I played around with something to give me the list of receivers for any Ruby object in my introspection gem. If you load the "introspection/receivers" file you get a method #receivers on any object which gives you the whole receiver chain.
  19. Mar 2021
    1. Not enjoying Xcode, Amir used RubyMotion instead. Amir had real-world experience with Xcode and Objective-C, but didn't like it at all. Amir also has a Ruby background and went with RubyMotion to build A Dark Room. The command-line interface, the testing framework, the gems libraries and the CocoaPods integration and the freedom to use any text editor contributed to his decision.