John Townsend: Quantum Mechanics texts

Last night we spoke with John Townsend, a professor and author at Harvey Mudd College. He’s the author of two undergraduate texts on quantum mechanics (one for sophomores, and one for juniors/seniors) and he talked with us about their philosophies, organization, and use.

Here’s the recording.

Next week we’ll be talking about exciting things people saw at AAPT.

We’re looking for coaching volunteers for the fall. We do coaching once a month (the last Wednesday of the month) and we’d like to do one high school and one college teacher per month. Email Andy (andy.rundquist@gmail.com) if you have questions or want to volunteer.

Ted Hodapp and the PhysTEC Teacher Education Coalition

Last night we had a discussion with Ted Hodapp, the Director of Education and Diversity for the American Physical Society, about the state of high school physics teaching and teacher training in the US.

link to recording of discussion with Ted Hodapp

Links:

Laravel tutorial

Here’s a tutorial created by documenting how I added the ability for users to add a “solution” to a problem. While adding the code to make this happen, I paused and put in the relevant details into the blog post. I also recorded (with lots of pauses) a screencast while I was working so you can watch that in addition to reading this post.

Ok, first, what’s the file structure of our Laravel-based project? Here’s a screencast of how the githup repository looks on my computer (and, thanks to the way github works, how it looks on the server, too).

For what I want to do, I’m going to make a new view that’ll have all the form elements needed for people to add a solution, and I’ll add a new controller that will have all the php needed to make sure the form info goes where it’s supposed to in the database. I won’t have to make substantial changes to the models folder, unless I make a simple getter method or something.

First, the controller. I’ll make a copy of the problems

<?php

class Solutions_Controller extends Base_Controller
{
    public $restful=true;
   
    public function __construct()
    {
        $this->filter('before', 'auth');
    }
   
    public function get_index()
    {
        echo "this is the index page of solutions";
    }
}

Here I’ve just put in the very basics you need to get a controller working. The name needs to be a capitalized and pluralized version of the name of the php file (that’s stored in the controllers folder). The restful stuff allows us to separately deal with “get” requests (basic views of a web page) and “post” requests (after someone hits “submit” on a form). The construct method ensures that all pages made in this file can only be viewed by a logged-in user. The “get_index” function includes whatever you want shown at “public/solutions”.

What we really want is a page that displays a problem (with attachments) and gives a text box where people can enter a solution, along with uploads for their own attachments. So we need a “view” that gets us that:

@layout('templates.main')

@section('content')

<div>


    <h1>
        {{$prob->title}}
    </h1>
    <div>
        {{$prob->fixmathjax}}
       
    </div>
    <div>
    Attachments:
                @foreach ($prob->attachments AS $attachment)
                   
                    <!-- <img src="{{$attachment->link}}" alt="" width="" height="" border="0" /><br /> -->
                    <div>{{$attachment->imgsrc}}<div>{{$attachment->pivot->description}}</div></div>    



                @endforeach
    </div>
    <div>
    {{Form::open_for_files('problems/new', "POST", array("class" => "form-horizontal"))}}

<fieldset>
    <legend>Add a solution to this problem</legend>

    <div class="control-group">
        {{Form::label('content', "Solution Text", array("class" => "control-label"))}}
        <div class="controls">
            {{Form::textarea('content',Input::old('content'), array("class" => "input-xlarge"))}}
        </div>
    </div>


    <hr />


    <div class="control-group">
        {{Form::label('attachement', "Add attachments", array("class" => "control-label"))}}
        <div class="controls attachment-block">
            {{Form::file('attachment1')}}<br />
            Caption: {{Form::text('caption1',Input::old('caption1'))}}<br /><p>
            {{Form::file('attachment2')}}<br />
            Caption: {{Form::text('caption2',Input::old('caption2'))}}<br /><p>
            {{Form::file('attachment3')}}<br />
            Caption: {{Form::text('caption3',Input::old('caption3'))}}
        </div>
    </div>
   
    <div class="form-actions">
        {{Form::submit('Submit', array("class" => "btn btn-primary"))}}
    </div>
</fieldset>

{{Form::close()}}
</div>

@endsection

We just have to add this to the solutions controller file to see this form at “public/solutions/add/2″ (the number at the end is the problem id we’re looking at);

public function get_add($prob_id)
    {
        $prob=Problem::find($prob_id);
        return View::make('pages.addsolution')
            ->with('prob', $prob);
    }

Here’s the screencast of everything so far:

Ok, now we need to put the info in the right places once someone hits submit. We do that with a post_add function added in the controller. One of the first things we need is a function that helps with the uploading. We’ll use the same one we used for uploading attachments to problems:

public function upload_attachment2($fname, $text, $sol, $userid)
    {
        if (array_get(Input::file($fname), 'tmp_name'))
        {
            $type=File::extension(array_get(Input::File($fname),'name'));
            $file1=Attachment::create(array('user_id'=>$userid,'type'=>$type));
            $sol->attachments()->attach($file1->id,array('description'=>$text,'user_id'=>$userid));
            $name=md5("XXXX".$file1->id);
            $name="$name.$type";
            $attachment1=Input::upload($fname,path('storage').'attachments/',$name);
        }
    }

This function grabs the file extention (like “png” or “jpg” etc), creates a new entry in the attachment table, attaches that attachment to the current solution, and then uploads the file and saves it in the storage location with a file name that’s salted and hashed with the attachment id.

Note that to put in the extra description and user_id in the pivot table, you have to make a slight adjustment to the solution model:

public function attachments()
    {
        return $this->has_many_and_belongs_to('Attachment')->with(array('user_id', 'description'));
    }

To put the solution into the database correctly, we use this code:

public function post_add($prob_id)
    {
        $input = Input::all();
        $rules = array(
            'content' => 'required',
            'attachment1' => 'image',
            'attachment2' => 'image',
            'attachment3' => 'image',
        ); 
       
        $validation = Validator::make($input, $rules);
        if ($validation->fails())
        {
            //this redirect needs to be fixed
            return Redirect::to('/')->with_input()->with_errors($validation);
        }
        else
        {  
           
            $content = Input::get('content');
            $userid=Auth::user()->id;
            $sol = new Solution(array(
                'content' => $content,
                'problem_id' => $prob_id));
            $user=User::find($userid);
            $sol=$user->solutions()->insert($sol);
                       
            //handle attachments
           
            $this->upload_attachment2('attachment1', Input::get('caption1'), $sol, $userid);
            $this->upload_attachment2('attachment2', Input::get('caption2'), $sol, $userid);
            $this->upload_attachment2('attachment3', Input::get('caption3'), $sol, $userid);
           
   
           
            return Redirect::to("solutions/add/$prob_id")->with_input()->with('submitworked', true);

            };
    }

This first grabs all the form input. Then it does some validation (making sure that the “content” field has something in it, and making sure that all the attachments are images. If the validation fails, it’s supposed to redirect you to the form with some error messages, but right now it’s taking you to the wrong page (note my comment).

After the validation, it grabs the content field, figures out the user model, makes a new solution model with the appropriate values, and inserts the model through the user model to ensure that that connection is solid in the database. After that, the 3 attachments are dealt with.

Here’s a screencast describing the upload code:

Finally (at least for this tutorial :) I wanted to make sure that any time you were looking at a problem, you could see a link that would allow you to add a solution. I did that by making a “getter” method in the problem model:

public function get_addsollink()
    {
        $id=$this->get_attribute('id');
        //return HTML::link('problems/view/'.$id, $title);
        // the line above works, but I think the below is what
        // Laravel likes better.
        return HTML::link_to_action('solutions@add', 'add solution', array($id));
    }

What this does is grabs the id, and makes the appropriate link anywhere you have a problem model. So, for example, in the “viewsingle” blade, I added {{$prob->addsollink}} right were I wanted the link to be.

I hope this tutorial is helpful. It was probably too ambitious, but it did cover all kinds of things we have to do in laravel all the time. Let me know in the comments how it could be improved! -Andy

Eugenia Etkina: Rutgers teacher preparation

We talked with Eugenia about her program for preparing physics teachers. She talked about four courses that she teachers that focus on content, pedagogy, and curriculum preparation.

We also continued our discussion of the Physics Problem Database (now at version 0.2!)

Here’s the recording.

Next week we’ll talk with Ted Hodapp from the APS, continuing our conversations about teacher preparation.