Skip to content

Instantly share code, notes, and snippets.

@JFickel
Forked from anonymous/error.sh
Last active December 26, 2015 19:29
Show Gist options
  • Save JFickel/7201922 to your computer and use it in GitHub Desktop.
Save JFickel/7201922 to your computer and use it in GitHub Desktop.
[1] pry(main)> f = FactoryGirl.build(:tournament, :with_teams, teams: 20)
(0.3ms) BEGIN
User Exists (0.9ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = 'example1' LIMIT 1
SQL (4.2ms) INSERT INTO "users" ("created_at", "email", "encrypted_password", "first_name", "last_name", "updated_at", "username") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["created_at", Mon, 28 Oct 2013 18:06:58 UTC +00:00], ["email", "[email protected]"], ["encrypted_password", "$2a$04$pQOTHk9MXOUE8ayPjkFzmOg/ZW5j0VjyEPmz0PbTgJJc0qGs5A7Ii"], ["first_name", "Maggie"], ["last_name", "Gerlach"], ["updated_at", Mon, 28 Oct 2013 18:06:58 UTC +00:00], ["username", "example1"]]
PgSearch::Document Load (0.9ms) SELECT "pg_search_documents".* FROM "pg_search_documents" WHERE "pg_search_documents"."searchable_id" = $1 AND "pg_search_documents"."searchable_type" = $2 ORDER BY "pg_search_documents"."id" ASC LIMIT 1 [["searchable_id", 1], ["searchable_type", "User"]]
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
SQL (0.8ms) INSERT INTO "pg_search_documents" ("content", "created_at", "searchable_id", "searchable_type", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["content", "example1 Maggie Gerlach"], ["created_at", Mon, 28 Oct 2013 18:06:58 UTC +00:00], ["searchable_id", 1], ["searchable_type", "User"], ["updated_at", Mon, 28 Oct 2013 18:06:58 UTC +00:00]]
(0.3ms) COMMIT
NoMethodError: undefined method `each' for 20:Fixnum
from /usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:333:in `replace'
(0.4ms) BEGIN
User Exists (0.9ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE "users"."username" = 'example1' LIMIT 1
SQL (3.6ms) INSERT INTO "users" ("created_at", "email", "encrypted_password", "first_name", "last_name", "updated_at", "username") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["created_at", Mon, 28 Oct 2013 18:21:36 UTC +00:00], ["email", "[email protected]"], ["encrypted_password", "$2a$04$EJhRK2MeTRC4.17vikLLGekWU8zsA.aDKMUbC14mJf.UpEzBSkr8i"], ["first_name", "Rodrigo"], ["last_name", "Wintheiser"], ["updated_at", Mon, 28 Oct 2013 18:21:36 UTC +00:00], ["username", "example1"]]
PgSearch::Document Load (0.8ms) SELECT "pg_search_documents".* FROM "pg_search_documents" WHERE "pg_search_documents"."searchable_id" = $1 AND "pg_search_documents"."searchable_type" = $2 ORDER BY "pg_search_documents"."id" ASC LIMIT 1 [["searchable_id", 1], ["searchable_type", "User"]]
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
SQL (0.8ms) INSERT INTO "pg_search_documents" ("content", "created_at", "searchable_id", "searchable_type", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["content", "example1 Rodrigo Wintheiser"], ["created_at", Mon, 28 Oct 2013 18:21:36 UTC +00:00], ["searchable_id", 1], ["searchable_type", "User"], ["updated_at", Mon, 28 Oct 2013 18:21:36 UTC +00:00]]
(0.3ms) COMMIT
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:333:in `replace'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/activerecord-4.0.0/lib/active_record/associations/collection_association.rb:42:in `writer'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/activerecord-4.0.0/lib/active_record/associations/builder/association.rb:78:in `teams='
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/attribute_assigner.rb:16:in `block (2 levels) in object'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/attribute_assigner.rb:15:in `each'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/attribute_assigner.rb:15:in `block in object'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/attribute_assigner.rb:14:in `tap'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/attribute_assigner.rb:14:in `object'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/evaluation.rb:12:in `object'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/strategy/build.rb:9:in `result'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/factory.rb:42:in `run'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/factory_runner.rb:23:in `block in run'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/activesupport-4.0.0/lib/active_support/notifications.rb:161:in `instrument'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/factory_runner.rb:22:in `run'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/factory_girl-4.2.0/lib/factory_girl/strategy_syntax_method_registrar.rb:19:in `block in define_singular_strategy_method'
(pry):2:in `__pry__'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:328:in `eval'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:328:in `evaluate_ruby'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:278:in `re'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:254:in `rep'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:234:in `block (3 levels) in repl'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:232:in `loop'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:232:in `block (2 levels) in repl'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:231:in `catch'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:231:in `block in repl'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:230:in `catch'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_instance.rb:230:in `repl'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.9.12.2/lib/pry/pry_class.rb:170:in `start'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/railties-4.0.0/lib/rails/commands/console.rb:90:in `start'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/railties-4.0.0/lib/rails/commands/console.rb:9:in `start'
/usr/local/rvm/rubies/ruby-2.0.0-p0/lib/ruby/gems/2.0.0/gems/railties-4.0.0/lib/rails/commands.rb:64:in `<top (required)>'
bin/rails:4:in `require'
bin/rails:4:in `<main>'
=> nil
# Read about factories at https://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :tournament do
sequence(:title) {|n| "Tournament#{n}"}
game 'League of Legends'
starts_at 1.minute.since
association :owner, factory: :user
trait :with_teams do
mode 'team'
after :create do |tournament, evaluator|
FactoryGirl.create_list :tournament_membership, evaluator.teams, team: team, tournament: tournament
end
end
trait :with_users do
mode 'individual'
after :create do |tournament, evaluator|
FactoryGirl.create_list :tournament_membership, evaluator.users, user: user, tournament: tournament
end
end
end
end
FactoryGirl.define do
factory :user do
sequence(:username) { |n| "example#{n}"}
first_name Faker::Name.first_name
last_name Faker::Name.last_name
email { "#{username}@example.com" }
password "password"
end
end
class Team < ActiveRecord::Base
has_many :team_memberships
has_many :users, through: :team_memberships
has_many :events
has_many :tournament_memberships
has_many :tournaments, through: :tournament_memberships
has_many :team_showings
has_many :matches, through: :team_showings
has_many :affiliated_tournament_relationships,
foreign_key: :affiliate_team_id,
class_name: 'Affiliation',
dependent: :destroy
has_many :affiliated_tournaments,
through: :affiliated_tournament_relationships,
source: :affiliated_tournament,
class_name: 'Tournament'
has_many :affiliated_group_relationships,
foreign_key: :affiliate_team_id,
class_name: 'Affiliation',
dependent: :destroy
has_many :affiliated_groups,
through: :affiliated_group_relationships,
source: :affiliated_group,
class_name: 'Group'
has_many :affiliated_team_relationships,
foreign_key: :affiliate_team_id,
class_name: 'Affiliation',
dependent: :destroy
has_many :affiliated_teams,
through: :affiliated_team_relationships,
source: :affiliated_team,
class_name: 'Team'
has_many :affiliate_team_relationships,
foreign_key: :affiliated_team_id,
class_name: 'Affiliation',
dependent: :destroy
has_many :affiliates,
through: :affiliate_team_relationships,
source: :affiliate_team,
class_name: 'Team'
belongs_to :leader, foreign_key: 'user_id', class_name: User
validates :name, presence: true, length: { minimum: 3, maximum: 24 }, uniqueness: { case_sensitive: false }
mount_uploader :avatar, AvatarUploader
include PgSearch
pg_search_scope :text_search,
against: :name,
using: { tsearch: { prefix: true }}
multisearchable against: :name,
using: { tsearch: { prefix: true }}
def self.construct(options)
team = Team.new(name: options[:name])
team.team_memberships << TeamMembership.new(user_id: options[:leader].id)
team.leader = options[:leader]
return team
end
end
class Tournament < ActiveRecord::Base
include ActiveModel::Validations
attr_accessor :start_date, :start_hour, :start_minute, :start_period
belongs_to :owner, foreign_key: 'user_id', class_name: User
has_many :tournament_memberships
has_many :users, through: :tournament_memberships
has_many :teams, through: :tournament_memberships
has_many :matches, inverse_of: :tournament
has_many :user_showings, through: :matches
has_many :team_showings, through: :matches
has_many :moderator_roles
has_many :moderators, through: :moderator_roles, source: :user
serialize :bracket
has_many :affiliate_team_relationships, foreign_key: :affiliated_tournament_id, class_name: 'Affiliation', dependent: :destroy
has_many :affiliates, through: :affiliate_team_relationships, source: :affiliate_team, class_name: 'Team'
include PgSearch
pg_search_scope :text_search,
against: {title: 'A', description: 'B'},
using: { tsearch: { prefix: true }}
multisearchable against: [:title, :description],
using: { tsearch: { prefix: true }}
validates :title, presence: true
validates :game, presence: true
validates_with TimeValidator, on: :create
validates_with TimeValidator, on: :update, if: :time_parameters?
before_save :set_starts_at, if: :time_parameters?
def set_starts_at
self.starts_at = Time.zone.parse("#{start_date} #{start_hour}:#{start_minute}#{start_period}")
end
def time_parameters?
start_hour.present? || start_minute.present? || start_date.present?
end
def start
reset_bracket
rounds = calculate_rounds
self.bracket = [[nil]]
rounds.times do |i|
self.bracket.unshift(Array.new((2**(i+1))/2))
end
initialize_bracket
self.started = true
self.save
end
def reset_bracket
self.user_showings.each(&:destroy)
self.matches.destroy_all
self.bracket = nil
end
def calculate_rounds
Math.log2(tournament_memberships.count).ceil
end
def calculate_filtered_round_size(rounds)
2**(rounds - 1)
end
def calculate_number_of_filter_pairs(filtered_round_size)
tournament_memberships.count - filtered_round_size
end
def add_participant_pair_to_match(match, pair)
if self.mode == 'individual'
match.user_showings.push UserShowing.new(user_id: pair[0].user_id, top: true), UserShowing.new(user_id: pair[1].user_id)
elsif self.mode == 'team'
match.team_showings.push TeamShowing.new(team_id: pair[0].team_id, top: true), TeamShowing.new(team_id: pair[1].team_id)
end
end
def add_first_initialized_filtered_round_participant_to_match(match, filter_slots)
if self.mode == 'individual'
match.user_showings.push UserShowing.new(user_id: tournament_memberships[filter_slots..-1].first.user_id)
elsif self.mode == 'team'
match.team_showings.push TeamShowing.new(team_id: tournament_memberships[filter_slots..-1].first.team_id)
end
end
def add_filled_matches_to_filter_round(filter_slots)
tournament_memberships.first(filter_slots).each_slice(2).with_object([]) do |pair,obj|
match = Match.new
self.matches << match
add_participant_pair_to_match(match, pair)
obj << match
end
end
def build_filtered_round_matches_with_odd_remainder(filter_slots)
after_filter_round = []
match = Match.new
self.matches << match
add_first_initialized_filtered_round_participant_to_match(match, filter_slots)
after_filter_round << match
tournament_memberships[filter_slots+1..-1].each_slice(2) do |pair|
match = Match.new
self.matches << match
add_participant_pair_to_match(match, pair)
after_filter_round << match
end
return after_filter_round
end
def build_filtered_round_matches_with_even_remainder(filter_slots)
tournament_memberships[filter_slots..-1].each_slice(2).with_object([]) do |pair, after_filter_round|
match = Match.new
self.matches << match
add_participant_pair_to_match(match, pair)
after_filter_round << match
end
end
def initialize_bracket
## Takes the number of rounds and finds how many slots are contested
## for the round following the "filter" round. It then takes these contested
## slots, multiplies them by two and shoves that amount of players into
## the "filter" round. The remainder get moved onto the end of the next round.
rounds = calculate_rounds
filtered_round_size = calculate_filtered_round_size(rounds)
filter_pairs = calculate_number_of_filter_pairs(filtered_round_size)
filter_slots = filter_pairs*2
self.bracket[0][0..((filter_slots/2)-1)] = add_filled_matches_to_filter_round(filter_slots)
if tournament_memberships[filter_slots..-1].length.odd?
self.bracket[1][(filter_pairs/2)..-1] = build_filtered_round_matches_with_odd_remainder(filter_slots)
else
self.bracket[1][(filter_pairs/2)..-1] = build_filtered_round_matches_with_even_remainder(filter_slots)
end
end
def find_bottom_participant(match)
if match.tournament.mode == "individual"
match.user_showings.find {|us| us.top == nil } ## methods
elsif match.tournament.mode == "team"
match.team_showings.find {|ts| ts.top == nil } ## methods
end
end
def find_top_participant(match)
if match.tournament.mode == "individual"
match.user_showings.find {|us| us.top == true } || match.user_showings.first ## methods
elsif match.tournament.mode == "team"
match.team_showings.find {|ts| ts.top == true } || match.team_showings.first ## methods
end
end
def create_and_position_new_match(position, new_showing)
match = Match.create
self.matches << match
add_showing_to_match(match, new_showing)
self.bracket[position[0]+1][position[1]/2] = match
end
def add_showing_to_match(match, new_showing)
if self.mode == "individual"
match.user_showings.push new_showing
elsif self.mode == "team"
match.team_showings.push new_showing
end
end
def set_new_showing(participant, position)
if self.mode == "individual"
UserShowing.new(user_id: participant.user_id, top: (position[1].even? ? true : nil) )
elsif self.mode == "team"
TeamShowing.new(team_id: participant.team_id, top: (position[1].even? ? true : nil) )
end
end
def advance position
match = self.bracket[position[0]][position[1]]
if position[2] == 1
participant = find_bottom_participant(match)
else
participant = find_top_participant(match)
end
## Create a new user showing and place him on top if his index is even
new_showing = set_new_showing(participant, position)
## Place the new user showing the correct position
next_match = self.bracket[position[0]+1][position[1]/2]
if next_match.nil?
create_and_position_new_match(position, new_showing)
else
add_showing_to_match(next_match, new_showing)
end
self.save
end
def delete_slot position
match = self.bracket[position[0]][position[1]]
if position[2] == 1
showing = find_top_participant(match)
else
showing = find_top_participant(match)
end
showing.destroy
end
end
class TournamentMembership < ActiveRecord::Base
belongs_to :user
belongs_to :tournament
belongs_to :team
validates :user_id, uniqueness: { scope: :tournament_id,
message: 'can only sign up once per tournament'}, if: :individual_mode
validates :team_id, uniqueness: { scope: :tournament_id,
message: 'can only sign up once per tournament'}, if: :team_mode
def individual_mode
self.tournament.try(:mode) == 'individual'
end
def team_mode
self.tournament.try(:mode) == 'team'
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment