Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Freeze a random number in Ruby

I'm trying to build something that will randomly pick two objects from a list in Ruby (using Rails) and then perform basic operations on those objects. My current set up involves randomly picking numbers at the start - using these numbers to get objects from the database and then rendering those objects to index. However, now I'm trying to edit these objects using AJAX I'm running into a problem.

It seems that, when I click on a link that the random number in being recalculated and is causing my AJAX function not to work.

I've included (what I believe is) all relevant code below but let me know if you need to see anything else to get to the bottom of this. I'm looking to get the titles of the old animals and (ideally their previous ratings and) their new ratings to appear at the bottom of the page.

Thanks,

Matt

controllers/static_pages.rb

class StaticPagesController < ApplicationController
respond_to :html, :js
before_filter :pickanimals

def pickanimals
    @allAnimals = Animal.all
    @random_no = rand(@allAnimals.length)
    @animal = @allAnimals[@random_no]
    @allAnimals.delete_at(@random_no)
    @newRandom = rand(@allAnimals.length)
    @animal2 = @allAnimals[@newRandom]
end

  def index
    respond_to do |format|
        format.html
        format.js
    end
end

  def help
  end

  def about
  end

  def contact
  end

def league
end

def voting
    @votedAnimal = Animal.find(params[:id])
    if @votedAnimal == @animal
        @animal.rating += 1
        @animal2.rating -= 1
    else
        @animal.rating -= 1
        @animal2.rating += 1    
    end
    Animal.transaction do
        @animal.save!
        @animal2.save!
    end
    respond_to do |format|
        format.html { redirect_to root_path }
        format.js  
    end
end
end

app/views/static_pages/index.html.erb

<div class="center hero-unit">
<h1>Animal Attack</h1>
<p> Who will win when nature collides? </p>
<div class="animalcontainerright">
<h2> <%= @animal.name %> </h2> 
<%= link_to image_tag(@animal.attachment.url(:large)), voting_path(@animal.id), :remote => true, :confirm => "Rating:  "[email protected]_s  %>
</div>
<div class="animalcontainerleft">
<h2> <%= @animal2.name %> </h2>
<%= link_to image_tag(@animal2.attachment.url(:large)), voting_path(@animal2.id), :remote => true, :confirm => "Rating:  "[email protected]_s  %>
</div>
<div id="animalfacts"></div>

routes.rb

AnimalAttack::Application.routes.draw do

resources :animals

root to: 'static_pages#index'
match '/help' => 'static_pages#help'
match '/about' => 'static_pages#about'
match '/contact' => 'static_pages#contact'
match '/league' => 'static_pages#league'
match '/voting/:id' => 'static_pages#voting'

end

rake routes

    animals GET    /animals(.:format)          animals#index
        POST   /animals(.:format)          animals#create
 new_animal GET    /animals/new(.:format)      animals#new
edit_animal GET    /animals/:id/edit(.:format) animals#edit
 animal GET    /animals/:id(.:format)      animals#show
        PUT    /animals/:id(.:format)      animals#update
        DELETE /animals/:id(.:format)      animals#destroy
   root        /                           static_pages#index
   help        /help(.:format)             static_pages#help
  about        /about(.:format)            static_pages#about
contact        /contact(.:format)          static_pages#contact
 league        /league(.:format)           static_pages#league
               /animals(.:format)          animals#new
               /voting/:id(.:format)       static_pages#voting
like image 954
Kali_89 Avatar asked Feb 19 '23 15:02

Kali_89


1 Answers

I'm guessing @animal is being re-assigned because of your :before_filter. Unless you tell it otherwise, it'll execute before all actions (thus reassigning @animal before every controller action). You probably want to limit it to just the methods that need a newly-regenerated random number. For example:

before_filter :pickanimals, :only => :index

Also. Do you know about Array#sample? It's a built-in way of picking a random element from an array. You might find it useful here:

@animal, @animal2 = @allAnimals.sample(2)

ADDITIONALLY

Relying on instance variables in the controller like this is a pretty fragile way of passing information between functions. If your controller needs to know the ids of two models to have counters on each incremented or decremented based on user selection, why not just use a form to send those two ids to this controller action? So far, you'll only need two fields: chosen_animal_id and reject_animal_id.

like image 181
pje Avatar answered Feb 26 '23 21:02

pje