hammond_data: Split models::insertables into multiple modules.
This commit is contained in:
parent
3766db2b14
commit
3a6f6d8931
@ -11,7 +11,8 @@ use rss;
|
|||||||
use dbqueries;
|
use dbqueries;
|
||||||
|
|
||||||
use models::queryables::{Podcast, Source};
|
use models::queryables::{Podcast, Source};
|
||||||
use models::insertables::{NewEpisode, NewPodcast};
|
use models::NewPodcast;
|
||||||
|
use models::NewEpisode;
|
||||||
use database::connection;
|
use database::connection;
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,25 @@
|
|||||||
pub(crate) mod insertables;
|
|
||||||
pub(crate) mod queryables;
|
pub(crate) mod queryables;
|
||||||
|
pub(crate) mod new_episode;
|
||||||
|
pub(crate) mod new_podcast;
|
||||||
|
pub(crate) mod new_source;
|
||||||
|
|
||||||
|
use diesel::prelude::*;
|
||||||
|
|
||||||
|
pub(crate) use self::new_episode::{NewEpisode, NewEpisodeMinimal};
|
||||||
|
pub(crate) use self::new_podcast::NewPodcast;
|
||||||
|
pub(crate) use self::new_source::NewSource;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
enum IndexState<T> {
|
||||||
|
Index(T),
|
||||||
|
Update(T),
|
||||||
|
NotChanged,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Insert {
|
||||||
|
fn insert(&self, &SqliteConnection) -> QueryResult<usize>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Update {
|
||||||
|
fn update(&self, &SqliteConnection, i32) -> QueryResult<usize>;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,196 +1,18 @@
|
|||||||
#![allow(unused_mut)]
|
|
||||||
|
|
||||||
use diesel::prelude::*;
|
use diesel::prelude::*;
|
||||||
use diesel;
|
use diesel;
|
||||||
|
use schema::episode;
|
||||||
|
|
||||||
use rss;
|
use rss;
|
||||||
use ammonia;
|
use ammonia;
|
||||||
use rfc822_sanitizer::parse_from_rfc2822_with_fallback as parse_rfc822;
|
use rfc822_sanitizer::parse_from_rfc2822_with_fallback as parse_rfc822;
|
||||||
use utils::{replace_extra_spaces, url_cleaner};
|
|
||||||
|
|
||||||
use schema::{episode, podcast, source};
|
|
||||||
use models::queryables::{Episode, Podcast, Source};
|
|
||||||
use dbqueries;
|
use dbqueries;
|
||||||
use database::connection;
|
|
||||||
use parser;
|
|
||||||
|
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
use models::{Insert, Update};
|
||||||
|
use models::queryables::Episode;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
use utils::{replace_extra_spaces, url_cleaner};
|
||||||
enum IndexState<T> {
|
use parser;
|
||||||
Index(T),
|
|
||||||
Update(T),
|
|
||||||
NotChanged,
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Insert {
|
|
||||||
fn insert(&self, &SqliteConnection) -> QueryResult<usize>;
|
|
||||||
}
|
|
||||||
|
|
||||||
trait Update {
|
|
||||||
fn update(&self, &SqliteConnection, i32) -> QueryResult<usize>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Insertable)]
|
|
||||||
#[table_name = "source"]
|
|
||||||
#[derive(Debug, Clone, Default, Builder, PartialEq)]
|
|
||||||
#[builder(default)]
|
|
||||||
#[builder(derive(Debug))]
|
|
||||||
#[builder(setter(into))]
|
|
||||||
pub(crate) struct NewSource {
|
|
||||||
uri: String,
|
|
||||||
last_modified: Option<String>,
|
|
||||||
http_etag: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Insert for NewSource {
|
|
||||||
fn insert(&self, con: &SqliteConnection) -> QueryResult<usize> {
|
|
||||||
use schema::source::dsl::*;
|
|
||||||
diesel::insert_into(source).values(self).execute(&*con)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NewSource {
|
|
||||||
pub(crate) fn new(uri: &str) -> NewSource {
|
|
||||||
NewSource {
|
|
||||||
uri: uri.trim().to_string(),
|
|
||||||
last_modified: None,
|
|
||||||
http_etag: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn index(&self) -> Result<()> {
|
|
||||||
let db = connection();
|
|
||||||
let con = db.get()?;
|
|
||||||
|
|
||||||
// Throw away the result like `insert or ignore`
|
|
||||||
// Diesel deos not support `insert or ignore` yet.
|
|
||||||
let _ = self.insert(&con);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look out for when tryinto lands into stable.
|
|
||||||
pub(crate) fn into_source(self) -> Result<Source> {
|
|
||||||
self.index()?;
|
|
||||||
dbqueries::get_source_from_uri(&self.uri)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset)]
|
|
||||||
#[table_name = "podcast"]
|
|
||||||
#[derive(Debug, Clone, Default, Builder, PartialEq)]
|
|
||||||
#[builder(default)]
|
|
||||||
#[builder(derive(Debug))]
|
|
||||||
#[builder(setter(into))]
|
|
||||||
pub(crate) struct NewPodcast {
|
|
||||||
title: String,
|
|
||||||
link: String,
|
|
||||||
description: String,
|
|
||||||
image_uri: Option<String>,
|
|
||||||
source_id: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Insert for NewPodcast {
|
|
||||||
fn insert(&self, con: &SqliteConnection) -> QueryResult<usize> {
|
|
||||||
use schema::podcast::dsl::*;
|
|
||||||
diesel::insert_into(podcast).values(self).execute(&*con)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Update for NewPodcast {
|
|
||||||
fn update(&self, con: &SqliteConnection, podcast_id: i32) -> QueryResult<usize> {
|
|
||||||
use schema::podcast::dsl::*;
|
|
||||||
|
|
||||||
info!("Updating {}", self.title);
|
|
||||||
diesel::update(podcast.filter(id.eq(podcast_id)))
|
|
||||||
.set(self)
|
|
||||||
.execute(&*con)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NewPodcast {
|
|
||||||
/// Parses a `rss::Channel` into a `NewPodcast` Struct.
|
|
||||||
pub(crate) fn new(chan: &rss::Channel, source_id: i32) -> NewPodcast {
|
|
||||||
let title = chan.title().trim();
|
|
||||||
|
|
||||||
// Prefer itunes summary over rss.description since many feeds put html into
|
|
||||||
// rss.description.
|
|
||||||
let summary = chan.itunes_ext().map(|s| s.summary()).and_then(|s| s);
|
|
||||||
let description = if let Some(sum) = summary {
|
|
||||||
replace_extra_spaces(&ammonia::clean(sum))
|
|
||||||
} else {
|
|
||||||
replace_extra_spaces(&ammonia::clean(chan.description()))
|
|
||||||
};
|
|
||||||
|
|
||||||
let link = url_cleaner(chan.link());
|
|
||||||
let x = chan.itunes_ext().map(|s| s.image());
|
|
||||||
let image_uri = if let Some(img) = x {
|
|
||||||
img.map(|s| s.to_owned())
|
|
||||||
} else {
|
|
||||||
chan.image().map(|foo| foo.url().to_owned())
|
|
||||||
};
|
|
||||||
|
|
||||||
NewPodcastBuilder::default()
|
|
||||||
.title(title)
|
|
||||||
.description(description)
|
|
||||||
.link(link)
|
|
||||||
.image_uri(image_uri)
|
|
||||||
.source_id(source_id)
|
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look out for when tryinto lands into stable.
|
|
||||||
pub(crate) fn into_podcast(self) -> Result<Podcast> {
|
|
||||||
self.index()?;
|
|
||||||
Ok(dbqueries::get_podcast_from_source_id(self.source_id)?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn index(&self) -> Result<()> {
|
|
||||||
let pd = dbqueries::get_podcast_from_source_id(self.source_id);
|
|
||||||
|
|
||||||
let db = connection();
|
|
||||||
let con = db.get()?;
|
|
||||||
match pd {
|
|
||||||
Ok(foo) => {
|
|
||||||
if (foo.link() != self.link) || (foo.title() != self.title)
|
|
||||||
|| (foo.image_uri() != self.image_uri.as_ref().map(|x| x.as_str()))
|
|
||||||
{
|
|
||||||
info!("NewEpisode: {:?}\n OldEpisode: {:?}", self, foo);
|
|
||||||
self.update(&con, foo.id())?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
self.insert(&con)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
// Ignore the following geters. They are used in unit tests mainly.
|
|
||||||
impl NewPodcast {
|
|
||||||
pub(crate) fn source_id(&self) -> i32 {
|
|
||||||
self.source_id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn title(&self) -> &str {
|
|
||||||
&self.title
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn link(&self) -> &str {
|
|
||||||
&self.link
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn description(&self) -> &str {
|
|
||||||
&self.description
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn image_uri(&self) -> Option<&str> {
|
|
||||||
self.image_uri.as_ref().map(|s| s.as_str())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "episode"]
|
#[table_name = "episode"]
|
||||||
@ -217,6 +39,7 @@ impl From<NewEpisodeMinimal> for NewEpisode {
|
|||||||
.duration(e.duration)
|
.duration(e.duration)
|
||||||
.epoch(e.epoch)
|
.epoch(e.epoch)
|
||||||
.podcast_id(e.podcast_id)
|
.podcast_id(e.podcast_id)
|
||||||
|
.guid(e.guid)
|
||||||
.build()
|
.build()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
@ -324,17 +147,19 @@ pub(crate) struct NewEpisodeMinimal {
|
|||||||
uri: Option<String>,
|
uri: Option<String>,
|
||||||
duration: Option<i32>,
|
duration: Option<i32>,
|
||||||
epoch: i32,
|
epoch: i32,
|
||||||
|
guid: Option<String>,
|
||||||
podcast_id: i32,
|
podcast_id: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NewEpisodeMinimal {
|
impl NewEpisodeMinimal {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn new(item: &rss::Item, parent_id: i32) -> Result<Self> {
|
pub(crate) fn new(item: &rss::Item, parent_id: i32) -> Result<Self> {
|
||||||
if item.title().is_none() {
|
if item.title().is_none() {
|
||||||
bail!("No title specified for the item.")
|
bail!("No title specified for the item.")
|
||||||
}
|
}
|
||||||
|
|
||||||
let title = item.title().unwrap().trim().to_owned();
|
let title = item.title().unwrap().trim().to_owned();
|
||||||
|
let guid = item.guid().map(|s| s.value().trim().to_owned());
|
||||||
|
|
||||||
let uri = if let Some(url) = item.enclosure().map(|s| url_cleaner(s.url())) {
|
let uri = if let Some(url) = item.enclosure().map(|s| url_cleaner(s.url())) {
|
||||||
Some(url)
|
Some(url)
|
||||||
@ -359,14 +184,14 @@ impl NewEpisodeMinimal {
|
|||||||
.uri(uri)
|
.uri(uri)
|
||||||
.duration(duration)
|
.duration(duration)
|
||||||
.epoch(epoch)
|
.epoch(epoch)
|
||||||
|
.guid(guid)
|
||||||
.podcast_id(parent_id)
|
.podcast_id(parent_id)
|
||||||
.build()
|
.build()
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn into_new_episode(self, item: &rss::Item) -> NewEpisode {
|
pub(crate) fn into_new_episode(self, item: &rss::Item) -> NewEpisode {
|
||||||
let guid = item.guid().map(|s| s.value().trim().to_owned());
|
|
||||||
let length = || -> Option<i32> { item.enclosure().map(|x| x.length().parse().ok())? }();
|
let length = || -> Option<i32> { item.enclosure().map(|x| x.length().parse().ok())? }();
|
||||||
|
|
||||||
// Prefer itunes summary over rss.description since many feeds put html into
|
// Prefer itunes summary over rss.description since many feeds put html into
|
||||||
@ -385,7 +210,7 @@ impl NewEpisodeMinimal {
|
|||||||
.duration(self.duration)
|
.duration(self.duration)
|
||||||
.epoch(self.epoch)
|
.epoch(self.epoch)
|
||||||
.podcast_id(self.podcast_id)
|
.podcast_id(self.podcast_id)
|
||||||
.guid(guid)
|
.guid(self.guid)
|
||||||
.length(length)
|
.length(length)
|
||||||
.description(description)
|
.description(description)
|
||||||
.build()
|
.build()
|
||||||
131
hammond-data/src/models/new_podcast.rs
Normal file
131
hammond-data/src/models/new_podcast.rs
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
use diesel::prelude::*;
|
||||||
|
use diesel;
|
||||||
|
|
||||||
|
use rss;
|
||||||
|
use ammonia;
|
||||||
|
|
||||||
|
use schema::podcast;
|
||||||
|
use models::queryables::Podcast;
|
||||||
|
use models::{Insert, Update};
|
||||||
|
|
||||||
|
use dbqueries;
|
||||||
|
use database::connection;
|
||||||
|
use utils::{replace_extra_spaces, url_cleaner};
|
||||||
|
|
||||||
|
use errors::*;
|
||||||
|
|
||||||
|
#[derive(Insertable, AsChangeset)]
|
||||||
|
#[table_name = "podcast"]
|
||||||
|
#[derive(Debug, Clone, Default, Builder, PartialEq)]
|
||||||
|
#[builder(default)]
|
||||||
|
#[builder(derive(Debug))]
|
||||||
|
#[builder(setter(into))]
|
||||||
|
pub(crate) struct NewPodcast {
|
||||||
|
title: String,
|
||||||
|
link: String,
|
||||||
|
description: String,
|
||||||
|
image_uri: Option<String>,
|
||||||
|
source_id: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Insert for NewPodcast {
|
||||||
|
fn insert(&self, con: &SqliteConnection) -> QueryResult<usize> {
|
||||||
|
use schema::podcast::dsl::*;
|
||||||
|
diesel::insert_into(podcast).values(self).execute(&*con)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Update for NewPodcast {
|
||||||
|
fn update(&self, con: &SqliteConnection, podcast_id: i32) -> QueryResult<usize> {
|
||||||
|
use schema::podcast::dsl::*;
|
||||||
|
|
||||||
|
info!("Updating {}", self.title);
|
||||||
|
diesel::update(podcast.filter(id.eq(podcast_id)))
|
||||||
|
.set(self)
|
||||||
|
.execute(&*con)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NewPodcast {
|
||||||
|
/// Parses a `rss::Channel` into a `NewPodcast` Struct.
|
||||||
|
pub(crate) fn new(chan: &rss::Channel, source_id: i32) -> NewPodcast {
|
||||||
|
let title = chan.title().trim();
|
||||||
|
|
||||||
|
// Prefer itunes summary over rss.description since many feeds put html into
|
||||||
|
// rss.description.
|
||||||
|
let summary = chan.itunes_ext().map(|s| s.summary()).and_then(|s| s);
|
||||||
|
let description = if let Some(sum) = summary {
|
||||||
|
replace_extra_spaces(&ammonia::clean(sum))
|
||||||
|
} else {
|
||||||
|
replace_extra_spaces(&ammonia::clean(chan.description()))
|
||||||
|
};
|
||||||
|
|
||||||
|
let link = url_cleaner(chan.link());
|
||||||
|
let x = chan.itunes_ext().map(|s| s.image());
|
||||||
|
let image_uri = if let Some(img) = x {
|
||||||
|
img.map(|s| s.to_owned())
|
||||||
|
} else {
|
||||||
|
chan.image().map(|foo| foo.url().to_owned())
|
||||||
|
};
|
||||||
|
|
||||||
|
NewPodcastBuilder::default()
|
||||||
|
.title(title)
|
||||||
|
.description(description)
|
||||||
|
.link(link)
|
||||||
|
.image_uri(image_uri)
|
||||||
|
.source_id(source_id)
|
||||||
|
.build()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look out for when tryinto lands into stable.
|
||||||
|
pub(crate) fn into_podcast(self) -> Result<Podcast> {
|
||||||
|
self.index()?;
|
||||||
|
Ok(dbqueries::get_podcast_from_source_id(self.source_id)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn index(&self) -> Result<()> {
|
||||||
|
let pd = dbqueries::get_podcast_from_source_id(self.source_id);
|
||||||
|
|
||||||
|
let db = connection();
|
||||||
|
let con = db.get()?;
|
||||||
|
match pd {
|
||||||
|
Ok(foo) => {
|
||||||
|
if (foo.link() != self.link) || (foo.title() != self.title)
|
||||||
|
|| (foo.image_uri() != self.image_uri.as_ref().map(|x| x.as_str()))
|
||||||
|
{
|
||||||
|
info!("NewEpisode: {:?}\n OldEpisode: {:?}", self, foo);
|
||||||
|
self.update(&con, foo.id())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
self.insert(&con)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
// Ignore the following geters. They are used in unit tests mainly.
|
||||||
|
impl NewPodcast {
|
||||||
|
pub(crate) fn source_id(&self) -> i32 {
|
||||||
|
self.source_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn title(&self) -> &str {
|
||||||
|
&self.title
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn link(&self) -> &str {
|
||||||
|
&self.link
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn description(&self) -> &str {
|
||||||
|
&self.description
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn image_uri(&self) -> Option<&str> {
|
||||||
|
self.image_uri.as_ref().map(|s| s.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
58
hammond-data/src/models/new_source.rs
Normal file
58
hammond-data/src/models/new_source.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#![allow(unused_mut)]
|
||||||
|
|
||||||
|
use diesel::prelude::*;
|
||||||
|
use diesel;
|
||||||
|
|
||||||
|
use schema::source;
|
||||||
|
use models::queryables::Source;
|
||||||
|
use models::{Insert, Update};
|
||||||
|
|
||||||
|
use dbqueries;
|
||||||
|
use database::connection;
|
||||||
|
|
||||||
|
use errors::*;
|
||||||
|
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[table_name = "source"]
|
||||||
|
#[derive(Debug, Clone, Default, Builder, PartialEq)]
|
||||||
|
#[builder(default)]
|
||||||
|
#[builder(derive(Debug))]
|
||||||
|
#[builder(setter(into))]
|
||||||
|
pub(crate) struct NewSource {
|
||||||
|
uri: String,
|
||||||
|
last_modified: Option<String>,
|
||||||
|
http_etag: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Insert for NewSource {
|
||||||
|
fn insert(&self, con: &SqliteConnection) -> QueryResult<usize> {
|
||||||
|
use schema::source::dsl::*;
|
||||||
|
diesel::insert_into(source).values(self).execute(&*con)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NewSource {
|
||||||
|
pub(crate) fn new(uri: &str) -> NewSource {
|
||||||
|
NewSource {
|
||||||
|
uri: uri.trim().to_string(),
|
||||||
|
last_modified: None,
|
||||||
|
http_etag: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn index(&self) -> Result<()> {
|
||||||
|
let db = connection();
|
||||||
|
let con = db.get()?;
|
||||||
|
|
||||||
|
// Throw away the result like `insert or ignore`
|
||||||
|
// Diesel deos not support `insert or ignore` yet.
|
||||||
|
let _ = self.insert(&con);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look out for when tryinto lands into stable.
|
||||||
|
pub(crate) fn into_source(self) -> Result<Source> {
|
||||||
|
self.index()?;
|
||||||
|
dbqueries::get_source_from_uri(&self.uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,7 +19,7 @@ use schema::{episode, podcast, source};
|
|||||||
use feed::Feed;
|
use feed::Feed;
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
|
||||||
use models::insertables::NewSource;
|
use models::NewSource;
|
||||||
use database::connection;
|
use database::connection;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|||||||
@ -36,8 +36,8 @@ mod tests {
|
|||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use rss::{Channel, ItemBuilder};
|
use rss::{Channel, ItemBuilder};
|
||||||
use rss::extension::itunes::ITunesItemExtensionBuilder;
|
use rss::extension::itunes::ITunesItemExtensionBuilder;
|
||||||
use models::insertables::{NewEpisode, NewEpisodeBuilder};
|
use models::new_episode::{NewEpisode, NewEpisodeBuilder};
|
||||||
use models::insertables::{NewPodcast, NewPodcastBuilder};
|
use models::new_podcast::{NewPodcast, NewPodcastBuilder};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|||||||
@ -153,7 +153,7 @@ mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use database::{connection, truncate_db};
|
use database::{connection, truncate_db};
|
||||||
use models::insertables::NewEpisodeBuilder;
|
use models::new_episode::NewEpisodeBuilder;
|
||||||
use self::tempdir::TempDir;
|
use self::tempdir::TempDir;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user