Qué es attr accessor en Ruby?


Estoy teniendo dificultades para entender attr_accessor en Ruby. ¿Alguien puede explicarme esto?

 889
Author: codeforester, 2010-12-07

18 answers

Digamos que tienes una clase Person.

class Person
end

person = Person.new
person.name # => no method error

Obviamente nunca definimos el método name. Hagámoslo.

class Person
  def name
    @name # simply returning an instance variable @name
  end
end

person = Person.new
person.name # => nil
person.name = "Dennis" # => no method error

Aha, podemos leer el nombre, pero eso no significa que podamos asignar el nombre. Esos son dos métodos diferentes. El primero se llama lector, y el segundo se llama escritor. Aún no creamos al escritor, así que hagámoslo.

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Dennis'
person.name # => "Dennis"

Impresionante. Ahora podemos escribir y leer variable de instancia @name usando los métodos reader y writer. Excepto, esto se hace con tanta frecuencia, ¿por qué perder el tiempo escribiendo estos métodos cada vez? Podemos hacerlo más fácil.

class Person
  attr_reader :name
  attr_writer :name
end

Incluso esto puede volverse repetitivo. Cuando usted quiere lector y escritor solo tiene que utilizar accessor!

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Dennis"
person.name # => "Dennis"

Funciona de la misma manera! Y adivina qué: la variable de instancia @name en nuestro objeto person se establecerá como cuando lo hicimos manualmente, por lo que puede usarlo en otros métodos.

class Person
  attr_accessor :name

  def greeting
    "Hello #{@name}"
  end
end

person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"

Eso es todo. Para entender cómo attr_reader, attr_writer, y attr_accessor métodos en realidad generar métodos para usted, leer otras respuestas, libros, ruby docs.

 2080
Author: Max Chernyak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-10 21:28:46

Attr_accessor es solo un método. (El enlace debe proporcionar más información sobre cómo funciona - mire los pares de métodos generados, y un tutorial debe mostrarle cómo usarlo.)

El truco es que class es no una definición en Ruby (es "solo una definición" en lenguajes como C++ y Java), sino que es una expresión que evalúa. Es durante esta evaluación cuando se invoca el método attr_accessor que a su vez modifica la clase actual - recuerde el receptor implícito: self.attr_accessor, donde self es el objeto de clase "open" en este punto.

La necesidad de attr_accessor y amigos, es, bueno:

  1. Ruby, al igual que Smalltalk, no permite que se acceda a variables de instancia fuera de los métodos1 por ese objeto. Es decir, no se puede acceder a las variables de instancia en la forma x.y como es común en, por ejemplo, Java o incluso Python. En Ruby y siempre se toma como un mensaje a enviar (o"método a llamar"). Así los métodos attr_* crear envoltorios que proxy la instancia @variable acceso a través de métodos creados dinámicamente.

  2. [14]} {[29]]}

Espero que esto aclare algunos de los pequeños detalles. Feliz codificación.


1 Esto no es estrictamente cierto y hay algunas "técnicas" alrededor de este , pero no hay soporte de sintaxis para el acceso de "variable de instancia pública".

 115
Author: Community,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:48

attr_accessor es (como se indica @pst) solo un método. Lo que hace es crear más métodos para usted.

Así que este código aquí:

class Foo
  attr_accessor :bar
end

Es equivalente a este código:

class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end

Puedes escribir este tipo de método tú mismo en Ruby:

class Module
  def var( method_name )
    inst_variable_name = "@#{method_name}".to_sym
    define_method method_name do
      instance_variable_get inst_variable_name
    end
    define_method "#{method_name}=" do |new_value|
      instance_variable_set inst_variable_name, new_value
    end
  end
end

class Foo
  var :bar
end

f = Foo.new
p f.bar     #=> nil
f.bar = 42
p f.bar     #=> 42
 63
Author: Phrogz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-06 21:29:34

attr_accessor es muy simple:

attr_accessor :foo

Es un atajo para:

def foo=(val)
  @foo = val
end

def foo
  @foo
end

No es más que un getter/setter para un objeto

 35
Author: efalcao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-06 21:28:47

Básicamente falsifican atributos de datos de acceso público, que Ruby no tiene.

 17
Author: Tyler Eaves,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-06 21:11:11

Es solo un método que define los métodos getter y setter por ejemplo variables. Un ejemplo de aplicación sería:

def self.attr_accessor(*names)
  names.each do |name|
    define_method(name) {instance_variable_get("@#{name}")} # This is the getter
    define_method("#{name}=") {|arg| instance_variable_set("@#{name}", arg)} # This is the setter
  end
end
 17
Author: Chuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-06 21:29:29

También me enfrenté a este problema y escribí una respuesta algo larga a esta pregunta. Hay algunas grandes respuestas sobre esto ya, pero cualquiera que busque más aclaraciones, espero que mi respuesta pueda ayudar

Método de inicialización

Initialize le permite establecer datos en una instancia de un objeto al crear la instancia en lugar de tener que establecerlos en una línea separada en su código cada vez que crea una nueva instancia de la clase.

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end


  def greeting
    "Hello #{@name}"
  end
end

person = Person.new("Denis")
puts person.greeting

En el código anterior estamos establecer el nombre "Denis" usando el método initialize pasando Dennis a través del parámetro en Initialize. Si queríamos establecer el nombre sin el método initialize, podríamos hacerlo así:

class Person
  attr_accessor :name

  # def initialize(name)
  #     @name = name
  # end

  def greeting
    "Hello #{name}"
  end
end

person = Person.new
person.name = "Dennis"
puts person.greeting

En el código anterior, establecemos el nombre llamando al método attr_accessor setter usando person.name, en lugar de establecer los valores al inicializar el objeto.

Ambos "métodos" de hacer este trabajo, pero inicializar nos ahorra tiempo y líneas de código.

Este es el único trabajo de inicializar. No se puede llamar a initialize como método. Para conseguir realmente los valores de un objeto de instancia deberá utilizar getters y setters (attr_reader (get), attr_writer(set), y attr_accessor(ambos)). Vea a continuación para más detalles sobre ellos.

Getters, Setters (attr_reader, attr_writer, attr_accessor)

Getters, attr_reader: Todo el propósito de un getter es devolver el valor de una variable de instancia en particular. Visite el siguiente código de ejemplo para obtener un desglose al respecto.

class Item

  def initialize(item_name, quantity)
    @item_name = item_name
    @quantity = quantity
  end

  def item_name
    @item_name
  end

  def quantity
     @quantity
  end
end

example = Item.new("TV",2)
puts example.item_name
puts example.quantity

En el código anterior está llamando a los métodos "item_name" y "quantity" en la instancia de Item "example". El " pone ejemplo.item_name" y "ejemplo.quantity "devolverá (o "get") el valor de los parámetros que se pasaron al "ejemplo" y los mostrará en la pantalla.

Afortunadamente en Ruby hay un método inherente que nos permite escribir este código de manera más sucinta; el método attr_reader. Véase el código que figura a continuación;

class Item

attr_reader :item_name, :quantity

  def initialize(item_name, quantity)
    @item_name = item_name
    @quantity = quantity
  end

end

item = Item.new("TV",2)
puts item.item_name
puts item.quantity

Esta sintaxis funciona exactamente de la misma manera, sólo que nos ahorra seis líneas de código. Imagina si tuvieras 5 estado más atribuible a la clase de Artículo? El código se alargaría rápidamente.

Setters, attr_writer: Lo que me cruzó al principio con los métodos setter es que a mis ojos parecía realizar una función idéntica al método initialize. A continuación explico la diferencia basada en mi comprensión;

Como se indicó anteriormente, el método initialize le permite establecer los valores para una instancia de un objeto tras otro creación.

Pero, ¿qué pasa si desea establecer los valores más tarde, después de que se creó la instancia, o cambiarlos después de que se hayan inicializado? Este sería un escenario en el que se utilizaría un método setter. ESA ES LA DIFERENCIA. No tiene que "establecer" un estado particular cuando está utilizando el método attr_writer inicialmente.

El siguiente código es un ejemplo del uso de un método setter para declarar el valor item_name para esta instancia de la clase Item. Note que continuamos utilice el método getter attr_reader para que podamos obtener los valores e imprimirlos en la pantalla, en caso de que desee probar el código por su cuenta.

class Item

attr_reader :item_name

  def item_name=(str)
    @item_name = (str)
  end

end

El siguiente código es un ejemplo de uso de attr_writer para acortar nuevamente nuestro código y ahorrarnos tiempo.

class Item

attr_reader :item_name
attr_writer :item_name

end

item = Item.new
puts item.item_name = "TV"

El siguiente código es una reiteración del ejemplo de inicializar anterior de donde estamos usando initialize para establecer el valor de los objetos item_name en el momento de la creación.

class Item

attr_reader :item_name

  def initialize(item_name)
    @item_name = item_name
  end

end

item = Item.new("TV")
puts item.item_name

Attr_accessor: Realiza las funciones de ambos attr_reader y attr_writer, ahorrándote una línea más de código.

 12
Author: Jbur43,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-05 00:12:45

Creo que parte de lo que confunde a los nuevos rubistas/programadores (como yo) es:

"¿Por qué no puedo simplemente decirle a la instancia que tiene cualquier atributo dado (por ejemplo, nombre) y darle a ese atributo un valor todo de una sola vez?"

Un poco más generalizado, pero así es como hizo clic para mí:

Dado:

class Person
end

No hemos definido a Person como algo que puede tener un nombre o cualquier otro atributo para el caso.

Así que si entonces:

baby = Person.new

...y tratar de dales un nombre...

baby.name = "Ruth"

Obtenemos un error porque, en Rubyland, una clase Person de objeto no es algo que esté asociado o sea capaz de tener un "nombre" ... ¡todavía!

PERO podemos usar cualquiera de los métodos dados (ver respuestas anteriores) como una forma de decir, "Una instancia de una clase Person (baby) ahora puede tener un atributo llamado 'nombre', por lo tanto, no solo tenemos una forma sintáctica de obtener y establecer ese nombre, sino que tiene sentido para nosotros hacer tan."

Nuevamente, golpeando esta pregunta desde un ángulo ligeramente diferente y más general, pero espero que esto ayude a la siguiente instancia de Persona de clase que encuentre su camino a este hilo.

 10
Author: Ben,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-26 01:24:36

Si está familiarizado con el concepto OOP, debe estar familiarizado con el método getter y setter. attr_accessor hace lo mismo en Ruby.

Getter y Setter en General

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"

Método Setter

def name=(val)
  @name = val
end

Método Getter

def name
  @name
end

Método Getter y Setter en Ruby

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"
 10
Author: Ahmed Eshaan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-04 14:59:39

La mayoría de las respuestas anteriores usan código. Esta explicación intenta responder sin usar ningún código:

Explicación por analogía

Las partes externas no pueden acceder a los secretos internos de la CIA

  • Imaginemos un lugar realmente secreto: la CIA. Nadie sabe lo que está pasando en la CIA aparte de la gente dentro de la CIA. En otras palabras, las personas externas no pueden acceder a ninguna información en la CIA. Pero porque no es bueno tener una organización que es completamente secreto, cierta información está disponible para el mundo exterior, solo cosas que la CIA quiere que todos sepan, por supuesto: por ejemplo, el Director de la CIA, qué tan amigable con el medio ambiente se compara este departamento con todos los demás departamentos gubernamentales, etc. Otra información: por ejemplo, quiénes son sus agentes encubiertos en Irak o Afganistán-este tipo de cosas probablemente permanecerán en secreto durante los próximos 150 años.

  • Si estás fuera de la CIA sólo puedes acceder la información que haya puesto a disposición del público. O para usar el lenguaje de la CIA, solo puede acceder a la información que está "despejada".

  • La información que la CIA quiere poner a disposición del público en general fuera de la CIA se llama: atributos.

El significado de leer y escribir atributos:

  • En el caso de la CIA, la mayoría de los atributos son de "solo lectura". Esto significa que si usted es un partido externo a la CIA, puedes preguntar: "¿quién es el director de la CIA?"y obtendrás una respuesta directa. Pero lo que no puede hacer con atributos de "solo lectura" es hacer cambios en la CIA. por ejemplo, no puedes hacer una llamada telefónica y de repente decidir que quieres que Kim Kardashian sea la Directora, o que quieres que Paris Hilton sea el Comandante en Jefe.

  • Si los atributos le dieron acceso de "escritura", entonces podría hacer cambios si lo desea, incluso si lo estuviera fuera. De lo contrario, lo único que puedes hacer es leer.

    En otras palabras, los accesores le permiten realizar consultas, o realizar cambios, a organizaciones que de otro modo no permiten la entrada de personas externas, dependiendo de si los accesores son de lectura o escritura.

Los objetos dentro de una clase pueden acceder fácilmente entre sí

  • Por otro lado, si ya estuvieras dentro de la CIA, entonces podrías llamar fácilmente a tu agente de la CIA en Kabul y pregúntale si quiere tomar una cerveza con el informante local de Kabul después del trabajo. Pero si estás fuera de la CIA, simplemente no se te dará acceso: no podrás saber quiénes son (acceso de lectura), y no podrás cambiar su misión (acceso de escritura).

Exactamente lo mismo con las clases y su capacidad para acceder a variables, propiedades y métodos dentro de ellas. HTH! Cualquier pregunta, por favor pregunte y espero poder aclarar.

 10
Author: BKSpurgeon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-15 13:56:04

Simplemente definirá un setter y un getter para la clase.

Tenga en cuenta que

attr_reader :v is equivalant to 
def v
  @v
end

attr_writer :v is equivalant to
def v=(value)
  @v=value
end

So

attr_accessor :v which means 
attr_reader :v; attr_writer :v 

Son equivalentes para definir un setter y un getter para la clase.

 7
Author: Marcus Thornton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-12 08:30:42

Simplemente attr-accessor crea los métodos getter y setter para los atributos especificados

 5
Author: Veeru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-17 11:05:49

Otra forma de entenderlo es averiguar qué código de error elimina al tener attr_accessor.

Ejemplo:

class BankAccount    
  def initialize( account_owner )
    @owner = account_owner
    @balance = 0
  end

  def deposit( amount )
    @balance = @balance + amount
  end

  def withdraw( amount )
    @balance = @balance - amount
  end
end

Los siguientes métodos están disponibles:

$ bankie = BankAccout.new("Iggy")
$ bankie 
$ bankie.deposit(100)
$ bankie.withdraw(5)

Los siguientes métodos arrojan error:

$ bankie.owner     #undefined method `owner'... 
$ bankie.balance   #undefined method `balance'...

owner y balance no son, técnicamente, un método, sino un atributo. La clase BankAccount no tiene def owner y def balance. Si lo hace, entonces puede usar los dos comandos a continuación. Pero esos dos métodos no están ahí. Sin embargo, usted puede access atributos como si access un método a través de attr_accessor!! De ahí la palabra attr_accessor. Atributo. Accessor. Accede a atributos como accederías a un método.

Agregar attr_accessor :balance, :owner le permite leer y escribir balance y owner "método". Ahora puedes usar los últimos 2 métodos.

$ bankie.balance
$ bankie.owner
 4
Author: Iggy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-13 18:26:41

Define un atributo con nombre para este módulo, donde el nombre es symbol.id2name, creando una variable de instancia (@name) y un método de acceso correspondiente para leerla. También crea un método llamado name= para establecer el atributo.

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]
 2
Author: Praveen_Shukla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-11 16:12:37

Para resumir un atributo accessor aka attr_accessor le da dos métodos libres.

Como en Java se llaman getters y setters.

Muchas respuestas han mostrado buenos ejemplos, así que voy a ser breve.

# the_attribute

Y

# the_attribute =

En los antiguos documentos de ruby una etiqueta hash # significa un método. También podría incluir un prefijo de nombre de clase... MyClass # my_method

 1
Author: Douglas G. Allen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-14 03:56:47

Atributos y métodos de acceso

Los atributos son componentes de clase a los que se puede acceder desde fuera del objeto. Se conocen como propiedades en muchos otros lenguajes de programación. Sus valores son accesibles usando la "notación de puntos", como en nombre_objeto.attribute_name. A diferencia de Python y algunos otros lenguajes, Ruby no permite acceder a variables de instancia directamente desde fuera del objeto.

class Car
  def initialize
    @wheels = 4  # This is an instance variable
  end
end

c = Car.new
c.wheels     # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>

En el ejemplo anterior, c es una instancia (objeto) de la clase Car. Intentamos sin éxito leer el valor de la variable de instancia wheels desde fuera del objeto. Lo que sucedió es que Ruby intentó llamar a un método llamado wheels dentro del objeto c, pero no se definió dicho método. En resumen, object_name.attribute_name intenta llamar a un método llamado attribute_name dentro del objeto. Para acceder al valor de la variable wheels desde el exterior, necesitamos implementar un método de instancia con ese nombre, que devolverá el valor de esa variable cuando se llame. Eso es llamado método de accessor. En el contexto de programación general, la forma habitual de acceder a una variable de instancia desde fuera del objeto es implementar métodos de acceso, también conocidos como métodos getter y setter. Un getter permite que el valor de una variable definida dentro de una clase se lea desde el exterior y un setter permite que se escriba desde el exterior.

En el siguiente ejemplo, hemos agregado los métodos getter y setter a la clase Car para acceder a la variable wheels desde fuera del objeto. Esta no es la" forma Ruby " de definir getters y setters; solo sirve para ilustrar lo que hacen los métodos getter y setter.

class Car
  def wheels  # getter method
    @wheels
  end

  def wheels=(val)  # setter method
    @wheels = val
  end
end

f = Car.new
f.wheels = 4  # The setter method was invoked
f.wheels  # The getter method was invoked
# Output: => 4

El ejemplo anterior funciona y código similar se usa comúnmente para crear métodos getter y setter en otros lenguajes. Sin embargo, Ruby proporciona una forma más sencilla de hacer esto: tres métodos integrados llamados attr_reader, attr_writer y attr_cessor. El método attr_reader hace que una variable de instancia sea legible desde el exterior, attr_writer la hace escribible, y attr_cessor lo hace legible y escribible.

El ejemplo anterior se puede reescribir así.

class Car
  attr_accessor :wheels
end

f = Car.new
f.wheels = 4
f.wheels  # Output: => 4

En el ejemplo anterior, el atributo wheels será legible y escribible desde fuera del objeto. Si en lugar de attr_accessor, usáramos attr_reader, sería de solo lectura. Si usamos attr_writer, sería solo escritura. Esos tres métodos no son getters y setters en sí mismos, pero, cuando se llaman, crean métodos getter y setter para nosotros. Son métodos que dinámicamente (programáticamente) generar otros métodos; eso se llama metaprogramación.

El primer ejemplo (más largo), que no emplea los métodos integrados de Ruby, solo debe usarse cuando se requiere código adicional en los métodos getter y setter. Por ejemplo, un método setter puede necesitar validar datos o hacer algún cálculo antes de asignar un valor a una variable de instancia.

Es posible acceder (leer y escribir) variables de instancia desde fuera del objeto, utilizando el instance_variable_get y instance_variable_set métodos integrados. Sin embargo, esto rara vez es justificable y generalmente es una mala idea, ya que evitar la encapsulación tiende a causar todo tipo de estragos.

 0
Author: BrunoFacca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-05 11:41:58

Hmmm. Muchas buenas respuestas. Aquí están mis centavos.

  • attr_accessor es un método simple que nos ayuda en la limpieza (SECADO ) hasta el repitiendo getter and setter métodos.

  • Para que podamos centrarnos más en escribir lógica de negocios y no preocuparnos por los setters y getters.

 -1
Author: Abibullah Rahamathulah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-29 09:50:08

La funcionalidad principal de attr_accessor sobre los otros es la capacidad de acceder a los datos de otros archivos.
Así que normalmente tendrías attr_reader o attr_writer pero la buena noticia es que Ruby te permite combinar estos dos junto con attr_accessor. Pienso en ello como mi método para ir porque es más redondeado o versátil. Además, peep en mente que en Rails, esto se elimina porque lo hace por ti en el back-end. Así que en otras palabras: mejor usar attr_cessor sobre los otros dos porque no tienes que preocuparte por ser específico, el accessor lo cubre todo. Sé que esto es más una explicación general, pero me ayudó como principiante.

Espero que esto haya ayudado!

 -3
Author: creativegeek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-17 15:40:55