Search code examples
rubyfileruby-on-rails-4link-to

Ruby on Rails - run Ruby File.open only when link is clicked


In my application I have a link_to that I use for voting purposes. This link_to does different things if user_signed_in? or not.

When user IS signed in, they can vote, otherwise a modal opens for them to sign up or login.

What I want to achieve is to count how many users has clicked on voting buttons but didn't vote because of sign up.

I was thinking to do a easy ruby operation and add 1 and date for each click.

Here is my link:

= link_to_unless has_voted?(@image.id, 1), (image_tag 'vote/thumb-up.png'),user_signed_in?? vote_image_path : File.open("public/count.txt", "a+") { |file| file.puts ([1, Date.today]).join }, data: {target: user_signed_in?? "" : "#login-modal", toggle: user_signed_in? ? "" : 'modal'}, remote: true

Everything works fine when user is signed in, but when I want to run: File.open("public/count.txt", "a+") { |file| file.puts ([1]).join } is when things goes wrong.

This adds the number, but instead of adding number to count.txt file only when link_to is clicked, it also adds 1 for each visit/refresh.

How can I make File.open("public/count.txt", "a+") { |file| file.puts ([1]).join } only run when link_to is clicked and not on each visit/refresh.

I have been thinking to make a route and add the function there and redirect back, but then I can't open sign up modal and at same time I do not want to refresh the page and send user back and forward.


Solution

  • Seems to me like it would be a good fit for server-generated JavaScript responses.

    To summarize the concept:

    • create a link which triggers an AJAX request to the server (using link_to with remote: true)
    • let the server decide whether to count the vote or increase the voted-but-not-logged-in-counter and show the modal. Based on this it will generate the corresponding JavaScript which will be executed on the client
    • the client receives a JavaScript response and executes it

    It is your decision whether the modal functionality is already loaded from the start and the server just returns showLoginModal(); or whether the server response contains the whole JavaScript to create the modal.