undefined method `post_up_vote_path' - ruby-on-rails

I am trying to come up with upvote/downvote method in my app and I running into a no method error.
Here is my voter form:
<div>
<div class= 'pull-left'>
<div><%= link_to " ", post_up_vote_path(post), class: 'glyphicon plyphicon-chevron-up', method: :post %></div>
<div><strong><%= post.points %></strong></div>
<div><%= link_to " ", post_down_vote_path(post), class: 'glyphicon plyphicon-chevron-up', method: :post %></div>
</div>
Here are my routes:
App::Application.routes.draw do
devise_for :users
resources :users
resources :topics do
resources :posts, except: [:index] do
resources :comments, only: [:create, :destroy]
post '/up-vote' => 'votes#post_up_vote', as: :up_vote
post '/down-vote' => 'votes#post_down_vote', as: :down_vote
end
end
get 'about' => 'welcome#about'
root to: 'welcome#index'
end
And here is my partial call:
<%= render partial: 'votes/voter', locals: { post: post } %>
Now I don't think there is anything wrong with my partial call or my voter partial because everything works until I try to route it.

First, you will need to change up your routes a bit.
resources :posts, except: [:index] do
resources :comments, only: [:create, :destroy]
post 'upvote', on: :member
post 'downvote', on: :member
end
The reason these are member routes instead of collection routes is being they apply to a specific member of the collection of posts...a single Post.
Then, you will want to run the command, rake routes in your Terminal to see what the appropriate path methods are. It should be something like
upvote_post_path(:id)
which requires an object be passed in..so in your view you would use it like you currently are.
upvote_post_path(post)

Related

Rails custom action not working due to show, how to fix?

I'm trying to create a customer action in my campaigns controller called building.
http://localhost:3000/campaigns/building
Shows error:
Showing .../app/views/campaigns/show.html.erb where line #1 raised:
undefined method `name' for nil:NilClass
<h2><%= #campaign.name %></h2>
<p>
Created by: <%= #campaign.user.email %> <%= time_ago_in_words(#campaign.created_at) %> ago.
</p>
<h5>Website: <%= #campaign.website %></h5>
My routes file:
resources :campaigns do
resources :targets
end
get "campaigns/building" => "campaigns#building", :as => :campaigns_building
Controller:
class CampaignsController < ApplicationController
before_action :find_campaign, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def show
end
def building
end
...
My show.html.erb:
<h2><%= #campaign.name %></h2>
<p>
Created by: <%= #campaign.user.email %> <%= time_ago_in_words(#campaign.created_at) %> ago.
</p>
<h5>Website: <%= #campaign.website %></h5>
How do I make it not give this error?
It seems you are trying to make a custom route and unable to make it work. If so, to make it work, you should move your custom route above resources to avoid conflicts with the default resourceful route and correctly route to building action
get "campaigns/building" => "campaigns#building", :as => :campaigns_building
resources :campaigns do
resources :targets
end
This is because Rails tries to match routes starting from the top down. You can also define it as a collection route on the resources
resources :campaigns do
get "building", on: :collection
resources :targets
end

How to Create an Instance of Model A, from a Form inside a view for Model B

So I have a Message model, and a ChatRoom model.
When I display a chat room, I use the show action on the ChatRoom controller. In the view for this action, there is a little form for the user to create a post, and submit that post to the chat room being shown.
When I run my tests, however, I get an error "no route matches [POST] /messages/an_id_of_some_sort". Specifically, in this little test:
post message_path, params: {message: {body: "yo ho ho and a bottle of rum!"}}
assert_redirected_to chat_room_path(#channel)
the error pops up in the post message_path.
The show method on the chat room controller looks like
def show
if(#user = current_user)
#chats = #user.chat_rooms
#chosen = ChatRoom.find_by(id: params[:id])
if(#chosen.messages.any?)
#messages = #chosen.messages
else
#messages = nil
end
#message = Message.new
end
end
Then the little form bit of the view is:
<div class="message-input">
<%= form_for(#message) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.text_area :body, placeholder: "Write Message..." %>
<%= f.hidden_field :room, :value => params[:room] %>
<%= button_tag(type: "submit", class: "message-submit-btn", name: "commit", value: "") do %>
<span class="glyphicon glyphicon-menu-right"></span>
<% end %>
<% end %>
</div>
I have a create action on the Messages Controller which does the saving to the database:
#message = current_user.messages.build(message_params);
#message.chat_room = params[:room]
if #message.save
redirect_to chat_room_path(#message.chat_room)
end
and routing-wise I have
Rails.application.routes.draw do
root 'welcome#welcome'
get '/login', to: 'sessions#new'
post '/login', to: 'sessions#create'
delete '/logout', to: 'sessions#destroy'
get '/signup', to: 'users#new'
post '/signup', to: 'users#create'
get 'users/signup_success'
delete '/chat_rooms/leave/:id', to: 'chat_rooms#leave', as: 'current'
get 'welcome/welcome'
resources :users
resources :account_activations, only: [:edit] #Only providing an Edit route for this resource.
resources :password_resets, only: [:new, :edit, :create, :update]
resources :chat_rooms, only: [:new, :create, :show, :index]
resources :messages, only: [:create, :edit, :destroy]
end
I have tried playing around with explicitly setting the :url on the form_for, but no dice. There is another question on this problem, but the solution there hasn't really helped.
I would greatly appreciate any help.
With this line you're running POST /messages/:id
post message_path, params: {message: {body: "yo ho ho and a bottle of rum!"}}
In your routes file you have this:
resources :messages, only: [:create, :edit, :destroy]
This will create the routes POST /messages, PUT/PATCH /messages/:id, and DELETE /messages/:id. You can verify this with rake routes.
None of these generated routes handle POST /messages/:id.
If you're trying to have the test create a new message, then you can use messages_path instead. message_path (with singular message) takes a message argument as a message, e.g. message_path(Message.first) and uses that to build the url.

No route matches {:action=>"show", :controller=>"report"

I have a report#show view which I would to link_to, but I'm unsure about how to set up the routing.
In my packages#show view:
<% link_to 'Report', package_report_path(#package) %>
Here's my routes.rb:
Rails.application.routes.draw do
devise_for :users
resources :packages do
resources :sales, only: [:new]
resources :report, only: [:show]
end
root "packages#index"
end
If I do rake routes:
package_report GET /packages/:package_id/report/:id(.:format) report#show
The route is set up correct, but you need to pass both #package and #report to the package_report_path, like:
<% link_to 'Report', package_report_path(#package, #report) %>
Your report resource is nested under the package resource. So, you have to pass both #package and #report to the package_report_path helper method:
<% link_to 'Report', package_report_path(#package, #report) %>

No route matches [PUT] but I included "resources" in routes.rb

I'm coding a blog that has two types of articles: "drafts" and "published". I'm using the aasm gem for making the article transition from draft to published or viceverza. There are also three types of users: "regular readers", "editors" and "admins".
As users write articles, admins can evaluate whether to publish them or not. To accomplish this, admins have a view in which they can see both drafts and published articles.
The problem is that when I try to publish the articles I get the No route matches [PUT] "/articles" error, regardless I've added resources :articles in routes.rb.
The code I wrote is the following:
routes.rb
resources :categories
resources :articles do
resources :comments, only: [:create, :update, :destroy, :show]
end
devise_for :users
root 'welcome#index'
get '/dashboard', to: 'welcome#dashboard'
put '/articles/:id/publish', to: 'articles#publish'
articles_controller.rb
...
def publish
#article.publish! # Article transition from draft to published.
redirect_to #article
end
...
dashboard.html.erb
...
<% #articles.each do |art| %>
<h1><%= link_to art.title, art, method: :get %> | id = <%= art.id %> | user_id = <%= art.user_id %></h1>
<div>
<%= art.body %> - <%= link_to "Eliminar", art, method: :delete %>
<% if art.may_publish? %>
- <%= link_to "Publicar", '/articles/#{article.id}/publish' , method: :put %>
<% end %>
</div>
<% end %>
...
I can't see why I get this error if I included the article resource. If you need me to include more code don't hesitate to ask me.
Thanks in advanced.
You should remove your custom routes and put it into resources :articles like this :
routes.rb
resources :articles do
put 'publish', on: :member
resources :comments, only: [:create, :update, :destroy, :show]
end
and you should use this in your view :
<%= button_to "Publicar", publish_article_path(article), method: :put %>
It will generate a form.
The code seems to be correct, so try to reset the server and, by the way, restart the browser. It usually solves strange problems like this :) Let me know if it worked.

Couldnt Find Id="your_question"

My error says that:
Couldn't find Question with 'id'=your_questions"
and
ActiveRecord::RecordNotFound in QuestionsController#show
What should I do to fix it?
def show
#question = Question.find(params[:id])
#answer = Answer.new
end
on the second line it says where the error is.
Edit:
The Index View File
<%= form_for(#question) do |f| %>
<%= render 'common/form_errors', object: #question %>
<p>
<%= f.label :body, "Question" %><br />
<%= f.text_field :body %>
<%= f.submit "Ask a Question" %>
</p>
<% end %>
Rails.application.routes.draw do
get "/" => "main_app#index"
get "/location" => "location#location"
post "/location/index" => "location#index"
get "/location/index" => "location#index"
get "/location/directions" => "location#directions"
root to: 'questions#index'
get '/logout', to: 'sessions#destroy', via: :delete
resources :users, only: [:new, :create]
resources :sessions, only: [:new, :create]
resources :questions, except: [:new] do
resources :answers, only: [:create]
end
get '/register', to: 'users#new'
get '/login', to: 'sessions#new'
get '/logout', to: 'sessions#destroy', via: :delete
get '/questions/:id', to: 'questions#your_questions'
get '/search', to: 'questions#search'
You mention you have this route:
get '/questions/your_questions', to: 'questions#your_questions
If you also have a route like following the restful style, you should also have something like:
get 'questions/:id', to: 'questions#your_questions'
Or a resource call. Anyway, so Rails is actually trying to access your show action passing "your_questions" as the id for the route. Write this route like this:
get '/questions/:id', to: 'questions#show
This means: "If a request using the GET HTTP method follows the url 'questions/:id', then go to controller: questions and its action(method in the controller) called: your_questions" and pass into the params hash the value of id as in the URL.

Resources