Skip to content

Commit 8038777

Browse files
committed
Switch to using toml for categories instead of plain text
1 parent ba1ec8c commit 8038777

File tree

6 files changed

+118
-18
lines changed

6 files changed

+118
-18
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ env_logger = "0.3"
3535
rustc-serialize = "0.3"
3636
license-exprs = "^1.3"
3737
dotenv = "0.8.0"
38+
toml = "0.2"
3839

3940
conduit = "0.8"
4041
conduit-conditional-get = "0.8"

src/categories.rs

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,96 @@
1-
// Sync available crate categories from `src/categories.txt`.
1+
// Sync available crate categories from `src/categories.toml`.
22
// Runs when the server is started.
33

4+
use toml;
45
use pg;
56
use env;
6-
use util::errors::CargoResult;
7+
use util::errors::{CargoResult, ChainError, internal};
8+
9+
struct Category {
10+
name: String,
11+
slug: String,
12+
}
13+
14+
impl Category {
15+
fn concat(&self, child: &Category) -> Category {
16+
Category {
17+
name: format!("{}::{}", self.name, child.name),
18+
slug: format!("{}::{}", self.slug, child.slug),
19+
}
20+
}
21+
}
22+
23+
fn concat_parent_and_child(parent: Option<&Category>, child: Category)
24+
-> Category {
25+
parent.map(|p| p.concat(&child)).unwrap_or(child)
26+
}
27+
28+
fn required_string_from_toml(toml: &toml::Table, key: &str)
29+
-> CargoResult<String> {
30+
toml.get(key)
31+
.and_then(toml::Value::as_str)
32+
.map(str::to_string)
33+
.chain_error(|| {
34+
internal("Expected Category toml attribute to be a String")
35+
})
36+
}
37+
38+
fn category_from_toml(toml: &toml::Value, parent: Option<&Category>)
39+
-> CargoResult<Vec<Category>> {
40+
let toml = toml.as_table().chain_error(|| {
41+
internal("Category isn't a toml Table")
42+
})?;
43+
44+
let category = Category {
45+
slug: required_string_from_toml(&toml, "slug")?,
46+
name: required_string_from_toml(&toml, "name")?,
47+
};
48+
49+
let category = concat_parent_and_child(parent, category);
50+
51+
let mut children: Vec<_> = toml.get("categories")
52+
.and_then(toml::Value::as_slice)
53+
.map(|children| {
54+
children.iter()
55+
.flat_map(|ref child| {
56+
category_from_toml(child, Some(&category))
57+
.expect("Could not create child from toml")
58+
}).collect()
59+
}).unwrap_or(Vec::new());
60+
61+
children.push(category);
62+
63+
Ok(children)
64+
}
765

866
pub fn sync() -> CargoResult<()> {
967
let conn = pg::Connection::connect(&env("DATABASE_URL")[..],
1068
pg::TlsMode::None).unwrap();
1169
let tx = conn.transaction().unwrap();
1270

13-
let categories = include_str!("./categories.txt");
71+
let categories = include_str!("./categories.toml");
72+
let toml = toml::Parser::new(categories).parse().expect(
73+
"Could not parse categories.toml"
74+
);
75+
76+
let categories = toml.get("categories")
77+
.expect("No categories key found")
78+
.as_slice()
79+
.expect("Categories isn't a toml::Array");
1480

15-
let slug_categories: Vec<_> = categories.lines().map(|c| {
16-
let mut parts = c.splitn(2, ' ');
17-
let slug = parts.next().expect("No slug found!");
18-
let name = parts.next().expect("No display name found!");
19-
(slug, name)
20-
}).collect();
81+
let categories: Vec<_> = categories
82+
.iter()
83+
.flat_map(|c| {
84+
category_from_toml(c, None)
85+
.expect("Categories from toml failed")
86+
}).collect();
2187

22-
let insert = slug_categories.iter().map(|&(ref slug, ref name)| {
23-
format!("(LOWER('{}'), '{}')", slug, name)
88+
let insert = categories.iter().map(|ref category| {
89+
format!("(LOWER('{}'), '{}')", category.slug, category.name)
2490
}).collect::<Vec<_>>().join(",");
2591

26-
let in_clause = slug_categories.iter().map(|&(slug, _)| {
27-
format!("LOWER('{}')", slug)
92+
let in_clause = categories.iter().map(|ref category| {
93+
format!("LOWER('{}')", category.slug)
2894
}).collect::<Vec<_>>().join(",");
2995

3096
try!(tx.batch_execute(

src/categories.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[[categories]]
2+
slug = "development-tools"
3+
name = "Development Tools"
4+
5+
[[categories.categories]]
6+
slug = "testing"
7+
name = "Testing"
8+
9+
[[categories.categories.categories]]
10+
slug = "mocking"
11+
name = "Mocking"
12+
13+
[[categories]]
14+
slug = "libraries"
15+
name = "Libraries"
16+
17+
[[categories.categories]]
18+
slug = "async"
19+
name = "Async"
20+
21+
[[categories.categories]]
22+
slug = "date-and-time"
23+
name = "Date and Time"
24+
25+
[[categories]]
26+
slug = "games"
27+
name = "Games"

src/categories.txt

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extern crate s3;
2121
extern crate semver;
2222
extern crate time;
2323
extern crate url;
24+
extern crate toml;
2425

2526
extern crate conduit;
2627
extern crate conduit_conditional_get;

0 commit comments

Comments
 (0)