Skip to content

Instantly share code, notes, and snippets.

@chrisortman
Created April 2, 2014 11:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisortman/9932595 to your computer and use it in GitHub Desktop.
Save chrisortman/9932595 to your computer and use it in GitHub Desktop.
rails new nebcc14 -m https://raw.github.com/RailsApps/rails-composer/master/composer.rb

This will give me a little wizard where I can choose some default options. For simplicitly I'm going to omit some things like devise (used for user authentication)

In this example I will choose the first option for everything except

  • Build a starter application - 3 I want to build my own
  • Unit Testing? - 2 RSpec
  • Fixture replacement? - 2 - Factory Girl
  • set a robots.txt ? - Doesn't matter - y
  • Create a Github repository - n - I usually do this on my own
  • Reduce assets logger noise - sounds good - y
  • Improve error reporting - why not - y
  • Use or create a project-specific rvm gemset - only if you are using rvm, i use rbenv - n

I have some libraries and settings that I always want to make so I capture those in what is called a template and I can run it

rake rails:template LOCATION=../template.rb

Let's make sure that everything is working

rails server

Able to see default rails page, know it is working

rails g scaffold tournament name:string date:date
rake db:migrate

Now I can goto /tournaments and add/edit/update/delete

Ugh, it let me create a tournament without a name.

Let's fix that. First I need to add a test.

it { should validate_presence_of :name }

And then make it pass

validates :name, presence: true

Now I can run my site again and create some tournaments

rails g scaffold division name:string tournament_id:integer
rails g scaffold team name:string coach:string phone:string email:string tournament_id:integer
rake db:migrate  

Now I can make teams and divisions too, but they should be part of a tournament so let's put a dropdown list on our form

vim app/views/divisions/_form.html.erb
<%= f.collection_select, :tournament_id, Tournament.all, :id, :name,{},{:class => "form-control"} %>

and do the same for teams

Now I want to show the divisions and teams on the page for the tournament, need to add a has_many to tournaments for divisions and teams then add html to render the list

Let's add a couple of quick tests to tournament

it { should have_many :teams}
it { should have_many :divisions}

And run the tests to see them fail, now make them pass.

#dournament.rb
has_many :teams, inverse_of: :tournament
has_many :divisions, inverse_of :tournament
#division.rb
belongs_to :tournament, inverse_of: :division
#team.rb
belongs_to :tournament, inverse_of: :teams

Now that I have relation ships I can use them on my tournaments page

vim app/views/tournaments/show.html.erb

Need to put h2 headers and loop through divisions then teams. Divisions gets a link to add a team, team gets a link to edit the team

Now is a good time to fix it so that if i edit the team or division and save it I want it to take me back to the tournaments page

redirect_to @team.tournament

And now I want to be able to put my teams into divisions this is call HABTM (has and belongs to many)

To do this I first need to create the table for that I"ll use a migration

rails g migration AddDivisionsTeamsTable
	
class AddDivisionsTeamsTable < ActiveRecord::Migration
  def change
        create_table :divisions_teams do |t|
          t.belongs_to :division
          t.belongs_to :team
        end
     end
  end


rake db:migrate

Table name is derived by alphabetical order of class names

Want to make the add team link work, need to make it so on new team page I can pick divisions too

<%= link_to 'add team', new_team_path %>
<%= link_to 'edit', [:edit, @team] %>

Have to remember to update the params to accept ids

{:division_ids => []}

Can make some of the display nicer

1 team or 2 teams

pluralize(@division.teams,'team')

and 3rd grade boys, 4th grade boys, and 5th grade boys

@team.divisions.map(&:name).to_sentence

Can make it a lot nicer to work with by redirecting to the tournament page after saving division and team

belongs_to :tournament
redirect_to @team.tournament

Resources

Nested forms and mtm

collection select

Prag studio rails intro

# GEMS
#
gem "bcrypt-ruby"
gem 'bootstrap-generators', '~> 3.1.1'
gem_group :development do
gem "spring"
end
gem_group :test do
gem "shoulda-matchers"
end
run "bundle install"
generate("bootstrap:install","-f")
run "bundle exec spring binstub --all"
git :init
git add: "."
git commit: %Q{ -m 'Adding bootstrap and spring' }
# hook up factory_girl methods
#
inject_into_file 'spec/spec_helper.rb', "\nconfig.include(FactoryGirl::Syntax::Methods)", :after => 'config.include(EmailSpec::Matchers)'
## rspec scaffold
file 'lib/templates/rspec/scaffold/controller_spec.rb', <<-CODE
require 'spec_helper'
# This spec was generated by rspec-rails when you ran the scaffold generator.
# It demonstrates how one might use RSpec to specify the controller code that
# was generated by Rails when you ran the scaffold generator.
#
# It assumes that the implementation code is generated by the rails scaffold
# generator. If you are using any extension libraries to generate different
# controller code, this generated spec may or may not pass.
#
# It only uses APIs available in rails and/or rspec-rails. There are a number
# of tools you can use to make these specs even more expressive, but we're
# sticking to rails and rspec-rails APIs to keep things simple and stable.
#
# Compared to earlier versions of this generator, there is very limited use of
# stubs and message expectations in this spec. Stubs are only used when there
# is no simpler way to get a handle on the object needed for the example.
# Message expectations are only used when there is no simpler way to specify
# that an instance is receiving a specific message.
<% module_namespacing do -%>
describe <%= controller_class_name %>Controller do
# This should return the minimal set of attributes required to create a valid
# <%= class_name %>. As you add validations to <%= class_name %>, be sure to
# adjust the attributes here as well.
let(:valid_attributes) { <%= formatted_hash(example_valid_attributes) %> }
# This should return the minimal set of values that should be in the session
# in order to pass any filters (e.g. authentication) defined in
# <%= controller_class_name %>Controller. Be sure to keep this updated too.
let(:valid_session) { {} }
# Use a factory to create a default instance of your model
let(:<%= file_name %>) { create(:<%= file_name %>) }
let(:id_params) do
{:id => <%= file_name %>.to_param }
end
before{ action.call }
<% unless options[:singleton] -%>
describe "GET index" do
let(:action) do
-> { get :index, id_params , valid_session }
end
it { expect(assigns(:<%= table_name %>)).to eq([<%= file_name %>]) }
it { should render_template(:index) }
end
<% end -%>
describe "GET show" do
let(:action) do
-> {get :show, id_params, valid_session }
end
it { expect(assigns(:<%= ns_file_name %>)).to eq(<%= file_name %>) }
it { should render_template(:show) }
end
describe "GET new" do
let(:action) do
-> { get :new, {}, valid_session }
end
it { expect(assigns(:<%= ns_file_name %>)).to be_a_new(<%= class_name %>) }
it { should render_template(:new) }
end
describe "GET edit" do
let(:action) do
-> { get :edit, id_params, valid_session }
end
it { expect(assigns(:<%= ns_file_name %>)).to eq(<%= file_name %>) }
it { should render_template(:edit) }
end
describe "POST create" do
describe "with valid params" do
let(:action) do
-> { post :create, {:<%= ns_file_name %> => valid_attributes }, valid_session }
end
it { expect(assigns(:<%= ns_file_name %>)).to be_a(<%= class_name %>) }
it { expect(assigns(:<%= ns_file_name %>)).to be_persisted }
it { should redirect_to(<%= class_name %>.last) }
end
describe "with invalid params" do
let(:action) do
-> {
allow_any_instance_of(<%= class_name %>).to receive(:save).and_return(false)
post :create, {:<%= ns_file_name %> => <%= formatted_hash(example_invalid_attributes) %> }, valid_session
}
end
it { expect(assigns(:<%= ns_file_name %>)).to be_a_new(<%= class_name %>) }
it { should render_template('new') }
end
end
describe "PUT update" do
describe "with valid params" do
let(:action) do
-> {
# Assuming there are no other <%= table_name %> in the database, this
# specifies that the <%= class_name %> created on the previous line
# receives the :update_attributes message with whatever params are
# submitted in the request.
expect_any_instance_of(<%= class_name %>).to receive(:update).with(<%= formatted_hash(example_params_for_update) %>).and_return(true)
put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => <%= formatted_hash(example_params_for_update) %>}, valid_session
}
end
it { expect(assigns(:<%= ns_file_name %>)).to eq(<%= file_name %>) }
it { should redirect_to(<%= file_name %>)}
end
describe "with invalid params" do
let(:action) do
-> {
# Trigger the behavior that occurs when invalid params are submitted
allow_any_instance_of(<%= class_name %>).to receive(:save).and_return(false)
put :update, {:id => <%= file_name %>.to_param, :<%= ns_file_name %> => <%= formatted_hash(example_invalid_attributes) %>}, valid_session
}
end
it { expect(assigns(:<%= ns_file_name %>)).to eq(<%= file_name %>) }
it { should render_template('edit') }
end
end
describe "DELETE destroy" do
let(:action) do
-> { delete :destroy, id_params, valid_session }
end
it { expect(assigns(:<%= ns_file_name %>)).to be_destroyed }
it { should redirect_to(<%= index_helper %>_url) }
end
end
<% end -%>
CODE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment