Posts Tagged Running

Authentication With Devise Using Username – Configuration

Devise is probably the most popular authentication gem for Rails apps but, in the current version (1.1.5), doesn’t fully support logging in with a username and password. This Railscast walks through how to add a username to the model and use username as the key to log in with but 1.1.5 will still require email as the key to unlock an account, reset a password or resend confirmation instructions.

Version 1.2rc adds the ability to use username as a key for unlocking and resetting and I have submitted a patch to use username as a key when resending confirmations which will hopefully make it into a 1.2.x release. I have included my fork in the Gemfile below and will re-edit this post as future versions of devise are released.

My patch has now been included in 1.2rc so use the https://github.com/plataformatec/devise.git url in your gemfile.

I’ll keep this terse and include my workflow

  1. Create a new Rails app.
  2. git flow feature start authentication
  3. Amend Gemfile:

    I have included hpricot and ruby_parser gems as they are required by devise for haml views. Note that the devise gem is pointing to my fork. I’ll amend this as soon as the patch gets included.
  4. bundle install
  5. rails g devise:install
  6. Make the three changes specified by generator:
    1. Set the action_mailer host in development.rb, test.rb, and production.rb.

      (The production host should obviously point to your production host.)
    2. Uncomment and amend the root route in routes.rb.

      This is also a good time to delete public/index.html.
    3. Add flash messages to the application layout. I prefer haml so I delete application.html.erb and add the following application.html.haml.
  7. This is a good time to commit with git add -A and git commit -m "Installed devise."
  8. Amend devise.rb.
  9. rails g devise user
  10. Amend user.rb.

    Note I can’t use the validatable module as that would require emails to be unique so I will have to write my own validation later.
  11. Amend ####_devise_create_users.rb.

    The most important points are to add the user column and index and remove unique from the email index.
  12. rake db:migrate
  13. rake db:test:clone
  14. Generate the devise views so we can amend them. rails g devise:views -e:haml (skip the -e:haml to generate erb views.) I will drive the view changes with tests later.
  15. Another good point to commit and take a break. git add -A and git commit -m "Configured devise"

 

Changing the views is just a matter of replacing :email with :username but I will do that with some cucumber tests in a future post.

, , , , , , , , , , , , , , , , , , , , , , , , , ,

No Comments

BDD with SpecFlow, NUnit and MVC3–More View a List Of Products

Following on from this post where it looked like BDD was a spectacularly inefficient way to drive out code, I’ll add a new feature to the scenario:

Scenario: Display 10 products
    Given There are 10 products
    When the product controller is told to display the default view
    Then the view should contain a list of 10 products

Compiling and running the tests provides templates for the Given and the Then methods, we get to reuse the existing When method. This reuse is one of the big daws for BDD for me (plus the readability).

To write the method GivenThereAre10Products I need to tell the controller there are ten products. The simplest thing to do is to pass 10 as an argument to the controller constructor then write a loop to populate the product list. I need to move the controller out of WhenTheProductControllerIsToldToDisplayTheDefaultView and declare it as a class field, then re new it in GivenThereAre10Products:

private ProductController controller = new ProductController(0);

[Given(@"There are 10 products")]
public void GivenThereAre10Products() {
    controller = new ProductController(10);
}

[When(@"the product controller is told to display the default view")]
public void WhenTheProductControllerIsToldToDisplayTheDefaultView() {
    _result = controller.Index();
}

[Then(@"the view should contain a list of 10 products")]
public void ThenTheViewShouldContainAListOf10Products() {
    var products = (List<Product>) ViewResult.ViewData.Model;
    products.Count.ShouldEqual(10);
}

I can then write the code to make these tests compile then pass, the relevant changes to the controller are:

private readonly int _productsCount;

public ProductController(int productsCount) {
    _productsCount = productsCount;
}

public ActionResult Index() {
    ViewData["Title"] = "Products";
    var products = new List<Product>();
    var product = new Product();
    for (int i = 0; i < _productsCount; i++) {
        products.Add(product);
    }
    return View(products);
}

This makes the tests pass but needs refactoring. As is fairly standard practise I will refactor to pass a repository into the controller and the repository will be passed a context which will, in this instance fake the database connection. I will detail the repository and fake context in a separate post, but I include a method on the fake repository to add a number of an entity to help testing.

I need to refactor the specs to create a controller with a repository and the relevant refactored code is:

private ProductController _controller;
private ActionResult _result;

public ViewAListOfProducts() {
    CreateController(0);
}

private void CreateController(int productCount) {
    var context = new FakeRavenContext();
    context.AddProducts(productCount);
    _controller = new ProductController(new ProductRepository(context));
}

[Given(@"There are 10 products")]
public void GivenThereAre10Products() {
    CreateController(10);
}

And the refactored code from the controller:

private readonly IProductRepository _repository;

public ProductController(IProductRepository repository) {
    _repository = repository;
}

public ActionResult Index() {
    ViewData["Title"] = "Products";
    return View(_repository.All());
}

The final thing I want to do here is to add a scenario for 0 products:

Scenario: Display 0 products

    Given There are 0 products

    When the product controller is told to display the default view

    Then the view should contain a list of 0 products

This is where SpecFlow begins to shine, I just need to parameterise 2 of the methods to implement this:

[Given(@"There are 10 products")]
public void GivenThereAre10Products() {
    CreateController(10);
}

[Then(@"the view should contain a list of 10 products")]
public void ThenTheViewShouldContainAListOf10Products() {
    var products = (List<Product>) ViewResult.ViewData.Model;
    products.Count.ShouldEqual(10);
}

Becomes:

[Given(@"There are (.*) products")]
public void GivenThereAreXProducts(int productCount) {
    CreateController(productCount);
}

[Then(@"the view should contain a list of (.*) products")]
public void ThenTheViewShouldContainAListOfXProducts(int productCount) {
    var products = (List<Product>) ViewResult.ViewData.Model;
    products.Count.ShouldEqual(productCount);
}

I still need to implement paging for this scenario then create the view details, add, edit, and delete product scenarios which should drive the design of the product class but I think the BDD side will be pretty much more of the same.

I expect coding with BDD will be at least as fast as TDD but I suspect I will still write some unit tests to complement the BDD specs.

, , , , , , , , , , , ,

7 Comments

Azure Development Fabric and Visual Studio 2010

Just installed Visual Studio 2010. The first thing I tried was creating an new Cloud project.

image

The whole process was surprisingly painless. After creating the solution, I was prompted to download and install the Azure tools. Once they were installed, I deleted and recreated the solution and was prompted for which Roles I wanted:

image

After creating the solution just hit F5 to see the project running in the Azure Development Fabric.

image

The debugger is already connected and all works just as you would expect.

, , , , , ,

No Comments