I am trying to implement voting for various models: Character, Universe models. I have some vote buttons on their respective show templates via a single DRY rendered partial. This means I need to make that partial agnostic to the model when I pass that model to the controller logic that creates the vote record.
So yes, I am wondering if it is possible to have this kind of duck typed variable passing to a votes controller, rather than repeating the vote creation logic in each of the Character and Universe controller.
How do I make this sort of duck typed variable passing using path helpers, votes partials, and votes controllers? Or should I just repeat the code in each votable model?
FYI: Naturally, the votes is polymorphic to the two models. I am using acts_as_votable gem https://github.com/ryanto/acts_as_votable
_vote.html.haml
.vote-comment-buttons
= link_to image_tag("upvote.png"), votes_upvote_path(), method: :post, remote: true
%span=# @comment.get_upvotes.sum(:vote_weight)
= link_to image_tag("downvote.png"), votes_downvote_path(), method: :post, remote: true
^ Do I pass a duck type variable to the paths?, If so, how/where do I define the duck type variable?
(Note: i'm trying to vote via AJAX, but feel free to ignore the ajax related code like remote: true)
character.rb
class Character < ActiveRecord::Base
acts_as_votable # creates a polymorphic association with votes
end
universe.rb
class Universe < ActiveRecord::Base
acts_as_votable # creates a polymorphic association with votes
end
votes_controller.rb
class VotesController < ApplicationController
before_action :check_if_voted(@votable)
def upvote
#votable.vote_up current_user
end
def downvote(votable)
#votable.vote_down current_user
end
end
Iis it valid to have parameters on actions? or do you just use params[]?
Iis it valid to have parameters on actions? or do you just use params[]?
You can not have parameters at public actions, all the data should be parsed from params[]
How do I make this sort of duck typed variable passing using path helpers, votes partials, and votes controllers? Or should I just repeat the code in each votable model?
Assuming voting procedure is the same for both models, consider using concerns :
config/application.rb
module YourApplicationName
class Application < Rails::Application
config.autoload_paths += %W(#{config.root}/app/controllers/concerns)
end
end
app/controllers/concerns/voting_controller.rb
module VotingController
extend ActiveSupport::Concern
included do
before_filter :obtain_resources, only: [:upvote, :downvote]
end
def upvote
# here goes your upvoting logics, something like
# @object.liked_by user1, :vote_weight => 1
# the @object variable has already been set in obtain_resource filter
# other params should be catched up from the params hash
end
def downvote
# here goes your downvoting logics
end
private
def obtain_resources
# here we retrieve the name of a particular controller which triggered this action
model = controller_name.singularize.camelize.constantize
@object = model.find(params[:id])
end
end
In case you prefer using meaningful variable names instead of just @object
, you can do this kind of thing:
# app/controllers/concerns/voting_controller.rb
def obtain_resources
model = controller_name.singularize.camelize.constantize
instance_name = controller_name.singularize
# here you get @universe or @character
instance_variable_set "@#{instance_name}", model.find(params[:id])
end
Then in your controllers you should include that concern:
class UniverseController < ApplicationController
include VotingController
# that's all, you should not implement voting actions here as they are included from VotingController
end
class CharactersController < ApplicationController
include VotingController
end
You should also be sure to set appropriate routes in your config/routes.rb file, so that upvote
and downvote
actions exist in both of the controllers. As you could already understand, you should pass upvote_universe_path
or upvote_characters_path
to your partial to make this work (same for the downvoting). Each route should pass id
of the object to controller's action.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.