RV: Filtrar con Ajax Scaffold

Hola Luis. He estado un par de días liado con otro tema. Volvemos al
ataque.

Efectivamente el controlador se llama préstamos y la función se llama
actualizaCapaPrestamos(). Te pasé el código que me enviaste tú
directamente sin modificarlo.

Respecto a la línea siguiente, cuando dices, que debería ir en otro
fichero .rhtml, ¿en cuál?

En cuanto al filtrado que quiero establecer intentaré explicarme. Tengo
una serie de préstamos de portátiles en los cuales quiero filtrar
mediante un combo la situación de los mismos. El combo tiene tres
valores: Abierto, Cerrado y Todos, con valores 1, 2 y 3 respectivamente

En el modelo existe un campo denominado fecha_devolucion que es por el
que quiero filtrar. Cuando selecciono Abierto sólo mostraré los
registros donde ese campo esté a null (vacío - aún no han devuelto los
portátiles), Cuando seleccione Cerrado, mostraré los que ya han sido
entregados, por tanto fecha_devolucion distinta de null y en Todos, pues
lo dicho Todos (fecha_devolucion <> 01/01/1900 por ejemplo.

La tabla está en Mysql y los campos fechas son del tipo Date, y el campo
fecha_devolucion está definido que puede ser null.

En el fichero app/views/prestamos/component.rhtml he definido el combo
de la siguiente forma:

Incidencias -

  <span style="font-size:18px;font-weight:bold;">Estado:

    <select name="filtro_estado" id="filtro_estado" 

onchange=“actualizaCapaPrestamos()”>

        <option value ="1">

            Abiertos

        </option>

        <option value ="2">

            Cerrados

        </option>

        <option value = "3">

            Todos

        </option>

    </select>

</span>

Fernando González Macías

fgonzalez @ grupojoly.com

Dpto. Informática Diario de Cádiz

(Grupo Joly)


De: [email protected]
[mailto:[email protected]] En nombre de Luis
Villegas
Enviado el: martes, 06 de marzo de 2007 10:14
Para: La lista sobre Ruby On Rails (rubyonrails.com) en castellano
Asunto: Re: [Ror-es] Filtrar con Ajax Scaffold

Buenas.

Veo que en tu script pone:

¿seguro que el controlador se llama “incidencias”?¿no debería ser
“préstamos”?
Aparte, en component.rhtml no debería ir ir:

<%= render_component :controller => ‘/prestamos’, :action => ‘list’,
:params => params %>

porque se está llamando a sí mismo continuamente. Tienes que poner el
código en otro rhtml.

En cuanto a tu segunda duda:

Dices:
La primera línea filtro_estado = params[:filtro_estado] || “0”, sino me
equivoco debe de recoger el valor de la selección del combo y si no se
realiza le asigna un 0.
Realmente sólo le asigna 0 si es nulo params[:filtro_estado]. Si está en
blanco, el valor de filtro_estado será una cadena vacía.
La condición sería algo así:
if params[:filtro_estado].blank?
filtro_estado = params[:filtro_estado]
else
filtro_estado = “0”
end

Y lo de que la fecha no sea null, no lo he entendido muy bien. Podrías
explicara los campos que tienes en el html y en la BD y qué es
exactamente lo que quieres que haga?

Un saludo

On 3/5/07, Fernando González Macías [email protected] wrote:

Hola Luis, muchas gracias por contestar.

Respecto a tú código tengo dos problemas:

  1.   El fichero .rhtml que estoy actualizando con tú código es el 
    

component.rhtml. Una vez que situo el siguiente código:

    <%= render_component :controller => '/prestamos', :action => 

‘list’, :params => params %>

Me entra en una especie de bucle, listándome continuamente el grid,
junto con el combo de selección, una y otra vez, hasta que me da un
error. ¿No es en este fichero donde hay que situar este código?

  1.  El segundo problema es con respecto, al código a introducir en 
    

el controlador. Quiero filtrar por el estado de un campo fecha, en
función de que ese campo tenga valor o no, o bien que me muestre todos
los registros. Por lo tanto defino un combo de selección con préstamos
Abiertos, Cerrados y Todos. A los préstamos aún no devueltos se le
asigna en el campo fecha de devolución a NULL. El caso es que no tengo
nada claro como definir la condición para que el select la incorpore.

Tengo lo siguiente en el controlador:

def component

filtro_estado = params[:filtro_estado] || "0"

@show_wrapper = true if @show_wrapper.nil?

@sort_sql = 

Prestamo.scaffold_columns_hash[current_sort(params)].sort_sql rescue nil

@sort_by = @sort_sql.nil? ? 

“#{Prestamo.table_name}.#{Prestamo.primary_key} asc” : @sort_sql + " "

  • current_sort_direction(params)

    logger.debug(“Valor de filtro_estado”+filtro_estado)

    case filtro_estado

    when '1'
    
      logger.debug("Valor 1")
    
    
    
      condiciones = ["fecha_devolucion =  null"]
    
    when "2"
    
    logger.debug("Valor 2")
    
    
    
      condiciones = ["fecha_devolucion != null"]
    

    else

      logger.debug("Entra en ELSE")
    
    
    
      condiciones = ["fecha_devolucion != ?", '1900/01/01']
    
    end
    

    @paginator, @prestamos = paginate(:prestamos, :order => @sort_by,
    :per_page => default_per_page, :conditions => condiciones )

     render :action => "component", :layout => false
    

    end

Aquí como es evidente tengo varias dudas. La primera línea filtro_estado
= params[:filtro_estado] || “0”, sino me equivoco debe de recoger el
valor de la selección del combo y si no se realiza le asigna un 0.

¿Como puedo establecer que la fecha sea null o no null? Tal como lo he
puesto no me va.

Saludos y gracias…

Mira, pon en list.rhtml:

Incidencias - Estado: Abiertos Cerrados Todos

<%= observe_field ‘filtro_estado’,
:url => “/prestamos/component”,
:with => “filtro_estado”,
:frequency => 2,
:update => “capa_listado” %>

<%= render_component :controller => '/prestamos', :action => 'component', :params => params %>

Ten en cuenta que va en list.rhtml, ya que lo único que quieres que se
cambie es el contenido de las tablas, que va en component.rhtml.

Fíjate que he quitado la función javascript y le he puesto un observer,
para
que sea más rails.

Y en tu controlador (he supuesto que se llamaba prestamos):


def component
filtro_estado = params[:filtro_estado]
@show_wrapper = true if @show_wrapper.nil?
@sort_sql =
Prestamo.scaffold_columns_hash[current_sort(params)].sort_sql
rescue nil
@sort_by = @sort_sql.nil? ? “#{Prestamo.table_name}.#{
Prestamo.primary_key} asc” : @sort_sql + " " +
current_sort_direction(params)
logger.debug(“Valor de filtro_estado”+filtro_estado)
case filtro_estado
when ‘1’
logger.debug(“Valor 1”)
condiciones = [“fecha_devolucion is null”]
when “2”
logger.debug(“Valor 2”)
condiciones = [“fecha_devolucion is not null”]
else
logger.debug(“Entra en ELSE”)
condiciones = nil
end
@paginator, @prestamos = paginate(:prestamos, :order => @sort_by,
:per_page => default_per_page, :conditions => condiciones )
render :action => “component”, :layout => false
end

Tenías un error mysql yo creo, ya que en mysql lo que es null es “is
null” y
lo no null es “is not null”. En el caso de que quieras todos,
directamente
no te harían falta condiciones, por lo que se le pasa al método
“paginate”
conditions como nil y no meterá el where en la query

A ver si con esto te funciona.

Un saludo

Hola Luis, muchas gracias efectivamente me ha funcionado.

Aunque me gustaría corregir algunas cosillas:

  1.  En el combo tiene tres estados: Abiertos, Cerrados y Todos. Me 
    

gustaría filtrar por defecto por el estado inicial. Es decir sólo los
préstamos abiertos. He visto que inicialmente me muestra todos los
registros y hasta que no me voy al combo y selecciono un estado no me
modifica la selección.

  1.  Un efecto colateral que he visto, es que ya no ordena por los 
    

valores de cada campo. Es decir al darle a la cabecera de cada campo,
aparentemente realiza la acción, pero no modifica el orden de los
registros, ni ascendentemente, ni descendentemente.

  1.  Posiblemente ponga otro filtro con un combo por empresas, que 
    

tirará de una tabla de empresas. ¿Supongo que para esto tendré que
concatener los valores de condiciones1 y condiciones2 en condiciones,
por decirlo de alguna forma?

Saludos y gracias por tu paciencia…

Fernando González Macías


De: [email protected]
mailto:[email protected]
[mailto:[email protected]]
mailto:[mailto:[email protected]] En nombre
de Luis V.
Enviado el: viernes, 09 de marzo de 2007 15:00
Para: La lista sobre Ruby On Rails (rubyonrails.com) en castellano
Asunto: Re: [Ror-es] RV: Filtrar con Ajax Scaffold

Mira, pon en list.rhtml:

Incidencias - Estado: Abiertos Cerrados Todos

<%= observe_field ‘filtro_estado’,
:url => “/prestamos/component”,
:with => “filtro_estado”,
:frequency => 2,
:update => “capa_listado” %>

<%= render_component :controller => '/prestamos', :action => 'component', :params => params %>

Ten en cuenta que va en list.rhtml, ya que lo único que quieres que se
cambie es el contenido de las tablas, que va en component.rhtml.

Fíjate que he quitado la función javascript y le he puesto un observer,
para que sea más rails.

Y en tu controlador (he supuesto que se llamaba prestamos):


def component
filtro_estado = params[:filtro_estado]
@show_wrapper = true if @show_wrapper.nil?
@sort_sql = Prestamo.scaffold_columns_hash
[current_sort(params)].sort_sql rescue nil
@sort_by = @sort_sql.nil? ?
“#{Prestamo.table_name}.#{Prestamo.primary_key} asc” : @sort_sql + " "

  • current_sort_direction(params)
    logger.debug (“Valor de filtro_estado”+filtro_estado)
    case filtro_estado
    when ‘1’
    logger.debug(“Valor 1”)
    condiciones = [“fecha_devolucion is null”]
    when “2”
    logger.debug(“Valor 2”)
    condiciones = [“fecha_devolucion is not null”]
    else
    logger.debug(“Entra en ELSE”)
    condiciones = nil
    end
    @paginator, @prestamos = paginate(:prestamos, :order => @sort_by,
    :per_page => default_per_page, :conditions => condiciones )
    render :action => “component”, :layout => false
    end

Tenías un error mysql yo creo, ya que en mysql lo que es null es “is
null” y lo no null es “is not null”. En el caso de que quieras todos,
directamente no te harían falta condiciones, por lo que se le pasa al
método “paginate” conditions como nil y no meterá el where en la query

A ver si con esto te funciona.

Un saludo

On 3/8/07, Fernando González Macías <[email protected] >
wrote:

Hola Luis. He estado un par de días liado con otro tema. Volvemos al
ataque.

Efectivamente el controlador se llama préstamos y la función se llama
actualizaCapaPrestamos(). Te pasé el código que me enviaste tú
directamente sin modificarlo.

Respecto a la línea siguiente, cuando dices, que debería ir en otro
fichero .rhtml, ¿en cuál?

En cuanto al filtrado que quiero establecer intentaré explicarme. Tengo
una serie de préstamos de portátiles en los cuales quiero filtrar
mediante un combo la situación de los mismos. El combo tiene tres
valores: Abierto, Cerrado y Todos, con valores 1, 2 y 3 respectivamente

En el modelo existe un campo denominado fecha_devolucion que es por el
que quiero filtrar. Cuando selecciono Abierto sólo mostraré los
registros donde ese campo esté a null (vacío - aún no han devuelto los
portátiles), Cuando seleccione Cerrado, mostraré los que ya han sido
entregados, por tanto fecha_devolucion distinta de null y en Todos, pues
lo dicho Todos (fecha_devolucion <> 01/01/1900 por ejemplo.

La tabla está en Mysql y los campos fechas son del tipo Date, y el campo
fecha_devolucion está definido que puede ser null.

En el fichero app/views/prestamos/component.rhtml he definido el combo
de la siguiente forma:

Incidencias -

  <span style="font-size:18px;font-weight:bold;">Estado:

    <select name="filtro_estado" id="filtro_estado" 

onchange=“actualizaCapaPrestamos()”>

        <option value ="1">

            Abiertos

        </option>

        <option value ="2">

            Cerrados

        </option>

        <option value = "3">

            Todos

        </option>

    </select>

</span>

Fernando González Macías

fgonzalez @ grupojoly.com

Dpto. Informática Diario de Cádiz

(Grupo Joly)

Hola de nuevo Fernando, te respondo por partes:

On 3/9/07, Fernando González Macías [email protected] wrote:

en el controller:

def component
filtro_estado = params[:filtro_estado] || “1”

Así, si el valor de filtro estado viene nil, le pone un uno y en el
case,
irá a la primera opción en vez de al else

  1.  Un efecto colateral que he visto, es que ya no ordena por los
    

valores de cada campo. Es decir al darle a la cabecera de cada campo,
aparentemente realiza la acción, pero no modifica el orden de los registros,
ni ascendentemente, ni descendentemente.

No debería pasar… pasa el trozo de log en development.log cuando le
des a
ordenar

  1.  Posiblemente ponga otro filtro con un combo por empresas, que 
    

tirará

de una tabla de empresas. ¿Supongo que para esto tendré que concatener los
valores de condiciones1 y condiciones2 en condiciones, por decirlo de alguna
forma?

Para eso haz algo así como:


def component
filtro_estado = params[:filtro_estado]
@show_wrapper = true if @show_wrapper.nil?
@sort_sql =
Prestamo.scaffold_columns_hash[current_sort(params)].sort_sql rescue
nil
@sort_by = @sort_sql.nil? ? “#{Prestamo.table_name}.#{
Prestamo.primary_key} asc” : @sort_sql + " " +
current_sort_direction(params)
logger.debug (“Valor de filtro_estado”+filtro_estado)

condiciones = ["nombre_empresa = ?

“,”%"+params[:filtro_nombre_empresa]+"%"]

case filtro_estado
  when '1'
    logger.debug("Valor 1")
    condiciones[0] += [" fecha_devolucion is  null"]
  when "2"
    logger.debug("Valor 2")
    condiciones[0] += [" fecha_devolucion is not null"]
else
    logger.debug("Entra en ELSE")
    #aquí no hagas nada, para que se quede sólo con el filtro de 

empresa
end
@paginator, @prestamos = paginate(:prestamos, :order => @sort_by,
:per_page => default_per_page, :conditions => condiciones )
render :action => “component”, :layout => false
end

Lo he hecho un poco a pelo, pero esa es la idea

A ver si te funciona.

Un saludo

Respecto a lo primero, ok, ya filtra inicialmente por los préstamos
Abiertos. Gracias.

Te adjunto el log al darle al botón de ordenar por el campo Sección.
Aparentemente está bien, no veo nada raro, pero no llega a realizar la
ordenación. Te lo adjunto por si vieras algo.

Processing PrestamosController#component_update (for 10.210.7.11 at
2007-03-12 11:29:13) [POST]

Session ID: fdff610943f75f6969700c409965ea69

Parameters: {“action”=>“component_update”, “controller”=>“prestamos”,
“filtro_estado”=>“3”, “sort”=>“seccion”, “page”=>“1”,
“sort_direction”=>“desc”, “scaffold_id”=>“prestamo”}

[4;35;1mPrestamo Columns (0.000000)[0m [0mSHOW FIELDS FROM
prestamos[0m

[4;36;1mSQL (0.000000)[0m [0;1mSELECT count(*) AS count_all FROM
prestamos [0m

[4;35;1mPrestamo Load (0.000000)[0m [0mSELECT * FROM prestamos ORDER
BY prestamos.id asc LIMIT 0, 25[0m

Rendering prestamos/component

Rendered prestamos/_column_headings (0.03100)

Rendered prestamos/_messages (0.01600)

[4;36;1mLaptop Columns (0.000000)[0m [0;1mSHOW FIELDS FROM
laptops[0m

[4;35;1mLaptop Load (0.000000)[0m [0mSELECT * FROM laptops WHERE
(laptops.id = 16) [0m

[4;36;1mAdministrator Columns (0.016000)[0m [0;1mSHOW FIELDS FROM
administrators[0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 8) [0m

Rendered prestamos/_prestamo (0.18700)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 21) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 9) [0m

Rendered prestamos/_prestamo (0.03100)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 10) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 18) [0m

Rendered prestamos/_prestamo (0.04700)

[4;36;1mLaptop Load (0.016000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 18) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 11) [0m

Rendered prestamos/_prestamo (0.04700)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 21) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 9) [0m

Rendered prestamos/_prestamo (0.04700)

[4;36;1mLaptop Load (0.016000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 24) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 5) [0m

Rendered prestamos/_prestamo (0.06300)

[4;36;1mLaptop Load (0.015000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 7) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 19) [0m

Rendered prestamos/_prestamo (0.03100)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 9) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 19) [0m

Rendered prestamos/_prestamo (0.01500)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 28) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 10) [0m

Rendered prestamos/_prestamo (0.01600)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 18) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 11) [0m

Rendered prestamos/_prestamo (0.01600)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 28) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 10) [0m

Rendered prestamos/_prestamo (0.01500)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 10) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 4) [0m

Rendered prestamos/_prestamo (0.01600)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 22) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 24) [0m

Rendered prestamos/_prestamo (0.01600)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 21) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 9) [0m

Rendered prestamos/_prestamo (0.17100)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 23) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 5) [0m

Rendered prestamos/_prestamo (0.01600)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 24) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 5) [0m

Rendered prestamos/_prestamo (0.01600)

[4;36;1mLaptop Load (0.000000)[0m [0;1mSELECT * FROM laptops WHERE
(laptops.id = 27) [0m

[4;35;1mAdministrator Load (0.000000)[0m [0mSELECT * FROM
administrators WHERE (administrators.id = 10) [0m

Rendered prestamos/_prestamo (0.01500)

Rendered prestamos/_pagination_links (0.00000)

Completed in 0.84300 (1 reqs/sec) | Rendering: 0.74900 (88%) | DB:
0.06300 (7%) | 200 OK
[http://cadi13/prestamos/component_update?scaffold_id=prestamo&filtro_estado=3&sort_direction=desc&page=1&sort=seccion]

Fernando González Macías


De: [email protected]
[mailto:[email protected]] En nombre de Luis
Villegas
Enviado el: lunes, 12 de marzo de 2007 10:08
Para: La lista sobre Ruby On Rails (rubyonrails.com) en castellano
Asunto: Re: [Ror-es] RV: Filtrar con Ajax Scaffold

Hola de nuevo Fernando, te respondo por partes:

On 3/9/07, Fernando González Macías <[email protected] >
wrote:

Hola Luis, muchas gracias efectivamente me ha funcionado.

Aunque me gustaría corregir algunas cosillas:

  1.  En el combo tiene tres estados: Abiertos, Cerrados y Todos. Me 
    

gustaría filtrar por defecto por el estado inicial. Es decir sólo los
préstamos abiertos. He visto que inicialmente me muestra todos los
registros y hasta que no me voy al combo y selecciono un estado no me
modifica la selección.

en el controller:

def component
filtro_estado = params[:filtro_estado] || “1”

Así, si el valor de filtro estado viene nil, le pone un uno y en el
case, irá a la primera opción en vez de al else

  1.  Un efecto colateral que he visto, es que ya no ordena por los 
    

valores de cada campo. Es decir al darle a la cabecera de cada campo,
aparentemente realiza la acción, pero no modifica el orden de los
registros, ni ascendentemente, ni descendentemente.

No debería pasar… pasa el trozo de log en development.log cuando le
des a ordenar

  1.  Posiblemente ponga otro filtro con un combo por empresas, que 
    

tirará de una tabla de empresas. ¿Supongo que para esto tendré que
concatener los valores de condiciones1 y condiciones2 en condiciones,
por decirlo de alguna forma?

Para eso haz algo así como:


def component
filtro_estado = params[:filtro_estado]
@show_wrapper = true if @show_wrapper.nil?
@sort_sql = Prestamo.scaffold_columns_hash
[current_sort(params)].sort_sql rescue nil
@sort_by = @sort_sql.nil? ?
“#{Prestamo.table_name}.#{Prestamo.primary_key} asc” : @sort_sql + " "

  • current_sort_direction(params)
    logger.debug (“Valor de filtro_estado”+filtro_estado)

    condiciones = [“nombre_empresa = ?
    “,”%”+params[:filtro_nombre_empresa]+"%"]

    case filtro_estado
    when ‘1’
    logger.debug(“Valor 1”)
    condiciones[0] += [" fecha_devolucion is null"]
    when “2”
    logger.debug(“Valor 2”)
    condiciones[0] += [" fecha_devolucion is not null"]
    else
    logger.debug(“Entra en ELSE”)
    #aquí no hagas nada, para que se quede sólo con el filtro de
    empresa
    end
    @paginator, @prestamos = paginate(:prestamos, :order => @sort_by,
    :per_page => default_per_page, :conditions => condiciones )
    render :action => “component”, :layout => false
    end

Lo he hecho un poco a pelo, pero esa es la idea

A ver si te funciona.

Un saludo

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs