Add support for generic timeline #525

Merged
Plume_migration_agent merged 58 commits from timeline into master 2019-10-07 17:08:21 +00:00
2 changed files with 73 additions and 13 deletions
Showing only changes of commit afc17f1dfa - Show all commits

View file

@ -1,12 +1,13 @@
use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl}; use diesel::{self, ExpressionMethods, QueryDsl, RunQueryDsl};
use lists::List;
use posts::Post; use posts::Post;
use schema::{posts, timeline, timeline_definition}; use schema::{posts, timeline, timeline_definition};
use {Connection, Error, Result}; use {Connection, Error, Result};
pub(crate) mod query; pub(crate) mod query;
elegaanz commented 2019-05-01 10:00:16 +00:00 (Migrated from github.com)
Review

What is this field for? Is it important to always have a defined order for timelines? And how should it be determined: by the user, or automatically?

What is this field for? Is it important to always have a defined order for timelines? And how should it be determined: by the user, or automatically?
Review

hum, I don't know, my through was that the first one would be on top, the second under and so on, but it clearly limit what can be done, I'll revert that

hum, I don't know, my through was that the first one would be on top, the second under and so on, but it clearly limit what can be done, I'll revert that
use self::query::{Kind, TimelineQuery}; use self::query::{Kind, QueryError, TimelineQuery};
#[derive(Clone, Queryable, Identifiable)] #[derive(Clone, Queryable, Identifiable)]
#[table_name = "timeline_definition"] #[table_name = "timeline_definition"]
@ -47,27 +48,74 @@ impl Timeline {
conn: &Connection, conn: &Connection,
user_id: i32, user_id: i32,
name: String, name: String,
query: String, query_string: String,
) -> Result<Timeline> { ) -> Result<Timeline> {
TimelineQuery::parse(&query)?; // verify the query is valid {
let query = TimelineQuery::parse(&query_string)?; // verify the query is valid
if let Some(err) =
query
Review

Welcome to the party!
Diesel consider that anything eq None unless we are that explicit

Welcome to the party! Diesel consider that anything eq None unless we are that explicit
Review

I've tried for a few hours to add a eq_optional via some trait, but the best I got was "only" 4 compiler error, of which the shortest was 4 lines long. I'm giving up on this

I've tried for a few hours to add a `eq_optional` via some trait, but the best I got was "only" 4 compiler error, of which the shortest was 4 lines long. I'm giving up on this
igalic commented 2019-07-28 18:08:30 +00:00 (Migrated from github.com)
Review

kudos for trying.

kudos for trying.
.list_used_lists()
.into_iter()
.find_map(|(name, kind)| {
let list = List::find_by_name(conn, Some(user_id), &name)
.map(|l| l.kind() == kind);
match list {
Ok(true) => None,
Ok(false) => Some(Error::TimelineQuery(QueryError::RuntimeError(
format!("list '{}' has the wrong type for this usage", name),
))),
Err(_) => Some(Error::TimelineQuery(QueryError::RuntimeError(
format!("list '{}' was not found", name),
))),
}
})
{
Err(err)?;
}
}
Self::insert( Self::insert(
conn, conn,
NewTimeline { NewTimeline {
user_id: Some(user_id), user_id: Some(user_id),
name, name,
query, query: query_string,
}, },
) )
} }
pub fn new_for_instance(conn: &Connection, name: String, query: String) -> Result<Timeline> { pub fn new_for_instance(
TimelineQuery::parse(&query)?; // verify the query is valid conn: &Connection,
name: String,
query_string: String,
) -> Result<Timeline> {
{
let query = TimelineQuery::parse(&query_string)?; // verify the query is valid
if let Some(err) =
query
.list_used_lists()
.into_iter()
.find_map(|(name, kind)| {
let list = List::find_by_name(conn, None, &name).map(|l| l.kind() == kind);
match list {
Ok(true) => None,
Ok(false) => Some(Error::TimelineQuery(QueryError::RuntimeError(
format!("list '{}' has the wrong type for this usage", name),
))),
Err(_) => Some(Error::TimelineQuery(QueryError::RuntimeError(
format!("list '{}' was not found", name),
))),
}
})
{
Err(err)?;
}
}
Self::insert( Self::insert(
conn, conn,
NewTimeline { NewTimeline {
user_id: None, user_id: None,
name, name,
query, query: query_string,
}, },
) )
} }

View file

@ -177,8 +177,8 @@ impl<'a> TQ<'a> {
fn list_used_lists(&self) -> Vec<(String, ListType)> { fn list_used_lists(&self) -> Vec<(String, ListType)> {
match self { match self {
TQ::Or(inner) => inner.iter().flat_map(|e| e.list_used_lists()).collect(), TQ::Or(inner) => inner.iter().flat_map(TQ::list_used_lists).collect(),
TQ::And(inner) => inner.iter().flat_map(|e| e.list_used_lists()).collect(), TQ::And(inner) => inner.iter().flat_map(TQ::list_used_lists).collect(),
TQ::Arg(Arg::In(typ, List::List(name)), _) => vec![( TQ::Arg(Arg::In(typ, List::List(name)), _) => vec![(
name.to_string(), name.to_string(),
match typ { match typ {
@ -270,11 +270,17 @@ impl WithList {
} }
(WithList::Lang, ListType::Prefix) => { (WithList::Lang, ListType::Prefix) => {
let lang = whatlang::detect(post.content.get()) let lang = whatlang::detect(post.content.get())
.and_then(|i| if i.is_reliable() { Some(i.lang()) } else {None} ) .and_then(|i| {
if i.is_reliable() {
Some(i.lang())
} else {
None
}
})
.unwrap_or(Lang::Eng) .unwrap_or(Lang::Eng)
.name(); .name();
list.contains_prefix(conn, lang) list.contains_prefix(conn, lang)
}, }
(_, _) => Err(QueryError::RuntimeError(format!( (_, _) => Err(QueryError::RuntimeError(format!(
"The list '{}' is of the wrong type for this usage", "The list '{}' is of the wrong type for this usage",
name name
@ -313,11 +319,17 @@ impl WithList {
} }
WithList::Lang => { WithList::Lang => {
let lang = whatlang::detect(post.content.get()) let lang = whatlang::detect(post.content.get())
.and_then(|i| if i.is_reliable() { Some(i.lang()) } else {None} ) .and_then(|i| {
if i.is_reliable() {
Some(i.lang())
} else {
None
}
})
.unwrap_or(Lang::Eng) .unwrap_or(Lang::Eng)
.name(); .name();
Ok(list.iter().any(|s| lang.starts_with(s))) Ok(list.iter().any(|s| lang.starts_with(s)))
}, }
}, },
} }
} }