Foreign Key
Planning ahead for our association
A song belongs to an artist
An artist has many songs
class Artist < ActiveRecord::Base
has_many :songs
end
class Song < ActiveRecord::Base
belongs_to :artist
end
app/models/song.rb
app/models/artist.rb
# GET /songs/new
def new
@song = Song.new
@artists = Artist.all
end
# GET /songs/1/edit
def edit
@artists = Artist.all
end
songs_controller.rb
<!-- Remove this line -->
<%#= f.number_field :artist_id %>
<%= f.select(:artist_id, @artists.collect
{|a| [ a.name, a.id ] }, {:include_blank =>
'Please select an artist'}) %>
songs/_form.html.erb
<!-- Remove this line -->
<%#= f.number_field :rating %>
<%= f.select :rating, ["1","2","3","4","5","6","7","8","9","10"], {:include_blank => 'Rating'} %>
songs/_form.html.erb
class Song < ActiveRecord::Base
belongs_to :artist
validates :name, presence: true
validates :artist_id, presence: true
validates :rating, presence: true
end
class Artist < ActiveRecord::Base
has_many :songs
validates :name, presence: true
end
models/song.rb
models/artist.rb
class Song < ActiveRecord::Base
belongs_to :artist
validates :name, presence: true
validates :artist_id, presence: true
validates :rating, presence: true
validates :name, uniqueness: true
end
class Artist < ActiveRecord::Base
has_many :songs
validates :name, presence: true
validates :name, uniqueness: true
end
models/song.rb
models/artist.rb
def create
@song = Song.new(song_params)
@artists = Artist.all
...
end
controllers/songs_controller.rb
<div class="site-wrapper">
<div class="site-wrapper-inner">
<div class="cover-container">
<div class="masthead clearfix">
<div class="inner">
<h3 class="masthead-brand">Cover</h3>
<nav>
<ul class="nav masthead-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#">Features</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</div>
</div>
<div class="inner cover">
<h1 class="cover-heading">Cover your page.</h1>
<p class="lead">Cover is a one-page template for building simple and beautiful home pages. Download, edit the text, and add your own fullscreen background photo to make it your own.</p>
<p class="lead">
<a href="#" class="btn btn-lg btn-default">Learn more</a>
</p>
</div>
<div class="mastfoot">
<div class="inner">
<p>Cover template for <a href="http://getbootstrap.com">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p>
</div>
</div>
</div>
</div>
</div>
<div class="site-wrapper">
<div class="site-wrapper-inner">
<div class="cover-container">
<div class="masthead clearfix">
<div class="inner">
<h3 class="masthead-brand">JP's Top Jams</h3>
<nav>
<ul class="nav masthead-nav">
<li><%= link_to "Top 5", root_path %></li>
<li><%= link_to "Artists", artists_path %></li>
<li><%= link_to "Songs", songs_path %></li>
</ul>
</nav>
</div>
</div>
<div class="inner cover">
<%= yield %>
</div>
<div class="mastfoot">
<div class="inner">
<p>JP's Top Jams. @copy; 2015</p>
</div>
</div>
</div>
</div>
</div>
views/layouts/application.html.erb
/*
* Globals
*/
/* Links */
a,
a:focus,
a:hover {
color: #fff;
}
/* Custom default button */
.btn-default,
.btn-default:hover,
.btn-default:focus {
color: #333;
text-shadow: none; /* Prevent inheritence from `body` */
background-color: #fff;
border: 1px solid #fff;
}
/*
* Base structure
*/
html,
body {
height: 100%;
background-color: #333;
}
body {
color: #fff;
text-align: center;
text-shadow: 0 1px 3px rgba(0,0,0,.5);
}
/* Extra markup and styles for table-esque vertical and horizontal centering */
.site-wrapper {
display: table;
width: 100%;
height: 100%; /* For at least Firefox */
min-height: 100%;
-webkit-box-shadow: inset 0 0 100px rgba(0,0,0,.5);
box-shadow: inset 0 0 100px rgba(0,0,0,.5);
}
.site-wrapper-inner {
display: table-cell;
vertical-align: top;
}
.cover-container {
margin-right: auto;
margin-left: auto;
}
/* Padding for spacing */
.inner {
padding: 30px;
}
/*
* Header
*/
.masthead-brand {
margin-top: 10px;
margin-bottom: 10px;
}
.masthead-nav > li {
display: inline-block;
}
.masthead-nav > li + li {
margin-left: 20px;
}
.masthead-nav > li > a {
padding-right: 0;
padding-left: 0;
font-size: 16px;
font-weight: bold;
color: #fff; /* IE8 proofing */
color: rgba(255,255,255,.75);
border-bottom: 2px solid transparent;
}
.masthead-nav > li > a:hover,
.masthead-nav > li > a:focus {
background-color: transparent;
border-bottom-color: #a9a9a9;
border-bottom-color: rgba(255,255,255,.25);
}
.masthead-nav > .active > a,
.masthead-nav > .active > a:hover,
.masthead-nav > .active > a:focus {
color: #fff;
border-bottom-color: #fff;
}
@media (min-width: 768px) {
.masthead-brand {
float: left;
}
.masthead-nav {
float: right;
}
}
/*
* Cover
*/
.cover {
padding: 0 20px;
}
.cover .btn-lg {
padding: 10px 20px;
font-weight: bold;
}
/*
* Footer
*/
.mastfoot {
color: #999; /* IE8 proofing */
color: rgba(255,255,255,.5);
}
/*
* Affix and center
*/
@media (min-width: 768px) {
/* Pull out the header and footer */
.masthead {
position: fixed;
top: 0;
}
.mastfoot {
position: fixed;
bottom: 0;
}
/* Start the vertical centering */
.site-wrapper-inner {
vertical-align: middle;
}
/* Handle the widths */
.masthead,
.mastfoot,
.cover-container {
width: 100%; /* Must be percentage or pixels for horizontal alignment */
}
}
@media (min-width: 992px) {
.masthead,
.mastfoot,
.cover-container {
width: 700px;
}
}
assets/stylesheets/application.css
assets/stylesheets/application.css.erb
@media (min-width: 768px) {
/* Pull out the header and footer */
.masthead {
/* position: fixed;
top: 0;*/
}
.mastfoot {
/* position: fixed;
bottom: 0;*/
}
/* Start the vertical centering */
.site-wrapper-inner {
/* vertical-align: middle;*/
}
h3 {
font-weight: 100;
}
input[type="text"], input[type="number"]{
color: #000;
}
assets/stylesheets/application.css.erb
assets/stylesheets/application.css.erb
html,
body {
height: 100%;
background: url(<%= asset_path "bg.jpeg" %>) no-repeat center center fixed;
background-size: cover;
}
assets/stylesheets/application.css.erb
Also don't forget to save as .css.erb!
assets/stylesheets/application.css.erb
<h3 class="masthead-brand"><%= image_tag "logo.png" %> JP's Top Jams</h3>
If the icon is black we can invert using Pixlr (a Photoshop-like online tool: http://pixlr.com/editor
views/layouts/application.html.erb
assets/stylesheets/application.css.erb
assets/stylesheets/application.css.erb
<h1>My Songs</h1>
<p><%= link_to new_song_path do %>
<span class="glyphicon glyphicon-plus"></span> Add
<% end %>
</p>
views/songs/index.html.erb
assets/stylesheets/application.css.erb
<div class="row">
<% @songs.each do |song| %>
<div class="col-md-6">
<div class="well">
<h2><%= link_to song.name, song %></h2>
<h4><%= song.rating %></h4>
<p>
<%= link_to 'Edit', edit_song_path(song) %> |
<%= link_to 'Destroy', song, method: :delete, data: { confirm: 'Are you sure?' } %>
</p>
</div>
</div>
<% end %>
</div>
views/songs/index.html.erb
assets/stylesheets/application.css.erb
.well {
background: rgba(0,0,0,0.4);
}
assets/stylesheets/application.css.erb
assets/stylesheets/application.css.erb
<div class="row">
<% @songs.each do |song| %>
<div class="col-md-6">
<div class="well">
<h2><%= link_to song.name, song %></h2>
<h3>by <%= song.artist.name %></h3>
<h4><%= song.rating %></h4>
<p>
<%= link_to 'Edit', edit_song_path(song) %> |
<%= link_to 'Destroy', song, method: :delete, data: { confirm: 'Are you sure?' } %>
</p>
</div>
</div>
<% end %>
</div>
views/songs/index.html.erb
assets/stylesheets/application.css.erb
<div class="row">
<% @songs.each do |song| %>
<div class="col-md-6">
<div class="well">
<h2><%= link_to song.name, song %></h2>
<h3>by <%= song.artist.name %></h3>
<h4><%= song.rating %></h4>
<hr/>
<h4><%= link_to edit_song_path(song) do %>
<span class="glyphicon glyphicon-pencil"></span>
<% end %>
<%= link_to song, method: :delete, data: { confirm: 'Are you sure?' } do %>
<span class="glyphicon glyphicon-trash"></span>
<% end %>
</h4>
</div>
</div>
<% end %>
</div>
views/songs/index.html.erb
assets/stylesheets/application.css.erb
<p>
<% "#{song.rating}".to_i.times do %>
<span class="glyphicon glyphicon-star"></span>
<% end %>
</p>
views/songs/index.html.erb
assets/stylesheets/application.css.erb
.glyphicon-star {
color: yellow;
}
assets/stylesheets/application.css.erb
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<%= form_for(@song) do |f| %>
<% if @song.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@song.errors.count, "error") %> prohibited this song from being saved:</h2>
<ul>
<% @song.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :name, class: "sr-only" %>
<%= f.text_field :name, class: "form-control", placeholder: "Name" %>
</div>
<div class="form-group">
<%= f.select :rating, ["1","2","3","4","5","6","7","8","9","10"],
{:include_blank => 'Rating'}, class: "form-control" %>
</div>
<div class="form-group">
<%= f.select(:artist_id, @artists.collect {|a| [ a.name, a.id ] },
{:include_blank => 'Please select an artist'}, class: "form-control") %>
</div>
<div class="actions">
<%= f.submit class: "btn btn-primary btn-lg" %>
</div>
<% end %>
</div>
</div>
views/songs/_form.html.erb
assets/stylesheets/application.css.erb
assets/stylesheets/application.css.erb
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<%= form_for(@artist) do |f| %>
<% if @artist.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@artist.errors.count, "error") %> prohibited this artist from being saved:</h2>
<ul>
<% @artist.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :name, class: "sr-only" %><br>
<%= f.text_field :name, class: "form-control", placeholder: "Name" %>
</div>
<div class="form-group">
<%= f.submit class: 'btn btn-lg btn-primary' %>
</div>
<% end %>
</div>
</div>
views/artists/_form.html.erb
<h1>My Artists</h1>
<p><%= link_to new_artist_path do %>
<span class="glyphicon glyphicon-plus"></span> Add
<% end %>
</p>
<div class="row">
<% @artists.each do |artist| %>
<div class="col-md-6">
<div class="well">
<h2><%= link_to artist.name, artist %></h2>
<h4><%= link_to edit_artist_path(artist) do %>
<span class="glyphicon glyphicon-pencil"></span>
<% end %>
<%= link_to artist, method: :delete, data: { confirm: 'Are you sure?' } do %>
<span class="glyphicon glyphicon-trash"></span>
<% end %>
</h4>
</div>
</div>
<% end %>
</div>
views/artists/index.html.erb
assets/stylesheets/application.css.erb
<p id="notice"><%= notice %></p>
<div class="row">
<div class="col-md-12">
<div class="well">
<h1><%= @artist.name %></h1>
<% @artist.songs.each do |song| %>
<h3><%= link_to song.name, song %></a></h3>
<% end %>
</div>
</div>
</div>
views/artists/show.html.erb
assets/stylesheets/application.css.erb
<div class="row">
<h2> My Top 5 </h2>
<% @songs.each do |song| %>
<div class="well well-lg">
<h2><%= song.name %></h2>
<h3>by <%= song.artist.name %> </h3>
<p><% "#{song.rating}".to_i.times do |rank| %>
<span class="glyphicon glyphicon-star"></span>
<% end %>
</p>
</div>
<% end %>
</div>
views/main/index.html.erb
class MainController < ApplicationController
def index
@songs = Song.all
end
end
controllers/main_controller.rb
This is a start. It's pulling in all songs.
assets/stylesheets/application.css.erb
class MainController < ApplicationController
def index
@songs = Song.order(rating: :desc).limit(5)
end
end
controllers/main_controller.rb
assets/stylesheets/application.css.erb
assets/stylesheets/application.css.erb
# DELETE /artists/1.json
def destroy
@artist.destroy
@artist.songs.each do |song|
song.destroy
end
respond_to do |format|
format.html { redirect_to artists_url, notice: 'Artist and artist songs
were successfully destroyed.' }
format.json { head :no_content }
end
end
controllers/artists_controller.rb
assets/stylesheets/application.css.erb
<% if @artist.avatar.exists? != nil %>
<%= image_tag @artist.avatar.url(:thumb) %>
<% end %>
.well img {
border-radius: 100px;
}
assets/stylesheets/application.css.erb
assets/stylesheets/application.css.erb
Scaffold a resource Item with a name and due date
assets/stylesheets/application.css.erb
Add some style!
assets/stylesheets/application.css.erb