Gem 'merit' not counting points - ruby-on-rails

The goal is to give a user points when his comment gets an upvote. Now it just gives points when the comment is created(5 points) and doesn't count upvotes.
I've looked at this answer and according to it my code is correct. I'm using acts_as_votable gem for upvotes/downvotes.
gemfile
gem 'merit', '~> 2.1.1'
comments_controller
def upvote
#comment.liked_by current_user
render "update_likes"
end
point_rules
module Merit
class PointRules
include Merit::PointRulesMethods
def initialize
score 5, :on => ['comments#create'], :to => [:user], category: 'gold_points'
score 2, :on => ['comments#upvote'], :to => [:user], category: 'gold_points'
end
end
end
user model
class User < ActiveRecord::Base
has_merit
display points
<%= #user.points(category: 'gold_points') %>

I found the answer:
change
render "update_likes"
to
render :nothing => true

Related

Rails 4 Route Parameters Defined by Keywords

We're trying to set up rails routes with the parameters separated by more then just forward-slash symbols.
As an example:
someexample.com/SOME-ITEM-for-sale/SOME-PLACE
For the following path we'd like to extract SOME-ITEM and SOME-PLACE strings as parameters whilst identifying which controller to run it all against with the "-for-sale/" part.
I've been playing with variations on :constraints => {:item => /[^\/]+/} constructs but without any success. Am I looking in the right place? Thanks!
UPDATE
In the end I went with this solution:
get ':type/*place' => 'places#index', as: :place , :constraints => {:type => /[^\/]+-for-sale/}
And then recovered the full "SOME-ITEM-for-sale" sting for parsing in the controller using
params[:type]
Hope that helps someone!
friendly_id is what you want:
#Gemfile
gem 'friendly_id', '~> 5.1.0'
$ rails generate friendly_id
$ rails generate scaffold item name:string slug:string:uniq
$ rake db:migrate
#app/models/item.rb
class Item < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
end
The above will give you a slug column, which FriendlyId will look up any requests you send to the app:
#config/routes.rb
resources :items, path: "" do
resources :places, path: "" #-> url.com/:item_id/:id
end
Although the params will still be id (unless you use the param option of resources, but FriendlyId will override both your routes and model to use the slug instead:
<%= link_to "Item Place", items_place_path(#item, #place) %> #-> url.com/item-name-information/place-name-information
Update
If you wanted to have a "dynamic" routing structure, you'll be able to use the following (this requires the history module of FriendlyId):
#config/routes.rb
#...
get '/:item_id/:place_id', to: SlugDispatcher.new(self), as: :item #-> this has to go at the bottom
#lib/slug_dispatcher.rb
class SlugDispatcher
#http://blog.arkency.com/2014/01/short-urls-for-every-route-in-your-rails-app/
##########################################
#Init
def initialize(router)
#router = router
end
#Env
def call(env)
id = env["action_dispatch.request.path_parameters"][:item_id]
slug = Slug.find_by slug: id
if slug
strategy(slug).call(#router, env)
else
raise ActiveRecord::RecordNotFound
end
end
##########################################
private
#Strategy
def strategy(url)
Render.new(url)
end
####################
#Render
class Render
def initialize(url)
#url = url
end
def call(router, env)
item = #url.sluggable_type.constantize.find #url.sluggable_id
controller = (#url.sluggable_type.downcase.pluralize + "_controller").classify.constantize
action = "show"
controller.action(action).call(env)
end
end
####################
end
This won't work out the box (we haven't adapted it for nested routes yet), but will provide you the ability to route to the appropriate controllers.
In the end we went with this solution:
get ':type/*place' => 'places#index', as: :place , :constraints => {:type => /[^\/]+-for-sale/}
The router command only gets activated if the :type parameter contains "-for-sale" in the string
And then we recovered the full "SOME-ITEM-for-sale" sting for parsing in the controller using
params[:type]
Hope that helps someone!

merit ruby gem not working with conditional statement

The merit ruby gem is not adding the points to the user with the "user.passion.present" added. It works without it. I set everything up with working with Devise and Merit gems. Everything seems to work except this.
module Merit
class PointRules
include Merit::PointRulesMethods
def initialize
score 50, :on => 'user/registrations#create', model_name: 'User'
score 10, :on => 'user/registrations#update', model_name: 'User' do |user|
user.passion.present?
end
#
# score 15, :on => 'reviews#create', :to => [:reviewer, :reviewed]
#
# score 20, :on => [
# 'comments#create',
# 'photos#create'
# ]
score 20, on: 'lyrics#create', to: :user, description: 'Plus 20 points'
score (-20), on: 'lyrics#destroy', to: :user
end
end
end
Did you add the instance variable to the update overridden action?
See wiki page: https://github.com/tute/merit/wiki/How-to-grant-badges-on-user-registration-using-Devise.

Rails - Include association in json response

I got 2 Tables/Models: Paths and Questions. Each question belongs to a path
My question.rb:
class Question < ActiveRecord::Base
belongs_to :path
end
My path.rb
class Path < ActiveRecord::Base
has_many :questions
end
Everything works fine like
p = Path.last
Path.questions
returns everything I need but I'm returning a json response like this:
#path = Path.find_by_id(params[:id])
render :status=>200, :json => {:status => "success", :path => #path, :message => "Showing path"}
That answer doesn't include the questions for the path of course. What do I have to change to include all questions belonging to that path? I know I could just add :path_questions => #path.questions but is there no way to include the questions without a new return variable? I hope it's clear what I mean.
I do it like that in a Rails 5 API app:
BooksController
def index
#books = Book.limit(params[:limit])
render json: #books, include: ['author'], meta: { total: Book.count }
end
In the above situation, a Book belongs_to Author.
This is quite hacky, but should work:
:path => #path.as_json.merge(:questions => #path.questions.as_json)
Eventually you can override as_json inside your model:
def as_json(options={})
includes = [*options.delete(:include)]
hash = super(options)
includes.each do |association|
hash[self.class.name.underscore][association.to_s] = self.send(association).as_json
end
hash
end
And then just call: :path => #path.as_json(:include => :questions)
Note it will also add :include option to to_json method.

newbie: activerecord compare object.count with value throws undefined method `to_sym' for nil:NilClass

def has_photo
if user_signed_in?
#user = User.where(:id => current_user.id).first
if #user.has_photo?
if Asset.where(:attachable_id => current_user.id).count < 4
def sub_layout
"application"
end
render :template => "profiles/no_photo"
end
end
end
end
What would be the correct way to compare the Asset.count ?
Asset.where is a query, you would be much better using relationships for this.
If
Class User
has_many :assets
end
Class Asset
belongs_to :user
end
You could just use:
#user.assets.count < 4
As long as Asset has a user_id field (or make the relationship use :attachable_id) that is correctly set (the relationship can do that too if you create the Asset correctly)
By the way, if :id is unique for each user (it should be) you can rewrite
#user = User.where(:id => current_user.id).first
as
#user = User.find(current_user.id)
Hope it helps

Overriding a model rails 3.1

I am trying to override a model of forem gem so that I could use thumbs_up gem for voting purpose.
I did a rails g model Post and trying to inherit the post model of forem by this line of code
class Post < Forem::Post
acts_as_voteable
end
same for the controller
class PostsController < Forem::Postscontroller
def vote_up
begin
current_user.vote_for(#post = Post.find(params[:id]))
render :nothing => true, :status => 200
rescue ActiveRecord::RecordInvalid
render :nothing => true, :status => 404
end
end
end
I keep getting this error
undefined method `vote_up_post_path'
in my route.rb
mount Forem::Engine, :at => "/forums"
resources :posts do
member do
post :vote_up
end
end
I guess I am doing something really stupid out here and I am not overriding the model correctly. I was using this Clarification on how to use "thumbs_up" voting gem with Rails 3 post to set up thumbs_up
Can someone help??
If I'm getting your question correctly, you wanna change the behavior of forem Post in order to support voting using acts_as_votable.
For that to work you need to re-open Forem::Post class in an initializer (e.g. config/initializers/forem.rb) and add to it acts_as_votable line like this:
module Forem
class Post
acts_as_votable
end
end
And the same for Forem::PostsController:
module Forem
class PostsController
def vote_up
begin
current_user.vote_for(#post = Post.find(params[:id]))
render :nothing => true, :status => 200
rescue ActiveRecord::RecordInvalid
render :nothing => true, :status => 404
end
end
end
end
It seems it was a stupid mistake, realized it while having discussion with patrickmcgraw.
forem hides your routes and and you have to mention main_app before the routes, so after writing
main_app.vote_up_post_path instead of vote_up_post_path the page was up again.
Hope it helps someone trying to use forem.

Resources