Rails: Call controller action with link_to an external link (and update a join-table)

605 views Asked by At

In my rails app there are posts which has links to other external pages (@post.link gives me the link). If the current_user clicks on the link, a controller action should be triggered, namely the action viewed, which should update my database, more specifically a join-table with the information that the user has viewed the link.

What I've already done so far:

In my views/posts/index.html:

# Looping through all the posts
<%= link_to post.title, post.link, target: "_blank", controller: "posts", action: "viewed" %>

In my posts_controller.rb

def viewed
  @post = Post.find(params[:id])
  @post.views.create(user_id: current_user.id)

  #respond_to do |format|
  #  format.html { redirect_to posts_path }
  #  format.js
  #end
end

I've created a join table called views with the columns user_id:integer and post_id:integer.

In my models/view.rb

belongs_to :user
belongs_to :post

validates_uniqueness_of :post_id,  scope: :user_id

In my models/user.rb

has_many :views, dependent: :destroy
has_many :viewed_posts, through: :views, source: :post

In my models/post.rb

has_many :views, dependent: :destroy
has_many :viewed_user, through: :views, source: :user

In my routes.rb (I did not change anything or add any new routes)

devise_for :users, :controllers => {:registrations => "users/registrations", :sessions => "users/sessions"}
resources :users, only: [:show]
resources :thumbnails, only: [:new]
resources :posts, except: [:show] do
  member do 
    post 'upvote'
    post 'fupvote'
  end
end

authenticated :user do 
  root "posts#index"
end

My problem:

When I click on the links, my views table is not updated? (E.g. in my rails console View.find_by(user_id: some_user_which_has_clicked_on_links.id) or View.all gives me nil?

1

There are 1 answers

0
OhDaeSu On

I have now tried a workaround with Ajax:

My view

<%= link_to(view_post_path(post), :method => :post, :remote => true) do %>
  <%= post.title %>
<% end %>

My routes.rb

resources :posts, except: [:show] do
  member do 
    post 'upvote'
    post 'view'
  end
end

My posts_controller.rb

def view
  @post.views.create(user_id: current_user.id)

  respond_to do |format|
    format.html { redirect_to posts_path }
    #It now renders my external link. Problem: I cannot open it in a new tab. 
    format.js { render :js => "window.location = '#{@post.link}';"} 
  end
end

My views/posts/view.js.erb

// Do some javascript magic here 

Problems I am not really happy with my solution because there are two minor problems which I cannot really figure out:

  1. When it renders my link in my controller, the link should open in a new tab (e.g. "_blank"), not in the same window. Instead of window.locationI've tried window.open, but nothing happens.
  2. When a user hovers over a link with his mouse, the browser shows /posts/[:post_id]/view. It would be better if it already shows the "real" link - namely @post.link - like www.google.com.
  3. When the user opens the link in a new tab manually, an error occurs, e.g.: No route matches [GET] "/posts/605/view"