Add basic features

* list movies
* search movies
* add and remove movies from the list
master
Guillaume Dott 2015-10-21 12:37:28 +02:00
parent b41b03f178
commit eb8b14f3dd
15 changed files with 271 additions and 14 deletions

12
.gitignore vendored
View File

@ -1,14 +1,6 @@
/.bundle/ /.bundle/
/.yardoc
/Gemfile.lock /Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/ /tmp/
*.bundle *.bundle
*.so *.map
*.o .sass-cache
*.a
mkmf.log

View File

@ -1,5 +1,15 @@
require "librarix/version" require 'librarix/version'
require 'librarix/redis'
require 'librarix/redis/movie'
require 'librarix/application'
module Librarix module Librarix
# Your code goes here... def self.redis
@redis ||= Librarix::Redis.new(::Redis.new)
end
def self.redis=(connection, namespace: 'librarix')
@redis = Librarix::Redis.new(connection, namespace: namespace)
end
end end

View File

@ -0,0 +1,42 @@
require 'librarix/the_movie_db'
require 'sinatra/base'
require 'sinatra/content_for'
require 'sinatra/json'
require 'yaml'
require 'slim'
require 'themoviedb'
module Librarix
class Application < Sinatra::Application
helpers Librarix::TheMovieDB
get '/' do
slim :index, locals: {movies: Librarix::Redis::Movie.all.sort_by(&:release_date).reverse}
end
get '/search' do
movies = params.key?('search') ? Tmdb::Movie.find(params['search']) : Tmdb::Movie.popular.map { |m| Tmdb::Movie.new(m) }
slim :search, locals: {movies: movies, conf: Tmdb::Configuration.new}
end
post '/add' do
id = params[:id].to_i
movie = Tmdb::Movie.detail(id)
if movie['status_code'] == 34
elsif Librarix::Redis::Movie.new(id).added?
else
Librarix::Redis::Movie.new(id).add
end
redirect to('/')
end
post '/remove' do
Librarix::Redis::Movie.new(params[:id]).remove
redirect to('/')
end
end
end

View File

@ -0,0 +1,35 @@
body {
margin: 0;
}
h2 {
margin-top: 0;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
li {
padding: 10px;
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: center;
.poster {
margin-right: 10px;
}
.informations {
align-self: flex-start;
flex: 1 1 300px;
}
}
li:nth-child(even) {
background-color: #f4f4f4;
}
}

View File

@ -0,0 +1 @@
body{margin:0}h2{margin-top:0}ul{list-style-type:none;margin:0;padding:0}ul li{padding:10px;display:flex;flex-flow:row wrap;align-items:center;justify-content:center}ul li .poster{margin-right:10px}ul li .informations{align-self:flex-start;flex:1 1 300px}ul li:nth-child(even){background-color:#f4f4f4}

View File

@ -0,0 +1,2 @@
document.addEventListener('DOMContentLoaded', function(event) {
});

View File

@ -0,0 +1,49 @@
require 'redis'
module Librarix
class Redis
TTL = 10800
attr_reader :connection, :namespace
def initialize(connection, namespace:)
@connection = connection
@namespace = namespace
end
def exist?(key)
exists key
end
def keys(pattern)
@connection.keys("#{prefix}#{pattern}").map { |key| key.sub(prefix, '') }
end
def fetch(key, options = {})
if options[:force] || (!exist?(key) && block_given?)
value = yield
set key, value
expire key, TTL if options.key?(:ttl) && options[:ttl]
value
else
get key
end
end
def respond_to?(name, include_all = false)
super || @connection.respond_to?(name, include_all)
end
def method_missing(name, *args, &block)
return super unless @connection.respond_to?(name)
@connection.send(name, "#{prefix}#{args.shift}", *args)
end
private
def prefix
"#{namespace}:"
end
end
end

View File

@ -0,0 +1,44 @@
module Librarix
class Redis
class Movie
attr_reader :id
def self.all
Array(Librarix.redis.smembers('movies_id')).map { |id| new(id).fetch }
end
def initialize(id)
@id = id.to_i
end
def add
Librarix.redis.sadd('movies_id', id)
fetch
end
def added?
Librarix.redis.sismember('movies_id', id)
end
def fetch(force = false)
data = JSON.parse(Librarix.redis.fetch("movie:#{id}", force: force) do
Tmdb::Movie.detail(id).to_json
end)
Tmdb::Movie.new(data)
end
def update
fetch(true)
end
def remove
Librarix.redis.del("movie:#{id}")
Librarix.redis.srem('movies_id', id)
end
def view
end
end
end
end

View File

@ -0,0 +1,33 @@
require 'themoviedb'
module Librarix
module TheMovieDB
def poster_url(path, size = 'w92')
base_url = Librarix.redis.fetch('base_url', ttl: true) do
Tmdb::Configuration.new.base_url
end
"#{base_url}#{size}#{path}"
end
def movie(id)
Librarix::Redis::Movie.new(id).fetch
end
module Movie
def release_date
@_release_date ||= Date.parse(super) unless super.nil?
end
def release_year
release_date.year unless release_date.nil?
end
def added?
Librarix::Redis::Movie.new(id).added?
end
end
end
end
Tmdb::Movie.prepend Librarix::TheMovieDB::Movie

View File

View File

@ -0,0 +1,6 @@
- content_for(:title) { 'Index' }
ul
- movies.each do |movie|
li
== slim :movie, locals: {movie: movie}

View File

@ -0,0 +1,11 @@
doctype html
html
head
title = yield_content :title
meta charset="utf-8"
meta name="viewport" content="initial-scale=1.0, user-scalable=yes"
link rel="stylesheet" media="all" href="/application.css"
script type="text/javascript" src="/application.js"
body
div#main
== yield

View File

@ -0,0 +1,16 @@
.poster
- if movie.poster_path
img src="#{poster_url(movie.poster_path, 'w154')}"
.informations
h2
a href="https://www.themoviedb.org/movie/#{movie.id}" #{movie.original_title} (#{movie.release_year})
p = movie.overview
.actions
- if movie.added?
form method="post" action="/remove"
input type="hidden" name="id" value="#{movie.id}"
button type="submit" Remove
- else
form method="post" action="/add"
input type="hidden" name="id" value="#{movie.id}"
button type="submit" Add

View File

@ -0,0 +1,10 @@
- content_for(:title) { 'Search' }
form method="get" action="/search"
input type="text" name="search" value="#{params['search']}"
input type="submit"
ul
- movies.each do |movie|
li
== slim :movie, locals: {movie: movie}

View File

@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
spec.version = Librarix::VERSION spec.version = Librarix::VERSION
spec.authors = ["Guillaume Dott"] spec.authors = ["Guillaume Dott"]
spec.email = ["guillaume+github@dott.fr"] spec.email = ["guillaume+github@dott.fr"]
spec.summary = %q{TODO: Write a short summary. Required.} spec.summary = %q{A simple webapp to manage your collections}
spec.description = %q{TODO: Write a longer description. Optional.} spec.description = %q{Manage all your collections in your browser and automatically fetch infos from TheMovieDB}
spec.homepage = "" spec.homepage = ""
spec.license = "MIT" spec.license = "MIT"
@ -18,6 +18,12 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"] spec.require_paths = ["lib"]
spec.add_dependency "sinatra", '~> 1.4'
spec.add_dependency "sinatra-contrib", '~> 1.4'
spec.add_dependency "slim", '~> 3.0'
spec.add_dependency "redis", '~> 3.2'
spec.add_dependency "themoviedb", '~> 0.1'
spec.add_development_dependency "bundler", "~> 1.7" spec.add_development_dependency "bundler", "~> 1.7"
spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "rake", "~> 10.0"
end end