Vote with Mongoid at Ruby on Rails - ruby-on-rails

I've got a problem with my vote methods for comments. Im a begginer at RoR and waiting for your suggestions.
The error I get is:
ActionController::RoutingError at /posts/51f7d1279fefa5405a000003 No
route matches {:controller=>"comments", :action=>"vote(1)",
:class=>"post__button--edit"}
My code:
comment.rb
class Comment
include Mongoid::Document
field :name, type: String
field :email, type: String
field :body, type: String
field :up_vote, type: Integer, default: "0"
field :down_vote, type: Integer, default: "0"
belongs_to :post
validates_presence_of :name, :email, :body
def self.add_up_vote
self.increment(:up_vote, 1)
end
def self.add_down_vote
self.decrement(:down_vote, 1)
end
end
comment_controller.rb
.
.
.
def vote(a)
#comment = Comment.find(params[:comment_id])
#post = Post.find(params[:post_id])
if a == 1
comment.add_up_vote
redirect_to #post
elsif a == -1
comment.add_down_vote
redirect_to #post
else
redirect_to #post
end
end
routes.rb
Easyblog::Application.routes.draw do
authenticated :user do
root :to => 'home#index'
end
root :to => "home#index"
devise_for :users
resources :users
resources :posts do
resources :comments
member do
post :mark_archived
end
end
end
Im waiting for your help :)

What is a here? I guess it's vote direction
You have to remove argument a from vote action and pass direction via params for link path.
Fox example:
vote_comment_path(#comment.id, dir: 1) # or dir: -1
More than that there is no route for vote action. You can describe it like so:
resources :comments do
put :vote, as: :member
end
upd I would recommend you to read following guide http://guides.rubyonrails.org/routing.html
action in your path is not valid. You link should looks like
= link_to 'Yes', vote_comment_path(comment, dir: 1), method: :put
vote_comment_path can be different you could check it by rake routes command:
$ rake routes

Try changing like this
Easyblog::Application.routes.draw do
resources :posts do
resources :comments do
match :vote
end
member do
post :mark_archived
end
end
end

you could try something like this in youre routes
resources :posts do
resources :comments do
member do
post 'vote'
end
end
member do
post :mark_archived
end

No need to build your own voting system. Take a look at the voteable_mongo gem

Related

uninitialized constant Blog::PostsController

I'm getting the following error when I run my Rails app, "uninitialized constant Blog::PostsController"
routes.rb
Rails.application.routes.draw do
devise_for :authors
root to: 'blog/posts#index'
namespace :author do
resources :posts
end
scope module: 'blog' do
get 'about' => 'pages#about', as: :about
get 'contact' => 'pages#contact', as: :contact
get 'posts' => 'posts#index', as: :posts
get 'posts/:id' => 'posts#show', as: :post
end
end
posts.controller.rb
module Blog
class PostsController < BlogController
def index
#post = Post.most_recent
end
def show
#post = Post.friendly.find(params[:id])
end
private
def set_post
end
end
end
The directory path is as follows:
app/controller/blog/posts.controller.rb
I guess the problem is in Naming convention.
Here is example of naming convention:
Controller Naming Convention
Class: PostsController
File: /app/controllers/posts_controller.rb
For more detail on naming convention please check: http://www.ganeshkunwar.com.np/2018/01/02/naming-convention-rails/
Also inherit posts controller from application_controller not from blog controller.

How to set a like button in rails

Hello I have an exercise app where a user should be able to Like some products.
I could find a way to display the product he liked, but I really can't figure how to create and make work the like button.
I am not using any gem, I wan't to understand how to do it from Scratch.
Here are my models:
class User < ApplicationRecord
has_many :likes
has_many :liked_products, through: :likes, source: :product
end
class Product < ApplicationRecord
has_many :likes
end
class Like < ApplicationRecord
belongs_to :user
belongs_to :product
end
In my view product show where I want the like button:
<h1><%= #product.name %></h1>
<%= link_to "Like", product_likes_path(#product), method: :put, remote: true %>
my routes:
Rails.application.routes.draw do
root to: 'visitors#index'
devise_for :users
resources :users
resources :products do
resource :likes
end
end
That's my products controller, I think things must come in here but I don't know HOW!
class ProductsController < ApplicationController
before_action :find_product, only: :show
def index
#products = Product.all
end
def show
##product.like => gives an error 404
end
private
def find_product
#product = Product.find(params[:id])
end
end
I had created a likes controller but it seems it is not useful.... So... I gave up there...
class LikesController < ApplicationController
def new
#like = Like.new(like_params)
end
def create
#like = Like.new(like_params)
end
private
def like_params
params.require(:likes).permit(:user_id, :product_id)
end
end
I would really enjoy some light on this please :)
Finally found out how to set the controller
class LikesController < ApplicationController
def create
#user = current_user.id
#product = params[:product_id]
likes = {user_id: #user, product_id: #product}
#like = Like.new(likes)
#like.save!
if #like.save
redirect_to user_path(#user)
else
redirect_to product_path
end
end
end
the buttton
<%= link_to "Like", product_likes_path(#product), method: :post %>
routes
Rails.application.routes.draw do
root to: 'products#index'
devise_for :users
resources :users
resources :users do
resources :products do
resources :likes
end
end
end
You could try something along these lines:
Routes:
Rails.application.routes.draw do
root to: 'visitors#index'
devise_for :users
resources :users do
resources :products do
resources :likes
end
end
resources :products do
resource :likes
end
end
Which will give you something like:
... other routes ...
user_product_likes GET /users/:user_id/products/:product_id/likes(.:format) likes#index
POST /users/:user_id/products/:product_id/likes(.:format) likes#create
new_user_product_like GET /users/:user_id/products/:product_id/likes/new(.:format) likes#new
edit_user_product_like GET /users/:user_id/products/:product_id/likes/:id/edit(.:format) likes#edit
user_product_like GET /users/:user_id/products/:product_id/likes/:id(.:format) likes#show
PATCH /users/:user_id/products/:product_id/likes/:id(.:format) likes#update
PUT /users/:user_id/products/:product_id/likes/:id(.:format) likes#update
DELETE /users/:user_id/products/:product_id/likes/:id(.:format) likes#destroy
... other routes ...
Then:
<%= link_to "Like", user_product_likes_path(#user, #product), method: :post, remote: true %>
And in your LikesController:
class LikesController < ApplicationController
def new
#like = Like.new(like_params)
end
def create
#like = Like.new(like_params)
if #like.save
... do something happy
else
... do something sad
end
end
private
def like_params
params.require(:likes).permit(:user_id, :product_id)
end
end
Untested, so buyer beware. You might need to fiddle with your like_params and other stuff.

How to save a Boolean entry in a has_many through join Table

I need to define a method/action in my LessonsController that I can call from the lesson show action that marks the lesson as being completed by the current user. What does that controller method look like?
Here's the overview of my models:
User
has_many :completions
has_many :completed_steps, through: :completions, source: :lesson
Lesson
has_many :completions
has_many :completed_by, through: :completions, source: :user
Completions
belongs_to :user
belongs_to :lesson
My Completions Table looks like this:
t.integer "user_id"
t.integer "lesson_id"
t.boolean "completed_step"
t.string "completed_by"
I'm assuming in the LessonsController it looks like this
def complete_step
self.completions.create(completed_step: true, user_id: current_user.id)
end
Routes info:
Rails.application.routes.draw do
namespace :admin do
resources :users
resources :coupons
resources :lessons
resources :plans
resources :roles
resources :subscriptions
resources :completions
root to: "users#index"
end
devise_for :users, :controllers => { :registrations => "registrations"}
# Added by Koudoku.
mount Koudoku::Engine, at: 'koudoku'
scope module: 'koudoku' do
get 'pricing' => 'subscriptions#index', as: 'pricing'
end
resources :lessons do
member :complete
end
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
root 'pages#home'
get '/dashboard' => 'pages#dashboard', :as => 'dashboard'
mount StripeEvent::Engine, at: '/stripe-events' # prov
end
Here's my button link to make this functional.
<%= button_to "Mark this Lesson as Complete", complete_lesson_path(#lesson), method: :put, class: "btn btn-warning btn-lg" %>
Will this work or am I WAY off? Thanks!
Keep this is the LessonsController, but change it in either of the following ways:
def complete_step
current_user.completions.create(completed_step: true, lesson_id: #lesson.id)
end
# ~~ OR ~~
def complete_step
#lesson.completions.create(completed_step: true, user_id: current_user.id)
end
Both of these assume that you've already set #lesson in the controller, probably in a before_action :set_lesson.
EDIT:
If you need a route suggestion, then assuming you have resources :lessons in your routes file, you can either use an existing route (likely update) or add a member route like this:
resources :lessons do
get 'complete', on: :member
end
If you add a route, then you will need to add an action that looks like
def complete
complete_step
redirect #lesson
end
or similar, however you want to handle the response itself. You will also need to ensure that #lesson is set, so you should tweak your before_action :set_lesson, only: [:show, :update, ...] to also include :complete
Please try with below code.in your completion controller
def create
#lession = Lession.find(params[:lession_id])
#completion = current_user.completions.create(completed_step: true, lesson_id: #lesson.id)
redirected_to #completion
end
You can also just pass user: current_user to the completions.create method instead of passing in the current_user.id
Something like #lesson.completions.create(completed_step: true, user: current_user)

route or applogic

trying to get rails routing to "click" and just not getting it
have a project and a task model:
class Task
include Mongoid::Document
field :title, :type => String
has_many :projects
belongs_to :user
end
class Project
include Mongoid::Document
field :title, :type => String
has_and_belongs_to_many :tasks
belongs_to :user
end
I want to "associate" a task with a project
so I have this in the project controller:
def connect
#project = Project.find(params[:id])
#project.tasks_ids.push(params[:task_id])
#project.save
redirect_to project
end
with this route:
resources :projects do
match 'connect/:id' => 'projects#connect', :as => :connect, :via => :put
resources :tasks
end
I cant seem to get this to work in the view:
= link_to 'Associate Task', project_connect_path(#task)
fails with:
No route matches {:controller=>"projects", :action=>"connect"}
resources :projects do
member do
put :connect
end
resources :tasks
end
Your path should look like this:
= link_to 'Associate Task', project_connect_path(#project, :task_id => #task.id), :method => :put
Try to do this:
resources :projects do
member do
put 'connect'
end
resources :tasks
end
or you can write your route above the resources :projects do ...
and here is the link, you can read more about routes there: Rails routes

Rails 3 routing from root show

Currently
Project101::Application.routes.draw do
match '/:id' => 'companies#show'
resources :companies do
resources :customers
resources :users
resources :categories
resources :addresses
end
devise_for :users
resources :users, :controller => "users"
root :to => "companies#index"
end
Everything belongs to a company. Trying to create routes like www.example.com/:id/customers where :id is always the company id.
At the moment www.example.com/:id works but all url's are generated as /companies/:id/cusotmers.
Saw Rails 3 Routing Resources with Variable Namespace.
Is this the right way of doing this?
EDIT
Kept :as => :company to help generate the URL's, Links, etc a little easier for me. Sure others could do cleaner or better method. Also had to manually create the edit, destroy, new with different urls so I could use them in links if user was admin.
Project101::Application.routes.draw do
match '/' => 'companies#index'
match '/companies' => 'companies#index'
match '/:company_id' => 'companies#show', :as => :show_company
match '/companies/:id/edit' => 'companies#edit', :as => :edit_company
match '/companies/:id/new' => 'companies#new', :as => :new_company
match '/companies/:id/destroy' => 'companies#destroy', :as => :delete_company
scope '/:company_id', :as => :company do
resources :customers
resources :users
resources :categories
resources :services
resources :addresses
end
devise_for :users
resources :users, :controller => "users"
root :to => "companies#index"
end
Then just used basic nested_resources for links, controllers and forms.
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_company
def current_company
if params[:company_id] != nil
#current_company ||= Company.find(params[:company_id])
else
#current_company = nil
end
return #current_company
end
end
Basic links
<%= link_to "Customers", company_customers_path(current_company) %>
links for specific customer
<%= link_to #customer.name, edit_company_customer_path(current_company, #customer) %>
Controllers look like
class CustomersController < ApplicationController
before_filter :authenticate_user!
load_and_authorize_resource
def new
#company = current_company
#customer = #company.customers.new
end
def create
#customer = Customer.new(params[:customer])
if #customer.save
flash[:notice] = "Successfully created customer."
redirect_to company_customer_path(current_company, #customer)
else
render :action => 'new'
end
end
end
And finally my forms look like
<%= form_for [#company, #customer] do |f| %>
<%= f.error_messages %>
....
<% end %>
Yes, if you always want the routes to begin with the company id you can wrap them in a scope like this:
scope ":company_id" do
resources :customers
resources :users
resources :categories
resources :addresses
end

Resources