3

I use nickel.rs:

router.get("/api/movies", middleware! { |request, response|
    let mut test_movies =
    r#"[
        { "title": "Ironman"},
        { "title": "The Walk"},
        { "title": "Paddington"}
    ]
    "#;
    let json = Json::from_str(test_movies);
    format!("{}", json.unwrap())
});

I wanted to create JSON format. The code for connecting to PostgreSQL and converting to JSON definition is below:

extern crate rustc_serialize;
use rustc_serialize::json::{Json, Parser};

#[derive(RustcDecodable, RustcEncodable)]
struct Movie {
    title: String,
}

And I tried to select query and create JSON

router.get("/api/movies", middleware! { |request, response|
    let conn = Connection::connect("postgres://postgres@localhost", SslMode::None).unwrap();
    let stmt = match conn.prepare("select title from movie") {
        Ok(stmt) => stmt,
        Err(e) => {
            return response.send(format!("Preparing query failed: {}", e));
        }
    };
    let res = match stmt.execute(&[]) {
        Ok(v) => println!("Selecting movie was Success."),
        Err(e) => println!("Selecting movie failed. => {:?}", e)
    };

    // ???
    // let movies = Json::from_obj(res);
    // let movies = request.json_as::<&[Movie]>().unwrap();
    // let movies = request.json_as::Vec<Movie>().unwrap();
    format!("{}", movies)
});

however, I have no idea how to convert the result to JSON.

let conn = conn.clone();

makes the errors.

error: no method named `clone` found for type `postgres::Connection` in the current scope

I added

use nickel::status::StatusCode;

//use rustc_serialize::json::{Json, Parser};
use rustc_serialize::{json};

json::encode(&movies).unwrap();

was work. but null returned...

Finally

I changed execute to query and also use Vec<Movie>.

let mut v: Vec<Movie> = vec![];
let movies = &conn.query("select title from movie", &[]).unwrap();
for row in movies {
    let movie = Movie {
        title: row.get(0),
    };

    v.push(movie);
}

let json_obj = json::encode(&v).unwrap();
response.set(MediaType::Json);
response.set(StatusCode::Ok);
return response.send(json_obj);

I also defined struct Moview like model

struct Movie {
    // id: i32,
    title: String,
}

hmm.. troublesome a lot.

however, I can't conn.clone() yet.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
shinriyo
  • 344
  • 3
  • 17

1 Answers1

1

Try the following:

    let json = json::encode(&res).unwrap();
    response.set(MediaType::Json);
    response.set(StatusCode::Ok);
    return response.send(json);

Also, it's not efficient to create a new connection for each request. You can create one connection in the main() function and then clone it inside each request closure.

fn main(){

    let mut server = Nickel::new();
    let mut router = Nickel::router();

    let conn = Connection::connect("postgres://postgres@localhost", SslMode::None).unwrap();
    let shared_connection = Arc::new(conn);


    {
        let conn = shared_connection.clone();
        router.get("/api/movies", middleware! ( |request, mut response|{

            let mut v: Vec<Movie> = vec![];
            let movies = &conn.query("select title", &[]).unwrap();
            for row in movies {
                let movie = Movie {
                    title: row.get(0),
                };

                v.push(movie);
            }

            let json_obj = json::encode(&v).unwrap();
            res.set(MediaType::Json);
            res.set(StatusCode::Ok);
            return res.send(json_obj);

        }));
    }

    {
        let conn = shared_connection.clone();
        router.post("/api/movies",middleware!(|request, mut response|{

            //...

        }));
    }

    server.utilize(router);
    server.listen("127.0.0.1:6767");
}
W.K.S
  • 9,787
  • 15
  • 75
  • 122
  • 1
    Thank you for replying. Yes. I think it is bad to make new connection for each request. I tried let conn = conn.clone(); error: no method named `clone` found for type `postgres::Connection` in the current scope error happned. I added use nickel::status::StatusCode; And, I fix use rustc_serialize::json::{Json, Parser}; to use rustc_serialize::{json}; I modify res to movies. Your code was no error. But, null was return. I certainly interted data. Why it happned? – shinriyo Feb 06 '16 at 14:11
  • Selecting movie was Success. log shows. so, I guess SQL is correct. – shinriyo Feb 06 '16 at 14:43
  • Thanks for pointing out the inconsistencies in my answer. I'll update it to match your original code. Are you using the library `sfackler/rust-postgres`? If so, its documentation states that `execute()` returns the number of rows affected while `query()` returns an iterable object. So I suggest you try using `query()`. – W.K.S Feb 06 '16 at 18:50
  • yes. I wrote `postgres = "0.11"` of `[dependencies]` in `Cargo.toml`. And, I wrote `use postgres::{Connection, SslMode};` in my `main.rs`. So, there are a lot of libs? I also wrote `use nickel_postgres::{PostgresMiddleware, PostgresRequestExtensions};`... however it weren't used.. – shinriyo Feb 06 '16 at 19:02
  • Sorry, I forgot to initialize Atomic Reference Counting `Arc` for the connection.You should be able to `clone()` now – W.K.S Feb 06 '16 at 19:08
  • :22:50: 22:66 error: the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell` happened – shinriyo Feb 07 '16 at 03:58
  • I added `use std::sync::{Arc};` must I modify Connection souce code? – shinriyo Feb 07 '16 at 03:59
  • If the `Sync` trait hasn't been implemented for `Connection` then you can either create a new connection with each request otherwise, I think it's best to first raise an issue on the `sfackler/rust-postgres` repository. They will either guide you to their intended way of sharing a connection otherwise you can implement Sync for Connection and send a pull request. – W.K.S Feb 07 '16 at 07:39
  • It is my code now https://github.com/shinriyo/nickel-helloworld.git I'm not similar to Angular js so I can't delete and update movie yet... – shinriyo Feb 07 '16 at 09:18
  • `let shared_connection = Arc::new(Mutex::new(conn));` – shinriyo Feb 07 '16 at 16:40
  • author replied my topic – shinriyo Feb 07 '16 at 16:40
  • no. I fix `let shared_connection = Arc::new(Mutex::::new(conn));` but... not work – shinriyo Feb 07 '16 at 17:27