goals {
div(style: 'margin: 0 auto; width: 250px; height: 120px;') do
model_diagram header: 'Topics', fields: %w(id title description), style: "float: left;"
div(style: 'float: left; position: relative; width: 60px; height: 100px;') do
div(class: 'arrow-left', style: 'left: 0; top: 30px;')
div(class: 'horiz-line', style: 'left: 5px; top: 37px; width: 25px;')
div(class: 'vert-line', style: 'left: 30px; top: 38px; height: 25px;')
div(class: 'horiz-line', style: 'right: 0; top: 62px; width: 30px;')
end
model_diagram header: 'Votes', fields: %w(id topic_id), style: "float: left;"
end
message "Porque hay una relación explícita entre un tema y sus votos, necesitamos especificar eso. En este paso, declararemos explícitamente
la relación entre los votos y los temas."
}
steps {
step "Enséñale al modelo Topic acerca de Votes" do
message "Edita `app/models/topic.rb` para que quede así:"
source_code :ruby, <<-RUBY
class Topic < ActiveRecord::Base
has_many :votes, dependent: :destroy
end
RUBY
end
step "Enséñale al modelo Vote acerca de Topics" do
message "Edita `app/models/vote.rb` para que quede así:"
source_code :ruby, <<-RUBY
class Vote < ActiveRecord::Base
belongs_to :topic
end
RUBY
end
step "Juega un poco con los temas y votos en la consola de Rails" do
message "Primero, asegúrate de que has hecho por lo menos un tema en el sitio."
console_with_message "Luego, abre la consola de Rails en una terminal:", "rails c"
result <<-CONSOLE
$ rails c
Loading development environment (Rails 4.0.0)
1.9.3-p194 :001 >
CONSOLE
message "En la consola, intenta lo siguiente"
console_with_message "Ve cuántos temas existen:", "Topic.count"
console_with_message "Guarda el primer tema en una variable:", "mi_tema = Topic.first"
tip "`mi_tema` aquí podríamos tener cualquier nombre de variable, pero nos apegaremos a `mi_tema` por consistencia."
console_with_message "Cambia el título de ese tema por cualquier otro:", "mi_tema.update_attributes(title: 'Editado en la consola')"
console_with_message "Agrega un voto a ese tema:", "mi_tema.votes.create"
console_with_message "Ve cuántos votos tiene ese tema:", "mi_tema.votes.count"
console_with_message "Elimina un voto de ese tema:", "mi_tema.votes.first.destroy"
message "Observa que las cosas que puedes hacer con las **Clases de Modelo** (como **Topic** y **Vote**), son diferentes a las cosas que puedes hacer con las **Instancias de Modelo** (como mi\\_tema). **mi\\_tema.votes** es una **asociación**, y aquí se comporta mayormente como una clase de modelo."
div do
half_width "Clase de Modelo / métodos de asociación" do
ul class: 'no-style-type' do
li "Topic.first"
li "Topic.last"
li "Topic.all"
li "Topic.count"
li "Topic.find_by_id(5)"
li "Topic.destroy_all"
li "mi_tema.votes.count"
li "mi_tema.votes.create"
li "mi_tema.votes.destroy_all"
end
end
half_width "Métodos de Instancia de Modelo" do
ul class: 'no-style-type' do
li "mi_tema.title"
li "mi_tema.title = 'New title'"
li "mi_tema.update_attributes(title: 'New title')"
li "mi_tema.save"
li "mi_tema.save!"
li "mi_tema.destroy"
li "mi_tema.votes.first.destroy"
end
end
end
message <<-TEXT
Una lista exhaustiva de cosas que puedes hacer con los modelos y asociaciones se encuentra en <a href="http://guides.rubyonrails.org/active_record_querying.html">Active Record Query Interface RailsGuide</a>.
TEXT
end
}
explanation {
message <<-MARKDOWN
`has_many` y `belongs_to`:
* En Rails, las relaciones entre modelos son llamadas asociaciones.
* Asociaciones (por regla general) vienen en pares.
* Un tema tendrá muchos votos, por lo tanto ponemos `has_many :votes` en el modelo Topic.
* Cuando preguntamos a un tema por sus votos, obtendrás un arreglo de votos
para ese tema.
* Un voto es para un tema en particular, por lo tanto ponemos `belongs_to :topic`
en el modelo Vote.
* Cuando preguntamos a un voto por su tema, obtendrás el tema
para ese voto.
Esto es importante para que te asegures de limpiar: `dependent: :destroy`
en `has_many :votes` significa que cuando un **Topic** se destruye, todos
los **votes** que corresponden a él serán destruídos también. Si no ponemos
`dependent :destroy`, estos votos vivirían en la base de datos para siempre.
MARKDOWN
}
next_step "permitir_votar"