2017-01-02 2 views
0

Dans mon application rails il y a des messages qui ont des liens vers d'autres pages externes (@post.link me donne le lien). Si le current_user clique sur le lien, une action du contrôleur devrait être déclenchée, à savoir l'action viewed, qui devrait mettre à jour ma base de données, plus précisément une table de jointure avec les informations que l'utilisateur a vues le lien.Rails: appelez l'action du contrôleur avec link_to un lien externe (et mettez à jour une table de jointure)

Ce que je l'ai déjà fait jusqu'à présent:

Dans mon point de vue/messages/index.html:

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

Dans mon 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 

J'ai créé une table de jointure appelée views avec les colonnes user_id:integer et post_id:integer.

Dans mes modèles/view.rb

belongs_to :user 
belongs_to :post 

validates_uniqueness_of :post_id, scope: :user_id 

Dans mes modèles/user.rb

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

Dans mes modèles/post.rb

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

Dans mon routes.rb (je ne change rien ou ajouter de nouvelles 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 

Mon problème:

Lorsque je clique sur les liens, ma table de vues ne sont pas mis à jour? (Par exemple, dans ma console rails View.find_by(user_id: some_user_which_has_clicked_on_links.id) ou View.all me donne nulle

+0

ce retour '@ post.views.create (user_id: current_user.id)' . Peut-être que vous devriez utiliser 'create!' Ou tester la valeur de retour? – djothefou

+0

Je ne suis pas sûr, mais dans la méthode ** link_to **, vous utilisez un lien dans le second paramètre, ou Hash avec les touches ** controller ** et ** action **. Mais utilisez les deux semble pas avoir le sens – djothefou

+0

changez-le en '@ post.views.! Create()' et mettez-nous à jour avec le nouveau journal des erreurs, il y a probablement une validation qui échoue ou vous passez une valeur erronée à la fonction de création – amrdruid

Répondre

0

J'ai maintenant essayé une solution avec l'Ajax:

Mon point de vue

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

Mon routes.rb

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

Mes posts_controll er.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 

Mes vues/messages/view.js.erb

// Do some javascript magic here 

Problèmes Je ne suis pas vraiment satisfait de ma solution, car il y a deux problèmes mineurs que je ne peux pas vraiment figurer dehors:

  1. Quand il rend mon lien dans mon contrôleur, le le lien devrait s'ouvrir dans un nouvel onglet (par exemple "_blank"), pas dans la même fenêtre. Au lieu de window.location J'ai essayé window.open, mais rien ne se passe. Lorsque l'utilisateur survole un lien avec sa souris, le navigateur affiche /posts/[:post_id]/view. Il serait préférable qu'il montre déjà le "vrai" lien - à savoir @post.link - comme www.google.com.
  2. Lorsque l'utilisateur ouvre le lien dans un nouvel onglet manuellement, une erreur se produit, par exemple: Aucun résultat de l'itinéraire [GET] "/posts/605/view"