ruby - Rails 3: Polymorphic liking of Entities by User, how? -
background:
i followed tutorial here setup polymorphic user favorites data model in application. allows me let user make pretty entity in system add 'has_many :favorites, :as => :favorable
' line model favorite. plan on using implement facebook style 'like' system several other similar systems.
to start off added favoritability post model (each user can create status updates on facebook). have done , unit tested know data model sound , functioning either side of relationship (user , post).
details:
i have home controller single index method , view.
on index view render out posts user , user's friends
i want user able posts friends
the posts controller has create , destroy method associated routes (not full fledged resource) , through post method via ajax posts created , deleted without issue
where stuck
how add link or button add post user's favorites?
according tutorial way create new favorite through polymorphic association post.favorites.build(:user_id => current_user.id). direction build handles pulling out post's id , type , have pass in user's id
do use ajax form post favorites controller create , destroy method similar post controller?
i still struggling uncross wires in brain asp.net n-tier web application development on rails mvc. hasn't been bad until ;)
i bet there gems out there might need learn , best way suffer through it. maybe tutorial or sample code has implemented liking functionality within application helpful.
thanks in advance assistance!
jaap, appreciate comment on question. after writing question pretty didn't want wait because real learning takes place through trial , error, errored ;)
it turns out suggested pretty in line ended doing myself (it's nice find out decide others well, love sanity check value of all).
so here did , working through post-backs. need implement ajax , style it:
my favorite model because polymorphic favorites model requires entity can favorited once user added validations 'scopes' indicate each attribute has unique in scope of other 2 required attributes. solves issue of multiple favorites same user.
class favorite < activerecord::base before_save :associate_user belongs_to :favorable belongs_to :user # validations validates :user_id, :presence => true, :uniqueness => {:scope => [:favorable_id, :favorable_type], :message => "item in favorites list."} validates :favorable_id, :presence => true, :uniqueness => {:scope => [:user_id, :favorable_type], :message => "item in favorites list."} validates :favorable_type, :presence => true, :uniqueness => {:scope => [:favorable_id, :user_id], :message => "item in favorites list."} # callbacks protected def associate_user unless self.user_id return self.user_id = session[:user_id] if session[:user_id] return false end end end
my user model (that relevant): added 2 methods, get_favorites same favorable 1 tutorial , favorite? method checks see if entity in question has been added user's favorites.
class user < activerecord::base # relationships has_many :microposts, :dependent => :destroy has_many :favorites # methods def favorite?(id, type) if get_favorites({:id => id, :type => type}).length > 0 return true end return false end def get_favorites(opts={}) # polymorphic favoritability: allows model in # application favorited user. # favorable_type type = opts[:type] ? opts[:type] : :topic type = type.to_s.capitalize # add favorable_id condition if id provided con = ["user_id = ? , favorable_type = ?", self.id, type] # append favorable id query if :id passed option # function, , append id string "con" array if opts[:id] con[0] += " , favorable_id = ?" con << opts[:id].to_s end # return favorite objects matching above conditions favs = favorite.all(:conditions => con) case opts[:delve] when nil, false, :false return favs when true, :true # list of favorited object ids fav_ids = favs.collect{|f| f.favorable_id.to_s} if fav_ids.size > 0 # turn capitalized favorable_type actual class constant type_class = type.constantize # build query selects query = [] fav_ids.size.times query << "id = ?" end type_conditions = [query.join(" , ")] + fav_ids return type_class.all(:conditions => type_conditions) else return [] end end end end
my micropost model (that relevant): note polymorphic association in has_many relationship titled :favorites.
class micropost < activerecord::base attr_accessible :content # scopes default_scope :order => 'microposts.created_at desc' # relationships belongs_to :user has_many :favorites, :as => :favorable # polymorphic association # validations validates :content, :presence => true, :length => { :minimum => 1, :maximum => 140 } validates :user_id, :presence => true end
my micropost form: can see passing in entity mapped favorite model local variable 2 favorite forms 'local_entity'. way can pull out id , type of entity polymorphic association.
<div class="post"> <span class="value"> <%= micropost.content %> </span> <span> <% if current_user.favorite?(micropost.id, micropost.class.to_s) %> <%= render :partial => 'favorites/remove_favorite', :locals => {:local_entity => micropost} %> <% else %> <%= render :partial => 'favorites/make_favorite', :locals => {:local_entity => micropost} %> <% end %> </span> <span class="timestamp"> posted <%= time_ago_in_words(micropost.created_at) %> ago. </span> <div class="clear"></div> </div>
my make favorite form:
<%= form_for current_user.favorites.build |f| %> <div><%= f.hidden_field :favorable_id, :value => local_entity.id %></div> <div><%= f.hidden_field :favorable_type, :value => local_entity.class.to_s %></div> <div class="actions"><%= f.submit "make favorite" %></div> <% end %>
my remove favorite form:
<%= form_for current_user.get_favorites( {:id => local_entity.id, :type => local_entity.class.to_s}), :html => { :method => :delete } |f| %> <div class="actions"><%= f.submit "remove favorite" %></div> <% end %>
Comments
Post a Comment