From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS4713 221.184.0.0/13 X-Spam-Status: No, score=-2.6 required=3.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_MED,SPF_PASS,T_RP_MATCHES_RCVD shortcircuit=no autolearn=no autolearn_force=no version=3.4.0 Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by dcvr.yhbt.net (Postfix) with ESMTP id 105B91F404 for ; Wed, 10 Jan 2018 16:06:15 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id 3B65E1209E3; Thu, 11 Jan 2018 01:06:10 +0900 (JST) Received: from o1678948x4.outbound-mail.sendgrid.net (o1678948x4.outbound-mail.sendgrid.net [167.89.48.4]) by neon.ruby-lang.org (Postfix) with ESMTPS id 9E9651209CA for ; Thu, 11 Jan 2018 01:06:06 +0900 (JST) Received: by filter0015p3las1.sendgrid.net with SMTP id filter0015p3las1-11011-5A5639DF-5A 2018-01-10 16:05:52.045769607 +0000 UTC Received: from herokuapp.com (ec2-54-92-164-93.compute-1.amazonaws.com [54.92.164.93]) by ismtpd0010p1iad2.sendgrid.net (SG) with ESMTP id wB5aDUlbTmujpX7VOhBP1g Wed, 10 Jan 2018 16:05:51.958 +0000 (UTC) Date: Wed, 10 Jan 2018 16:06:01 +0000 (UTC) From: kevin.deisz@gmail.com To: ruby-core@ruby-lang.org Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 60047 X-Redmine-Project: ruby-trunk X-Redmine-Issue-Id: 14344 X-Redmine-Issue-Author: kddeisz X-Redmine-Sender: kddeisz X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: ync6xU2WACa70kv/Ymy4QrNMhiuLXJG8OTL2vJD1yS7hCLleRKw8yrT2i792H5fo73BxgSaEttkCyf qShg7HMNvf/JgUN8myJqo/dljKMzqJOL+4DzkkhZxDqBPQJCJIoQAUeVGkWy00vtkMKPrrPu3jOxRw cLdSkor+zlfUIm+77lFNjYgGOwWozAxT5c6lfy9I2pfeiQ4LeqLbx8xYSA== X-ML-Name: ruby-core X-Mail-Count: 84814 Subject: [ruby-core:84814] [Ruby trunk Feature#14344] refine at class level X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #14344 has been updated by kddeisz (Kevin Deisz). Just to take a real example from my current application, here's a job (from Rails ActiveJob) that I want to refine by moving the logic into the class in which it belongs. It currently looks like this: ~~~ruby class EventEndActionsJob < ApplicationJob queue_as :default def perform(event) return if event.end_actions_completed? event.update!(end_actions_completed: true) activate_survey_for(event) if event.survey end private def activate_survey_for(event) event.survey.update!(active: true) event.rsvps.not_declined.each do |rsvp| EmailJob.perform_later('PostEventSurvey', rsvp) end end end ~~~ but I want it to look like this: ~~~ ruby class EventEndActionsJob < ApplicationJob refine Event do def perform_end_actions return if end_actions_completed? update!(end_actions_completed: true) activate_survey if survey end private def activate_survey survey.update!(active: true) rsvps.not_declined.each do |rsvp| EmailJob.perform_later('PostEventSurvey', rsvp) end end end queue_as :default def perform(event) event.perform_end_actions end end ~~~ now all of the logic is in the right place (in the Event model) but I don't have to clutter up the class definition with a method that will only be used in this one place. I don't need to refine multiple classes, so I don't want to build a whole module, but instead right now I have to: ~~~ruby class EventEndActionsJob < ApplicationJob using( Module.new do refine Event do def perform_end_actions return if end_actions_completed? update!(end_actions_completed: true) activate_survey if survey end private def activate_survey survey.update!(active: true) rsvps.not_declined.each do |rsvp| EmailJob.perform_later('PostEventSurvey', rsvp) end end end end ) queue_as :default def perform(event) event.perform_end_actions end end ~~~ ---------------------------------------- Feature #14344: refine at class level https://bugs.ruby-lang.org/issues/14344#change-69528 * Author: kddeisz (Kevin Deisz) * Status: Open * Priority: Normal * Assignee: * Target version: ---------------------------------------- I rely on refinements a lot, but don't want to keep writing `Module.new` in code. I'm proposing `Object::refine`, which would create an anonymous module behind the scenes with equivalent functionality. So: ~~~ ruby class Test using Module.new { refine String do def refined? true end end } end ~~~ would become ~~~ ruby class Test refine String do def refined? true end end end ~~~ It's a small change, but reads a lot more clearly. Thoughts? -- https://bugs.ruby-lang.org/