2015-06-16 13 views
6

Üç modelim var: Kullanıcı, Yorum ve Yorum. Kullanıcıdan Yorum bire-bir ilişki vardır, Yorum-to-Upvote bire-çok ilişkisi vardır ve Kullanıcı-to-Upvote bire-çok ilişkisi vardır.Her yorum için tavsiye edilen modelin kullanılmasını önleyin

Yığınlama akışına benzer bir işlem yapmak istiyorum. Bu nedenle, sayfayı yenilediğinizde/düşürdüğünüzde, sayfayı yenilediğinizde veya sayfalar/haftalar sonra tekrar gelse bile, ok vurgulanacak ve vurgulanacaktır.

Şu anda yapıyorum:

<% if Upvote.voted?(@user.id, comment.id) %> 
    <%= link_to '^', ... style: 'color: orange;'%> 
<% else %> 
    <%= link_to '^', ... style: 'color:black;'%> 
<% end %> 

voted? yöntem şöyle burada:

def self.voted?(user_id, comment_id) 
    find_by(comment_id: comment_id, user_id: user_id).present? 
    end 

Bir sayfada 10 yorumlarınız varsa Yani, bu benim veritabanından bir upvote yükleyecektir 10 kez, sadece var olup olmadığını kontrol etmek için!

Bunu yapmak için daha iyi bir yol olmalı, ama bence beynim çalışmayı bıraktı, bu yüzden hiç düşünemiyorum.

+1

'upvote oylanacak kontrolörü

def index current_user = User.first # current_user may come from devise or any authentication logic you have. @comments = Comment.select('comments.*, upvotes.id as upvote').joins("LEFT OUTER JOIN upvotes ON comments.id = upvotes.comment_id AND upvotes.user_id = #{current_user.id}") end 

Ve görünümde de Sonra

# user.rb class User < ActiveRecord::Base has_many :comments has_many :upvotes end # comment.rb class Comment < ActiveRecord::Base belongs_to :user has_many :upvotes end # upvote.rb class Upvote < ActiveRecord::Base belongs_to :user belongs_to :comment end 

sınıf Oylama eylemini düşünürseniz, bu 'yorum'un yaptığı bir şey değil,' kullanıcı 'gibi bir şeydir. Yöntemi "Kullanıcı" sınıfına taşıyacağım. – kobaltz

+0

Bir yan notta, 'find_by(). Present [yerine] yapmak yerine, var olanı yapmak daha iyi olabilir?()' –

cevap

7

düzgün ayarlanmış ilişkileri

var varsayarsak
# user.rb 
class User 
    has_many :upvotes 
end 
biz yorum, geçerli kullanıcı ve onun upvotes yükleyebilirsiniz

:

# comments_controller.rb 
def index 
    @comments = Comment.limit(10) 
    @user = current_user 
    user_upvotes_for_comments = current_user.upvotes.where(comment_id: @comments.map(&:id)) 
    @upvoted_comments_ids = user_upvotes_for_comments.pluck(:comment_id) 
end 

Sonra görünümünde if koşulu değiştirin:

# index.html.erb 
<% if @upvoted_comments_ids.include?(comment.id) %> 
    <%= link_to '^', ... style: 'color: orange;'%> 
<% else %> 
    <%= link_to '^', ... style: 'color:black;'%> 
<% end %> 

Sadece 2 DB sorgusu gerektirecektir. Umarım yardımcı olur.

+0

Ayrıca bir "has_many through" ilişkilendirmesi kullanırsanız ve kullanıcı tanımlayın -> upvotes - -> yorumlar, daha sonra bunu bir birleştirme ve db'ye tek bir isabetle gerçekleştirebilirsiniz. –

+0

Kendinizi bir haritadan kurtarabilir ve veritabanı sorgusunun boyutunu küçültebilirsiniz: @comments = Comment.limit (10) .pluck (: id) ' – williamcodes

+0

@williamcodes Yorum nesnelerinin sayfada görüntülenebilmesi için 'pluck' – hedgesky

2

sayfa başına N yorumlarına sınırlama varsa o zaman muhtemelen ... ith sayfa için N yorumların ith seti, bir şey 1, 2. dönmek için limit ve offset yöntemler kullanılarak iki sorgularda yapabilirsiniz gibi (sözdizimi Ruby benim birincil dil değil, kapalı olabilir)

comment_ids = 
    Comments.select("comment_id") 
      .where(user_id: user_id) 
      .order(post_date/comment_id/whatever) 
      .offset(per_page * (page_number - 1)) // assumes 1-based page index 
      .limit(per_page) 

Bu size upvote sorgulamak için kullanabileceğiniz comment_ids bir listesini verir:

upvoted_comments = 
    Upvotes.select("comment_id") 
      .where(user_id: user_id, comment_id: comment_ids) 

comment_ids ürününü, Upvote'da bulunan bir sütuna göre sıralıyorsanız (ör. comment_id ile sıralama yapıyorsanız, Upvote sorguyu bir aralık sorgusuyla değiştirebilirsiniz.

Bir hash değerine upvoted_comments koyun ve gitmekte fayda var - eğer comment_id hash değerindeyse, o zaman değil, aksi durumda.

0

bu bu durumda aşırı sorgularını önlemek emin değilim ama bir yorum getirme zaman belki upvotes şunları içerebilir: Sonra görünümünde

@comments = Comment.includes(:upvotes).where(foo: 'bar').limit(10) 

:

<%= 
    link_color = comment.upvotes.map(&:user_id).include?(@user.id) ? 'orange' : 'red' 
    link_to '^', ...style: "color: #{link_color}" 
%> 
+0

'u kullanamayız Aynı durumda, bir nesnenin varlığını sorgulamak için 10 defa DB'ye varabilirim. –

+0

Haklısınız. Afedersiniz! Yanlış anlamışım. Benim önerimi gözden geçireceğim .. –

+0

Görüşünüzü beğeniye sevdim, sahip olduğumdan daha temiz. –

4

Yapabiliriz Tek bir sorgu tarafından ele alınmasını istiyorsanız, aşağıdaki yolu yapın.

ilişkiler doğru olduğundan emin olun Lets Muhtemelen çağıran edilmemelidir

# index.html.erb 
<% @comment.each do |comment| %> 
    <% link_color = comment.upvote ? 'orange' : 'black' %> 
    <%= link_to '^', ...style: "color: #{link_color}" %> 
<% end %> 
# And all of your logics ;) 
İlgili konular