Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add random button to form

I want to provide users a 'random' option so they can select a previous created date idea to use from the database (inside the letsgos table). There’s a “Let’s Go...” section that users can fill out a form and propose a date they would like to go on. There are going to be users who won’t be able to come up with a date idea on their own. So for those users who cannot create their own date I want to provide a ‘random’ button that with each click will insert a date (that’s from the database) into the form. The dates in the database from the letsgos table have content and tag assign to them. When a user clicks on random it should populate the form with the content and tag (each random click should show new data from the database). I don't have any javascript experience so I am not sure if I am doing it the right way.

/views/letsgos/_form.html.erb:

   <%= form_for(@letsgo) do |f| %>
    <div class="field">
        <%= f.text_area :content, placeholder: "Propose new date..." %>
        </div>
        <%= f.select :tag, options_for_select( [["Select One", ""], "Eat/Drink", "Listen/Watch", "Play", "Explore", "Other"]) %>
        <a href="/letsgos/random" class="ajax">Click here for a Random letsgo</a>
        <%= f.submit "Post" %>

        <% end %>

/views/layouts/application.html.erb

<head>
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>

<script>
  $(document).ready(function() {
    $('.ajax').click(function() {
      $.get(this.href, function(response) {
        console.log(response);
        $('body').html(response); 
      });
    });
  });
<script>
</head>

letsgo controller:

  def create
    @letsgo = current_user.letsgos.build(letsgo_params)
    if @letsgo.save
      flash[:success] = "Date posted!"
      redirect_to root_url
else
      flash[:error] = "Date was not posted!"
      redirect_to root_url
end
end
  def destroy
    @letsgo.destroy
    redirect_to root_url
  end

def random
  @letsgo = Letsgo.random.first
  if request.xhr?
  end
end

private

def letsgo_params
  params.require(:letsgo).permit(:content, :tag)
end

def correct_user
  @letsgo = current_user.letsgos.find_by(id: params[:id])
  redirect_to root_url if @letsgo.nil?
end

Caching columns migration:

rails g migration add_ids_count

def self.up
add_column :letsgos, :ids_count, :integer, :default => 0

 Letsgo.reset_column_information
    Letsgo.all.each do |l|
      l.update_attribute :id_count, l.id.length
    end
  end

 def self.down
    remove_column :letsgos, :id_count
  end
end
like image 657
Cornelius Wilson Avatar asked Oct 03 '22 15:10

Cornelius Wilson


1 Answers

A creative solution to this would be to set up a caching column to store an array of IDs of Letsgo's, if you're worried about the performance on Antarr Byrd's suggestion. Basically, this would cache the Letsgo.pluck(:id) in a single column in the DB. (Maybe do this in a worker in a post-save and/or post-delete hook on Letsgos.) I'd recommend doing this in a buffer of some sort, or maybe as an hourly task.

You could then either pull this in as a JavaScript array (letsgos_ids_array in the example) and create a Math.random() value based on the length of that array and send it to the .find(). Of course you could also just output the array's length directly.

var item_index = Math.floor(Math.random() * letsgos_ids_array_length);
$.get("/letsgos/random", {
    "ind" : item_index
}, function(data){
    /* do something with the data */
});

Then, this index can be used to pull out the actual ID value from the array from the db.

letsgoarray = Letsgosarray.first # this is the single-column "cached" array of IDs
item_id = letsgosarray[params[:id_index]]
@random_letsgo = Letsgos.find(item_id)
format.json do {
    render json: @random_letsgo
}

Array access is fast, and so is single db column querying.

like image 163
Jonathan Cutrell Avatar answered Oct 07 '22 19:10

Jonathan Cutrell