Slide 1

Slide 1 text

django v rails Stephen McCullough

Slide 2

Slide 2 text

who am i • Stephen McCullough • @swmcc on the interwebs • Senior Software Engineer @ ShopKeep • We are hiring - python/ruby - talk to me after

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Translation • models • template • views • URL • models • views • controllers • routes django rails

Slide 5

Slide 5 text

Tools • pypi • pip • pdb • virtualenv • rubygems • bundler • debugger • rvm/rbenv django rails

Slide 6

Slide 6 text

Comparison • generic templates • models • admin interface • authentication • south • scaffolding • active record • active admin • devise • migrations django rails

Slide 7

Slide 7 text

models To create a model in rails you run a command rails generate model SomeModel 
 somerow:string class SomeModel < ActiveRecord::Base
 
 end create_table “some_model”, force => true do |t| t.string “somerow” end

Slide 8

Slide 8 text

models To create a model in django you run a command class SomeModel(models.Model):
 somerow = models.CharField() created_at = models.DateTimeField(auto_now_add=True) upcated_at = models.DateTimeField(auto_now=True)

Slide 9

Slide 9 text

migrations To create a migration in rails you run a command rails generate migration AddAnotherThingToSomeModel something_else:string

Slide 10

Slide 10 text

migrations To create a migration in django you edit model.py class SomeModel(models.Model):
 somerow = models.CharField() something_else = models.CharField() created_at = models.DateTimeField(auto_now_add=True) upcated_at = models.DateTimeField(auto_now=True) end python manage.py schemamigration somemodel —auto python manage.py migrate somemodel

Slide 11

Slide 11 text

queries In rails you can be quite expressive with your queries. Client.where(created_at: (Time.now.midnight - 1.day)..Time.now.midnight) Model.where('field >= ?', value) Model.objects.filter(field__gt=value)

Slide 12

Slide 12 text

controllers In rails the controllers look nice. class OrdersController < ApplicationController def index @orders = Order.where(active: true) end def show @order = Order.find(params[:id]) end def new @order = Order.new end def create @order = Order.new(params[:order]) if @order.save redirect_to @order else render 'new' end end end

Slide 13

Slide 13 text

controllers In django the controllers don’t look so nice. # django usually calls the 'show' method 'detail' # the product_id parameter comes from the routing def detail(request, product_id): p = Product.objects.get(pk=product_id) # pk = primary key # renders detail.html with the third parameter passed as context return render(request, 'products/detail.html', {'product': p}) def create(request): # check if form was submitted if request.method == 'POST': # similar to RoR' 'create' action form = ProductForm(request.POST) # A form bound to the POST data if form.is_valid(): # All validation rules pass new_product = form.save() return HttpResponseRedirect(new_product.get_absolute_url()) else: # similar to RoR' 'new' action form = ProductForm() # An empty form return render(request, 'products/create.html', { 'form': form })

Slide 14

Slide 14 text

controllers In django controllers don’t look so nice. # Supposes the routing passed in a parameter called 'pk' # containing the object id and uses it for fetching the object. # Automatically renders the view /products/product_detail.html # and passes product as a context variable to the view. class ProductDetail(DetailView): model = Product # Generates a form for the given model. If data is POSTed, # automatically validates the form and creates the resource. # Automatically renders the view /products/product_create.html # and passes the form as a context variable to the view. class ProductCreate(CreateView): model = Product

Slide 15

Slide 15 text

views Forms <%= form_tag("/contact", method: "post") do %> <%= label_tag(:subject, "Subject:") %> <%= text_field_tag(:subject) %> <%= label_tag(:message, "Message:") %> <%= text_field_tag(:message) %> <%= label_tag(:subject, "Sender:") %> <%= text_field_tag(:sender) %> <%= label_tag(:subject, "CC myself:") %> <%= check_box_tag(:sender) %> <%= submit_tag("Search") %> <% end %>

Slide 16

Slide 16 text

views Forms class ContactForm(forms.Form): subject = forms.CharField(max_length=100) message = forms.CharField() sender = forms.EmailField() cc_myself = forms.BooleanField(required=False) def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): return HttpResponseRedirect('/thanks/') # Redirect after POST else: form = ContactForm() # An unbound form return render(request, 'contact.html', { 'form': form }

Slide 17

Slide 17 text

views Forms class ContactForm(forms.Form): subject = forms.CharField(max_length=100) message = forms.CharField() sender = forms.EmailField() cc_myself = forms.BooleanField(required=False) def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): return HttpResponseRedirect('/thanks/') # Redirect after POST else: form = ContactForm() # An unbound form return render(request, 'contact.html', { 'form': form }

Slide 18

Slide 18 text

views Forms {{ form.as_p }}

Slide 19

Slide 19 text

routing # automatically maps GET /products/:id to products#show # GET /products to products#index # POST /products to products#create # DELETE /products/:id to products#destroy # etc. resources :products urlpatterns = patterns('', # matches the detail method in the products controller url(r'^products/(?P\d+)/$', products.views.DetailView.as_view(), name='detail'), # matches the index method, you get the gist url(r'^products/$', products.views.IndexView.as_view(), name='index'), url(r'^products/create/$', products.views.CreateView.as_view(), name='create'), url(r'^products/(?P\d+)/delete/$', products.views.DeleteView.as_view(), name='delete'), )

Slide 20

Slide 20 text

testing class UsersControllerTest < ActionController::TestCase test "should get index" do get :index # GET request to the index action assert_response :success # request returned 200 # assigns is a hash containing all instance variables assert_not_nil assigns(:users) end end class UsersTest(unittest.TestCase): def setUp(self): self.client = Client() def test_index(self): """ should get index """ response = self.client.get(reverse('users:index')) self.assertEqual(response.status_code, 200) self.assertIsNotNone(response.context['users'])

Slide 21

Slide 21 text

Conclusion • Both are outstanding frameworks • You can’t go wrong my picking either one. • I prefer django, marginally • It's not hard to switch from one to another