signo rails punteros libro lenguaje identificadores español documentacion desde ruby-on-rails ruby syntax

ruby-on-rails - punteros - ruby on rails vs php



undef-¿Por qué querrías definir un método en rubí? (7)

La definición de métodos, clases y objetos en tiempo de ejecución es una característica muy buena de Ruby. Te permite extender clases (recuerda que están "abiertas"). Si observa Rails, tiene un método #find para encontrar objetos en un modelo, pero también puede usar find_by_user ; ese método no existe (por #method_missing se llama #method_missing ) pero se crea en tiempo de ejecución.

Si desea crear un lenguaje específico de dominio o DSL, usar #missing_method puede ser útil.

Nunca he visto undef, o cualquier otra cosa que te permita descifrar un método, en cualquier otro lenguaje de programación. ¿Por qué es necesario en Ruby?

EDITAR: No estoy argumentando que haya nada de malo en esto. Simplemente no entiendo el propósito de definir métodos en tiempo de ejecución? ¿Cuál es el propósito de eso? ¿Cómo se usa? Nunca he hecho esto en C o Java.


Puede ver todos los Rails para ver ejemplos de métodos de definición en tiempo de ejecución (también conocido como metaprogramación). Al invocar un método en la definición de su clase, puede definir un montón de métodos para todas las instancias de esa clase ...


La técnica de incluir módulos según sea necesario se relaciona con la definición de métodos en tiempo de ejecución. Trabajo en una aplicación de Rails donde a veces tenemos que exportar datos en varios formatos. El 99% de las veces, el objeto Formulario no necesita métodos relacionados con la exportación, pero en nuestra tarea de exportación de Rake, hacemos algo como:

Form.send(:include, FormExportingMethods)

Entonces solo tiene esos métodos cuando los necesita.

Este tipo de dinamismo es una de las cosas que amo de Ruby. Mientras que en algunos idiomas, tienes que definir tus clases y objetos al principio, Ruby te permite decir "oh, necesito que mi cerdo tenga alas ahora mismo". Simplemente las adjuntaré ".

Observe en mi ejemplo que los objetos de formulario específicos no están siendo modificados; la clase de forma es. Esto funciona porque, cuando envías un mensaje a un objeto, busca una respuesta en la cadena de búsqueda de métodos en el momento en que lo pides . Entonces puede crear un objeto, luego agregar un método en cualquier lugar de su cadena de herencia, luego llamar al método en el objeto y lo tendrá. Obviamente, tener que revisar toda la cadena de herencia para cada método es costoso, pero es una compensación para este tipo de flexibilidad.


Si usa herencia de tabla única con un ORM, como ActiveRecord, puede definir los métodos para los campos que no se utilizan para una clase / objeto en particular.

# table: shapes, with columns: name, sides, radius, type class Shape < ActiveRecord::Base end class Circle < Shape end class Square < Shape undefine_method :radius end

Nota: Esto realmente no funciona en ActiveRecord ya que internamente espera que siempre se defina un método para cada campo.

Nota: Un cuadrado tiene un radio que no se usa comúnmente, pero ¿entiendes? Piense en alguna propiedad que guarde en la base de datos que tiene un círculo, pero no en un cuadrado.


Estoy consumiendo una API externa, y una de las respuestas de JSON contiene un campo llamado "métodos". Estoy creando un OpenStruct alrededor del json, solo para hacer que el json sea más manejable. Al llamar a openStruct.methods, devuelve el resultado del método de instancia de objeto "métodos".

Así que lo hice:

class MyOpenStruct < OpenStruct def methods end undef :methods end openStruct = OpenStruct.new(my_json)


He visto esto usado junto con Mixins; para que pueda incluir todo y luego determinar los métodos que no debería admitir ... por ejemplo, los zapatos de la biblioteca gráfica de ruby.

La clase de button mezcla en el módulo undef y luego undef está disponible el método de release porque los botones no lo admiten.

Otro ejemplo rápido, por lo que está disponible aquí:

module Walkable attr_accessor :location def walk(steps) @location += steps end def walk_back(steps) @location -= steps end end class Zombie include Walkable undef walk_back #zombies can only walk forwards end


También está el patrón de clase en blanco en Ruby que necesita la funcionalidad undef .

La idea es eliminar todos los métodos de tu nueva clase para que cada llamada que hagas termine en #method_missing . De esta forma, puede implementar un proxy real que simplemente lo revuelve todo. Implementar el patrón de decorador con esto es alrededor de diez líneas de código, sin importar cuán grande sea su clase objetivo.

Si quieres ver ese modismo en acción, mira uno de los marcos de burla de Ruby, lo usan mucho. Algo así como flexmock .

Otro ejemplo es cuando agrega funciones dinámicamente a una clase basada en alguna condición. En un juego puedes agregar un método #attack al objeto del jugador y luego quitárselo cuando está paralizado en lugar de hacerlo con una bandera booleana. De esta forma, la clase llamante puede verificar la disponibilidad del método y no la bandera. No estoy diciendo que esto sea una buena idea, solo que es posible y que hay personas mucho más inteligentes que yo que tengo algo útil que hacer con esto.