From e141406d556732314da610af767e3cadab1ad6df Mon Sep 17 00:00:00 2001 From: Mike Kenworthy Date: Thu, 5 Feb 2015 11:27:54 -0500 Subject: [PATCH 1/3] Scaffolded URLS resource --- .../app/assets/stylesheets/scaffolds.css.scss | 69 ++++++++ source/app/controllers/urls_controller.rb | 72 ++++++++ source/app/models/url.rb | 2 + source/app/views/urls/_form.html.erb | 33 ++++ source/app/views/urls/edit.html.erb | 6 + source/app/views/urls/index.html.erb | 31 ++++ source/app/views/urls/index.json.jbuilder | 4 + source/app/views/urls/new.html.erb | 5 + source/app/views/urls/show.html.erb | 24 +++ source/app/views/urls/show.json.jbuilder | 1 + source/config/routes.rb | 2 + .../db/migrate/20150205161959_create_urls.rb | 12 ++ source/db/schema.rb | 25 +++ .../spec/controllers/urls_controller_spec.rb | 159 ++++++++++++++++++ source/spec/helpers/urls_helper_spec.rb | 15 ++ source/spec/models/url_spec.rb | 5 + source/spec/requests/urls_spec.rb | 10 ++ source/spec/routing/urls_routing_spec.rb | 35 ++++ source/spec/views/urls/edit.html.erb_spec.rb | 27 +++ source/spec/views/urls/index.html.erb_spec.rb | 28 +++ source/spec/views/urls/new.html.erb_spec.rb | 27 +++ source/spec/views/urls/show.html.erb_spec.rb | 20 +++ 22 files changed, 612 insertions(+) create mode 100644 source/app/assets/stylesheets/scaffolds.css.scss create mode 100644 source/app/models/url.rb create mode 100644 source/app/views/urls/_form.html.erb create mode 100644 source/app/views/urls/edit.html.erb create mode 100644 source/app/views/urls/index.html.erb create mode 100644 source/app/views/urls/index.json.jbuilder create mode 100644 source/app/views/urls/new.html.erb create mode 100644 source/app/views/urls/show.html.erb create mode 100644 source/app/views/urls/show.json.jbuilder create mode 100644 source/db/migrate/20150205161959_create_urls.rb create mode 100644 source/db/schema.rb create mode 100644 source/spec/controllers/urls_controller_spec.rb create mode 100644 source/spec/helpers/urls_helper_spec.rb create mode 100644 source/spec/models/url_spec.rb create mode 100644 source/spec/requests/urls_spec.rb create mode 100644 source/spec/routing/urls_routing_spec.rb create mode 100644 source/spec/views/urls/edit.html.erb_spec.rb create mode 100644 source/spec/views/urls/index.html.erb_spec.rb create mode 100644 source/spec/views/urls/new.html.erb_spec.rb create mode 100644 source/spec/views/urls/show.html.erb_spec.rb diff --git a/source/app/assets/stylesheets/scaffolds.css.scss b/source/app/assets/stylesheets/scaffolds.css.scss new file mode 100644 index 0000000..6ec6a8f --- /dev/null +++ b/source/app/assets/stylesheets/scaffolds.css.scss @@ -0,0 +1,69 @@ +body { + background-color: #fff; + color: #333; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { + color: #000; + &:visited { + color: #666; + } + &:hover { + color: #fff; + background-color: #000; + } +} + +div { + &.field, &.actions { + margin-bottom: 10px; + } +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px; + padding-bottom: 0; + margin-bottom: 20px; + background-color: #f0f0f0; + h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px; + margin-bottom: 0px; + background-color: #c00; + color: #fff; + } + ul li { + font-size: 12px; + list-style: square; + } +} diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index ef26710..6d826ea 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -1,2 +1,74 @@ class UrlsController < ApplicationController + before_action :set_url, only: [:show, :edit, :update, :destroy] + + # GET /urls + # GET /urls.json + def index + @urls = Url.all + end + + # GET /urls/1 + # GET /urls/1.json + def show + end + + # GET /urls/new + def new + @url = Url.new + end + + # GET /urls/1/edit + def edit + end + + # POST /urls + # POST /urls.json + def create + @url = Url.new(url_params) + + respond_to do |format| + if @url.save + format.html { redirect_to @url, notice: 'Url was successfully created.' } + format.json { render :show, status: :created, location: @url } + else + format.html { render :new } + format.json { render json: @url.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /urls/1 + # PATCH/PUT /urls/1.json + def update + respond_to do |format| + if @url.update(url_params) + format.html { redirect_to @url, notice: 'Url was successfully updated.' } + format.json { render :show, status: :ok, location: @url } + else + format.html { render :edit } + format.json { render json: @url.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /urls/1 + # DELETE /urls/1.json + def destroy + @url.destroy + respond_to do |format| + format.html { redirect_to urls_url, notice: 'Url was successfully destroyed.' } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_url + @url = Url.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def url_params + params.require(:url).permit(:long_url, :short_url, :name, :clicks) + end end diff --git a/source/app/models/url.rb b/source/app/models/url.rb new file mode 100644 index 0000000..e4834ff --- /dev/null +++ b/source/app/models/url.rb @@ -0,0 +1,2 @@ +class Url < ActiveRecord::Base +end diff --git a/source/app/views/urls/_form.html.erb b/source/app/views/urls/_form.html.erb new file mode 100644 index 0000000..a73cd28 --- /dev/null +++ b/source/app/views/urls/_form.html.erb @@ -0,0 +1,33 @@ +<%= form_for(@url) do |f| %> + <% if @url.errors.any? %> +
+

<%= pluralize(@url.errors.count, "error") %> prohibited this url from being saved:

+ + +
+ <% end %> + +
+ <%= f.label :long_url %>
+ <%= f.text_field :long_url %> +
+
+ <%= f.label :short_url %>
+ <%= f.text_field :short_url %> +
+
+ <%= f.label :name %>
+ <%= f.text_field :name %> +
+
+ <%= f.label :clicks %>
+ <%= f.number_field :clicks %> +
+
+ <%= f.submit %> +
+<% end %> diff --git a/source/app/views/urls/edit.html.erb b/source/app/views/urls/edit.html.erb new file mode 100644 index 0000000..e52fdf4 --- /dev/null +++ b/source/app/views/urls/edit.html.erb @@ -0,0 +1,6 @@ +

Editing url

+ +<%= render 'form' %> + +<%= link_to 'Show', @url %> | +<%= link_to 'Back', urls_path %> diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb new file mode 100644 index 0000000..4b560da --- /dev/null +++ b/source/app/views/urls/index.html.erb @@ -0,0 +1,31 @@ +

Listing urls

+ + + + + + + + + + + + + + <% @urls.each do |url| %> + + + + + + + + + + <% end %> + +
Long urlShort urlNameClicks
<%= url.long_url %><%= url.short_url %><%= url.name %><%= url.clicks %><%= link_to 'Show', url %><%= link_to 'Edit', edit_url_path(url) %><%= link_to 'Destroy', url, method: :delete, data: { confirm: 'Are you sure?' } %>
+ +
+ +<%= link_to 'New Url', new_url_path %> diff --git a/source/app/views/urls/index.json.jbuilder b/source/app/views/urls/index.json.jbuilder new file mode 100644 index 0000000..8c68ecc --- /dev/null +++ b/source/app/views/urls/index.json.jbuilder @@ -0,0 +1,4 @@ +json.array!(@urls) do |url| + json.extract! url, :id, :long_url, :short_url, :name, :clicks + json.url url_url(url, format: :json) +end diff --git a/source/app/views/urls/new.html.erb b/source/app/views/urls/new.html.erb new file mode 100644 index 0000000..7e711d5 --- /dev/null +++ b/source/app/views/urls/new.html.erb @@ -0,0 +1,5 @@ +

New url

+ +<%= render 'form' %> + +<%= link_to 'Back', urls_path %> diff --git a/source/app/views/urls/show.html.erb b/source/app/views/urls/show.html.erb new file mode 100644 index 0000000..79c4405 --- /dev/null +++ b/source/app/views/urls/show.html.erb @@ -0,0 +1,24 @@ +

<%= notice %>

+ +

+ Long url: + <%= @url.long_url %> +

+ +

+ Short url: + <%= @url.short_url %> +

+ +

+ Name: + <%= @url.name %> +

+ +

+ Clicks: + <%= @url.clicks %> +

+ +<%= link_to 'Edit', edit_url_path(@url) %> | +<%= link_to 'Back', urls_path %> diff --git a/source/app/views/urls/show.json.jbuilder b/source/app/views/urls/show.json.jbuilder new file mode 100644 index 0000000..3fd812b --- /dev/null +++ b/source/app/views/urls/show.json.jbuilder @@ -0,0 +1 @@ +json.extract! @url, :id, :long_url, :short_url, :name, :clicks, :created_at, :updated_at diff --git a/source/config/routes.rb b/source/config/routes.rb index 3f66539..ff8326b 100644 --- a/source/config/routes.rb +++ b/source/config/routes.rb @@ -1,4 +1,6 @@ Rails.application.routes.draw do + resources :urls + # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". diff --git a/source/db/migrate/20150205161959_create_urls.rb b/source/db/migrate/20150205161959_create_urls.rb new file mode 100644 index 0000000..d4c917d --- /dev/null +++ b/source/db/migrate/20150205161959_create_urls.rb @@ -0,0 +1,12 @@ +class CreateUrls < ActiveRecord::Migration + def change + create_table :urls do |t| + t.string :long_url + t.string :short_url + t.string :name + t.integer :clicks + + t.timestamps + end + end +end diff --git a/source/db/schema.rb b/source/db/schema.rb new file mode 100644 index 0000000..7113c1b --- /dev/null +++ b/source/db/schema.rb @@ -0,0 +1,25 @@ +# encoding: UTF-8 +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 20150205161959) do + + create_table "urls", force: true do |t| + t.string "long_url" + t.string "short_url" + t.string "name" + t.integer "clicks" + t.datetime "created_at" + t.datetime "updated_at" + end + +end diff --git a/source/spec/controllers/urls_controller_spec.rb b/source/spec/controllers/urls_controller_spec.rb new file mode 100644 index 0000000..7014ddd --- /dev/null +++ b/source/spec/controllers/urls_controller_spec.rb @@ -0,0 +1,159 @@ +require 'rails_helper' + +# This spec was generated by rspec-rails when you ran the scaffold generator. +# It demonstrates how one might use RSpec to specify the controller code that +# was generated by Rails when you ran the scaffold generator. +# +# It assumes that the implementation code is generated by the rails scaffold +# generator. If you are using any extension libraries to generate different +# controller code, this generated spec may or may not pass. +# +# It only uses APIs available in rails and/or rspec-rails. There are a number +# of tools you can use to make these specs even more expressive, but we're +# sticking to rails and rspec-rails APIs to keep things simple and stable. +# +# Compared to earlier versions of this generator, there is very limited use of +# stubs and message expectations in this spec. Stubs are only used when there +# is no simpler way to get a handle on the object needed for the example. +# Message expectations are only used when there is no simpler way to specify +# that an instance is receiving a specific message. + +RSpec.describe UrlsController, :type => :controller do + + # This should return the minimal set of attributes required to create a valid + # Url. As you add validations to Url, be sure to + # adjust the attributes here as well. + let(:valid_attributes) { + skip("Add a hash of attributes valid for your model") + } + + let(:invalid_attributes) { + skip("Add a hash of attributes invalid for your model") + } + + # This should return the minimal set of values that should be in the session + # in order to pass any filters (e.g. authentication) defined in + # UrlsController. Be sure to keep this updated too. + let(:valid_session) { {} } + + describe "GET index" do + it "assigns all urls as @urls" do + url = Url.create! valid_attributes + get :index, {}, valid_session + expect(assigns(:urls)).to eq([url]) + end + end + + describe "GET show" do + it "assigns the requested url as @url" do + url = Url.create! valid_attributes + get :show, {:id => url.to_param}, valid_session + expect(assigns(:url)).to eq(url) + end + end + + describe "GET new" do + it "assigns a new url as @url" do + get :new, {}, valid_session + expect(assigns(:url)).to be_a_new(Url) + end + end + + describe "GET edit" do + it "assigns the requested url as @url" do + url = Url.create! valid_attributes + get :edit, {:id => url.to_param}, valid_session + expect(assigns(:url)).to eq(url) + end + end + + describe "POST create" do + describe "with valid params" do + it "creates a new Url" do + expect { + post :create, {:url => valid_attributes}, valid_session + }.to change(Url, :count).by(1) + end + + it "assigns a newly created url as @url" do + post :create, {:url => valid_attributes}, valid_session + expect(assigns(:url)).to be_a(Url) + expect(assigns(:url)).to be_persisted + end + + it "redirects to the created url" do + post :create, {:url => valid_attributes}, valid_session + expect(response).to redirect_to(Url.last) + end + end + + describe "with invalid params" do + it "assigns a newly created but unsaved url as @url" do + post :create, {:url => invalid_attributes}, valid_session + expect(assigns(:url)).to be_a_new(Url) + end + + it "re-renders the 'new' template" do + post :create, {:url => invalid_attributes}, valid_session + expect(response).to render_template("new") + end + end + end + + describe "PUT update" do + describe "with valid params" do + let(:new_attributes) { + skip("Add a hash of attributes valid for your model") + } + + it "updates the requested url" do + url = Url.create! valid_attributes + put :update, {:id => url.to_param, :url => new_attributes}, valid_session + url.reload + skip("Add assertions for updated state") + end + + it "assigns the requested url as @url" do + url = Url.create! valid_attributes + put :update, {:id => url.to_param, :url => valid_attributes}, valid_session + expect(assigns(:url)).to eq(url) + end + + it "redirects to the url" do + url = Url.create! valid_attributes + put :update, {:id => url.to_param, :url => valid_attributes}, valid_session + expect(response).to redirect_to(url) + end + end + + describe "with invalid params" do + it "assigns the url as @url" do + url = Url.create! valid_attributes + put :update, {:id => url.to_param, :url => invalid_attributes}, valid_session + expect(assigns(:url)).to eq(url) + end + + it "re-renders the 'edit' template" do + url = Url.create! valid_attributes + put :update, {:id => url.to_param, :url => invalid_attributes}, valid_session + expect(response).to render_template("edit") + end + end + end + + describe "DELETE destroy" do + it "destroys the requested url" do + url = Url.create! valid_attributes + expect { + delete :destroy, {:id => url.to_param}, valid_session + }.to change(Url, :count).by(-1) + end + + it "redirects to the urls list" do + url = Url.create! valid_attributes + delete :destroy, {:id => url.to_param}, valid_session + expect(response).to redirect_to(urls_url) + end + end + +end diff --git a/source/spec/helpers/urls_helper_spec.rb b/source/spec/helpers/urls_helper_spec.rb new file mode 100644 index 0000000..bbafaf3 --- /dev/null +++ b/source/spec/helpers/urls_helper_spec.rb @@ -0,0 +1,15 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the UrlsHelper. For example: +# +# describe UrlsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe UrlsHelper, :type => :helper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/source/spec/models/url_spec.rb b/source/spec/models/url_spec.rb new file mode 100644 index 0000000..209ca4c --- /dev/null +++ b/source/spec/models/url_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe Url, :type => :model do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/source/spec/requests/urls_spec.rb b/source/spec/requests/urls_spec.rb new file mode 100644 index 0000000..cd1976c --- /dev/null +++ b/source/spec/requests/urls_spec.rb @@ -0,0 +1,10 @@ +require 'rails_helper' + +RSpec.describe "Urls", :type => :request do + describe "GET /urls" do + it "works! (now write some real specs)" do + get urls_path + expect(response).to have_http_status(200) + end + end +end diff --git a/source/spec/routing/urls_routing_spec.rb b/source/spec/routing/urls_routing_spec.rb new file mode 100644 index 0000000..d4ec06f --- /dev/null +++ b/source/spec/routing/urls_routing_spec.rb @@ -0,0 +1,35 @@ +require "rails_helper" + +RSpec.describe UrlsController, :type => :routing do + describe "routing" do + + it "routes to #index" do + expect(:get => "/urls").to route_to("urls#index") + end + + it "routes to #new" do + expect(:get => "/urls/new").to route_to("urls#new") + end + + it "routes to #show" do + expect(:get => "/urls/1").to route_to("urls#show", :id => "1") + end + + it "routes to #edit" do + expect(:get => "/urls/1/edit").to route_to("urls#edit", :id => "1") + end + + it "routes to #create" do + expect(:post => "/urls").to route_to("urls#create") + end + + it "routes to #update" do + expect(:put => "/urls/1").to route_to("urls#update", :id => "1") + end + + it "routes to #destroy" do + expect(:delete => "/urls/1").to route_to("urls#destroy", :id => "1") + end + + end +end diff --git a/source/spec/views/urls/edit.html.erb_spec.rb b/source/spec/views/urls/edit.html.erb_spec.rb new file mode 100644 index 0000000..4bf6d71 --- /dev/null +++ b/source/spec/views/urls/edit.html.erb_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.describe "urls/edit", :type => :view do + before(:each) do + @url = assign(:url, Url.create!( + :long_url => "MyString", + :short_url => "MyString", + :name => "MyString", + :clicks => 1 + )) + end + + it "renders the edit url form" do + render + + assert_select "form[action=?][method=?]", url_path(@url), "post" do + + assert_select "input#url_long_url[name=?]", "url[long_url]" + + assert_select "input#url_short_url[name=?]", "url[short_url]" + + assert_select "input#url_name[name=?]", "url[name]" + + assert_select "input#url_clicks[name=?]", "url[clicks]" + end + end +end diff --git a/source/spec/views/urls/index.html.erb_spec.rb b/source/spec/views/urls/index.html.erb_spec.rb new file mode 100644 index 0000000..3b57919 --- /dev/null +++ b/source/spec/views/urls/index.html.erb_spec.rb @@ -0,0 +1,28 @@ +require 'rails_helper' + +RSpec.describe "urls/index", :type => :view do + before(:each) do + assign(:urls, [ + Url.create!( + :long_url => "Long Url", + :short_url => "Short Url", + :name => "Name", + :clicks => 1 + ), + Url.create!( + :long_url => "Long Url", + :short_url => "Short Url", + :name => "Name", + :clicks => 1 + ) + ]) + end + + it "renders a list of urls" do + render + assert_select "tr>td", :text => "Long Url".to_s, :count => 2 + assert_select "tr>td", :text => "Short Url".to_s, :count => 2 + assert_select "tr>td", :text => "Name".to_s, :count => 2 + assert_select "tr>td", :text => 1.to_s, :count => 2 + end +end diff --git a/source/spec/views/urls/new.html.erb_spec.rb b/source/spec/views/urls/new.html.erb_spec.rb new file mode 100644 index 0000000..71c2a7d --- /dev/null +++ b/source/spec/views/urls/new.html.erb_spec.rb @@ -0,0 +1,27 @@ +require 'rails_helper' + +RSpec.describe "urls/new", :type => :view do + before(:each) do + assign(:url, Url.new( + :long_url => "MyString", + :short_url => "MyString", + :name => "MyString", + :clicks => 1 + )) + end + + it "renders new url form" do + render + + assert_select "form[action=?][method=?]", urls_path, "post" do + + assert_select "input#url_long_url[name=?]", "url[long_url]" + + assert_select "input#url_short_url[name=?]", "url[short_url]" + + assert_select "input#url_name[name=?]", "url[name]" + + assert_select "input#url_clicks[name=?]", "url[clicks]" + end + end +end diff --git a/source/spec/views/urls/show.html.erb_spec.rb b/source/spec/views/urls/show.html.erb_spec.rb new file mode 100644 index 0000000..1c74036 --- /dev/null +++ b/source/spec/views/urls/show.html.erb_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe "urls/show", :type => :view do + before(:each) do + @url = assign(:url, Url.create!( + :long_url => "Long Url", + :short_url => "Short Url", + :name => "Name", + :clicks => 1 + )) + end + + it "renders attributes in

" do + render + expect(rendered).to match(/Long Url/) + expect(rendered).to match(/Short Url/) + expect(rendered).to match(/Name/) + expect(rendered).to match(/1/) + end +end From e47d0021e3bf9378aa35b2853bbf9bfd74da02b0 Mon Sep 17 00:00:00 2001 From: Mike Kenworthy Date: Thu, 5 Feb 2015 20:45:16 -0500 Subject: [PATCH 2/3] More Changes --- source/Gemfile | 5 +++ source/Gemfile.lock | 9 ++++++ source/app/assets/stylesheets/application.css | 15 --------- .../assets/stylesheets/application.css.sass | 29 +++++++++++++++++ source/app/controllers/urls_controller.rb | 13 +++++++- source/app/views/layouts/application.html.erb | 14 --------- .../app/views/layouts/application.html.haml | 16 ++++++++++ source/app/views/partials/_nav.html.haml | 20 ++++++++++++ source/app/views/urls/index.html.erb | 31 ------------------- source/app/views/urls/index.html.haml | 24 ++++++++++++++ source/app/views/urls/stats.html.erb | 24 ++++++++++++++ source/config/routes.rb | 7 +++++ 12 files changed, 146 insertions(+), 61 deletions(-) delete mode 100644 source/app/assets/stylesheets/application.css create mode 100644 source/app/assets/stylesheets/application.css.sass delete mode 100644 source/app/views/layouts/application.html.erb create mode 100644 source/app/views/layouts/application.html.haml create mode 100644 source/app/views/partials/_nav.html.haml delete mode 100644 source/app/views/urls/index.html.erb create mode 100644 source/app/views/urls/index.html.haml create mode 100644 source/app/views/urls/stats.html.erb diff --git a/source/Gemfile b/source/Gemfile index 9627b8b..d21e835 100644 --- a/source/Gemfile +++ b/source/Gemfile @@ -6,11 +6,16 @@ gem 'rails', '4.1.6' # Use sqlite3 as the database for Active Record gem 'sqlite3' # Use SCSS for stylesheets +gem 'bootstrap-sass', '~> 3.2.0' gem 'sass-rails', '~> 4.0.3' +gem 'autoprefixer-rails' + # Use Uglifier as compressor for JavaScript assets gem 'uglifier', '>= 1.3.0' # Use CoffeeScript for .js.coffee assets and views gem 'coffee-rails', '~> 4.0.0' + +gem 'haml' # See https://github.com/sstephenson/execjs#readme for more supported runtimes # gem 'therubyracer', platforms: :ruby diff --git a/source/Gemfile.lock b/source/Gemfile.lock index fcf8b98..d519ebf 100644 --- a/source/Gemfile.lock +++ b/source/Gemfile.lock @@ -28,6 +28,10 @@ GEM thread_safe (~> 0.1) tzinfo (~> 1.1) arel (5.0.1.20140414130214) + autoprefixer-rails (3.1.2.20141016) + execjs + bootstrap-sass (3.2.0.2) + sass (~> 3.2) builder (3.2.2) coffee-rails (4.0.1) coffee-script (>= 2.2.0) @@ -39,6 +43,8 @@ GEM diff-lcs (1.2.5) erubis (2.7.0) execjs (2.2.1) + haml (4.0.6) + tilt hike (1.2.3) i18n (0.6.11) jbuilder (2.2.2) @@ -125,7 +131,10 @@ PLATFORMS ruby DEPENDENCIES + autoprefixer-rails + bootstrap-sass (~> 3.2.0) coffee-rails (~> 4.0.0) + haml jbuilder (~> 2.0) jquery-rails rails (= 4.1.6) diff --git a/source/app/assets/stylesheets/application.css b/source/app/assets/stylesheets/application.css deleted file mode 100644 index a443db3..0000000 --- a/source/app/assets/stylesheets/application.css +++ /dev/null @@ -1,15 +0,0 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the bottom of the - * compiled file so the styles you add here take precedence over styles defined in any styles - * defined in the other CSS/SCSS files in this directory. It is generally better to create a new - * file per style scope. - * - *= require_tree . - *= require_self - */ diff --git a/source/app/assets/stylesheets/application.css.sass b/source/app/assets/stylesheets/application.css.sass new file mode 100644 index 0000000..a233e6e --- /dev/null +++ b/source/app/assets/stylesheets/application.css.sass @@ -0,0 +1,29 @@ +@import "bootstrap-sprockets" +@import "bootstrap" + +.primary-body + margin: 0 auto + padding-top: 75px + + +.flash + border: solid 1px darken(green, 20%) + text-align: center + padding: 5px + color: white + + +.flash_notice + display: block + @extend .flash + background: green + +.flash_alert + @extend .flash + background: red + +table, th, td + border: 1px solid grey + text-align: left + padding: 5px + background-color: light-grey \ No newline at end of file diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index 6d826ea..551be21 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -1,5 +1,5 @@ class UrlsController < ApplicationController - before_action :set_url, only: [:show, :edit, :update, :destroy] + before_action :set_url, only: [:show, :stats, :edit, :update, :destroy] # GET /urls # GET /urls.json @@ -12,11 +12,22 @@ def index def show end + def expand + if @url = Url.find_by(short_url: params[:short_url]) + redirect_to @url.long_url + else + redirect_to '/', alert: "URL not found!" + end + end + # GET /urls/new def new @url = Url.new end + def stats + end + # GET /urls/1/edit def edit end diff --git a/source/app/views/layouts/application.html.erb b/source/app/views/layouts/application.html.erb deleted file mode 100644 index f946432..0000000 --- a/source/app/views/layouts/application.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - - - - Source - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> - <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> - <%= csrf_meta_tags %> - - - -<%= yield %> - - - diff --git a/source/app/views/layouts/application.html.haml b/source/app/views/layouts/application.html.haml new file mode 100644 index 0000000..069fbaf --- /dev/null +++ b/source/app/views/layouts/application.html.haml @@ -0,0 +1,16 @@ +!!! 5 +%html + %head + %title Source + = stylesheet_link_tag 'application', { media: 'all', 'data-turbolinks-track' => true } + = javascript_include_tag 'application', { 'data-turbolinks-track' => true } + = csrf_meta_tags + %body + + = render 'partials/nav' + + .container.primary-body + - flash.each do |name, msg| + = content_tag :div, msg, :class => "flash_#{name}" + + = yield \ No newline at end of file diff --git a/source/app/views/partials/_nav.html.haml b/source/app/views/partials/_nav.html.haml new file mode 100644 index 0000000..ab19615 --- /dev/null +++ b/source/app/views/partials/_nav.html.haml @@ -0,0 +1,20 @@ +%nav.navbar.navbar-default.navbar-fixed-top{ role: 'navigation' } + .container + .navbar-header + %button{ class: "navbar-toggle", "data-toggle" => "collapse", "data-target" => "#bs-example-navbar-collapse-1" } + %span.sr-only Toggle navigation + %span.icon-bar + %span.icon-bar + %span.icon-bar + %a{ class: "navbar-brand", href: "/" } + Super App + .collapse.navbar-collapse#bs-example-navbar-collapse-1 + %ul.nav.navbar-nav.navbar-right + %li=link_to 'Home', root_url + - if @current_user + %li= link_to "Logged in as #{@current_user.email}", user_path(@current_user) + + //%li= link_to "Logout", log_out_path + - else + //%li= link_to "Sign up", sign_up_path + //%li= link_to "login", log_in_path diff --git a/source/app/views/urls/index.html.erb b/source/app/views/urls/index.html.erb deleted file mode 100644 index 4b560da..0000000 --- a/source/app/views/urls/index.html.erb +++ /dev/null @@ -1,31 +0,0 @@ -

Listing urls

- - - - - - - - - - - - - - <% @urls.each do |url| %> - - - - - - - - - - <% end %> - -
Long urlShort urlNameClicks
<%= url.long_url %><%= url.short_url %><%= url.name %><%= url.clicks %><%= link_to 'Show', url %><%= link_to 'Edit', edit_url_path(url) %><%= link_to 'Destroy', url, method: :delete, data: { confirm: 'Are you sure?' } %>
- -
- -<%= link_to 'New Url', new_url_path %> diff --git a/source/app/views/urls/index.html.haml b/source/app/views/urls/index.html.haml new file mode 100644 index 0000000..3b754a6 --- /dev/null +++ b/source/app/views/urls/index.html.haml @@ -0,0 +1,24 @@ +%h1 Listing urls + +%table + %thead + %tr + %th Name + %th Clicks + %th Short url + %th Long url + %th{colspan: "3"} + %tbody> + - @urls.each do |url| + %tr + %td= link_to url.name, url_path(url.short_url) + %td= link_to url.clicks, url_stats_path(url) + %td= link_to url.short_url, expand_url_path(url.short_url) + %td= link_to url.long_url, expand_url_path(url.short_url) + + %td= link_to 'Show', url + %td= link_to 'Edit', edit_url_path(url) + %td= link_to 'Destroy', url, method: :delete, data: { confirm: 'Are you sure?' } +%br + += link_to 'New Url', new_url_path diff --git a/source/app/views/urls/stats.html.erb b/source/app/views/urls/stats.html.erb new file mode 100644 index 0000000..79c4405 --- /dev/null +++ b/source/app/views/urls/stats.html.erb @@ -0,0 +1,24 @@ +

<%= notice %>

+ +

+ Long url: + <%= @url.long_url %> +

+ +

+ Short url: + <%= @url.short_url %> +

+ +

+ Name: + <%= @url.name %> +

+ +

+ Clicks: + <%= @url.clicks %> +

+ +<%= link_to 'Edit', edit_url_path(@url) %> | +<%= link_to 'Back', urls_path %> diff --git a/source/config/routes.rb b/source/config/routes.rb index ff8326b..92b452d 100644 --- a/source/config/routes.rb +++ b/source/config/routes.rb @@ -1,5 +1,12 @@ Rails.application.routes.draw do + resources :urls + get '/urls/stats/:id', to: 'urls#stats', as: 'url_stats' + + get '/:short_url', to: 'urls#expand', as: 'expand_url' + + root 'urls#index' + # The priority is based upon order of creation: first created -> highest priority. # See how all your routes lay out with "rake routes". From 70347d9aebd8350b2b4568f56d21175ad5988cb4 Mon Sep 17 00:00:00 2001 From: Mike Kenworthy Date: Fri, 13 Feb 2015 14:12:22 -0500 Subject: [PATCH 3/3] Validation --- source/app/controllers/urls_controller.rb | 1 + source/app/models/url.rb | 22 ++++++++++++++++++++++ source/app/views/urls/index.html.haml | 6 +++--- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/source/app/controllers/urls_controller.rb b/source/app/controllers/urls_controller.rb index 551be21..2baec40 100644 --- a/source/app/controllers/urls_controller.rb +++ b/source/app/controllers/urls_controller.rb @@ -42,6 +42,7 @@ def create format.html { redirect_to @url, notice: 'Url was successfully created.' } format.json { render :show, status: :created, location: @url } else + flash.now.alert = "Error creating URL!" format.html { render :new } format.json { render json: @url.errors, status: :unprocessable_entity } end diff --git a/source/app/models/url.rb b/source/app/models/url.rb index e4834ff..bd7d138 100644 --- a/source/app/models/url.rb +++ b/source/app/models/url.rb @@ -1,2 +1,24 @@ class Url < ActiveRecord::Base + validates :long_url, format: { with: URI::regexp(%w(http https)), message: "Invalid URL!" } + + before_save :shorten + + validates :short_url, uniqueness: true + validates :name, presence: true + + + def shorten + p "========================Start shorten" + known_sites = { facebook: :fb, google: :goo} + if self.short_url.empty? + p "=======================" + /https:\/\/(?:www.)(\w+).\w{3}\/(.*)((?:\?).*)?/ =~ self.long_url + p self.long_url + p $1 + p $2 + self.short_url = known_sites.has_key?($1) ? known_sites[$1] : $1[0..3] + $2 && self.short_url += $2[0..3] + end + end + end diff --git a/source/app/views/urls/index.html.haml b/source/app/views/urls/index.html.haml index 3b754a6..47386f3 100644 --- a/source/app/views/urls/index.html.haml +++ b/source/app/views/urls/index.html.haml @@ -11,10 +11,10 @@ %tbody> - @urls.each do |url| %tr - %td= link_to url.name, url_path(url.short_url) + //%td= link_to url.name, url_path(url.short_url) %td= link_to url.clicks, url_stats_path(url) - %td= link_to url.short_url, expand_url_path(url.short_url) - %td= link_to url.long_url, expand_url_path(url.short_url) + //%td= link_to url.short_url, expand_url_path(url.short_url) + //%td= link_to url.long_url, expand_url_path(url.short_url) %td= link_to 'Show', url %td= link_to 'Edit', edit_url_path(url)