I'm setting up a in-app notification to show all the notifications that the user has however I am getting an can't find ID error. I am following this guide here https://www.youtube.com/watch?v=KOs8f8TnwZs.
I want to give notifications every time a Service Order gets a new Request associated with it.
Do you know what could be causing this?
I have tried going into my routes and adding something like this:
resources :service_orders do
resources :requests
end
But it didnt work, and it just made the requests route not work.
The code that I newly added is:
(#service_order.users.uniq - [current_user]).each do |user|
Notification.create(recipient: user, actor: current_user, action: "posted", notifiable: #request)
end
And thats whats causing the error, #service_order isn't being found for some weird reason.
My Request Controller is:
class RequestsController < ApplicationController
before_action :set_request, only: [:show, :edit, :update, :destroy]
before_action :old_request, only: [:show, :index, :update]
before_action :set_so
def index
if logged_in?(:site_admin)
#request = Request.all
elsif logged_in?(:itp_user)
#request = Request.pending.requests_by current_user
else
#request = Request.pending.so_user_request current_user.service_orders
end
end
def new
#request = Request.new
end
def create
#request = current_user.requests.new(request_params)
authorize #request
respond_to do |format|
if #request.save
(#service_order.users.uniq - [current_user]).each do |user|
Notification.create(recipient: user, actor: current_user, action: "posted", notifiable: #request)
end
format.html { redirect_to #service_order, notice: 'Your request has been sent' }
else
format.html { redirect_to #request, :flash => { :error => #request.errors.full_messages.join(', ') } }
end
end
end
def show
authorize #request
end
def edit
authorize #request
end
def update
authorize #request
if #request.update(request_params)
redirect_to requests_path, notice: 'Your request was created successfully'
else
render :edit
end
end
def destroy
authorize #request
#request.destroy
redirect_to requests_path, notice: 'Your request was deleted successfully'
end
private
def request_params
params.require(:request).permit(:available_date,
:message,
:charge_range,
:status,
:heading,
:service_order_id,
:user_id
)
end
def set_request
#request = Request.find(params[:id])
end
def old_request
Request.where('created_at <= :fifteen_days', fifteen_days: Time.now - 15.days).where(status: "pending").destroy_all
end
def set_so
#service_order = ServiceOrder.find(params[:service_order_id])
end
end
My routes.rb:
Rails.application.routes.draw do
resources :request_logs
namespace :admin do
resources :users
resources :issue_types
resources :requests
resources :service_orders
root to: "users#index"
end
resources :conversations do
resources :messages
end
resources :requests
devise_for :users, path: '', path_names: { sign_in: 'login', sign_out: 'logout', sign_up: 'register' }
resources :service_orders, except: [:show] do
member do
get :toggle_status
end
end
get 'user-landing', to: 'user_landing#index'
get 'service_order/:id', to: 'service_orders#show', as: 'service_order_show'
get 'contact', to: 'pages#contact'
root to: 'pages#home'
end
Request Form View:
<%= form_for :request, url: requests_path do |f| %>
<% if #request.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#request.errors.count, "error") %> prohibited this request from being sent:</h2>
<ul>
<% #request.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<h4>Subject:</h4>
<em><%= f.text_area :heading, class: "form-control" %></em>
</div>
<div class="form-group">
<h4>Message:</h4>
<em><%= f.text_area :message, class: "form-control" %></em>
</div>
<div class="form-group">
<h4>Issue Charge Range:</h4>
<em><%= f.number_field :charge_range, class: "form-control" %></em>
</div>
<div class="form-group">
<h4>Soonest Available Date:</h4>
<em><%= f.date_field :available_date, class: "form-control" %></em>
</div>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.hidden_field :service_order_id, :value => #service_orders.id %>
<div>
<%= f.submit 'Send Service Request', class: 'btn btn-primary btn-block' %>
</div>
<% end %>
To route to nested resources you should pass an array.
form_for( [#service_order, #request])
redirect_to([#service_order, #request])
# ... etc
This is equivalent to calling service_order_requests_path(service_order_id: #service_order.to_param). You can also use the shallow: true option to avoid nesting the member routes.
Related
I'm trying to make an app in Rails 5 for post answer to the task.
The Task content and the answer form in the same page.
When the user come into the task page, he can see the task content.
And he can post(create) an answer or edit the answer.
I get an error:
NoMethodError in Tasks#show
undefined method `to_key' for #
Did you mean? to_query
to_set
to_ary
What am I doing wrong?
What else information do you need that can help debug this issue?
I'd really apprieciate any help!
Models
```
# task.rb
class Task < ApplicationRecord
belongs_to :post
has_many :answers, dependent: :destroy
end
# answer.rb
class Answer < ApplicationRecord
belongs_to :task
belongs_to :user
end
```
routes.rb
```
resources :tasks, only: [:show] do
resources :answers #, only: [:new, :create, :edit, :update]
end
```
Controllers
```
# tasks_controller.rb
class TasksController < ApplicationController
before_action :authenticate_user!, only: [:show]
def show
#task = Task.find(params[:id])
#post = #task.post
if #task.answers.present?
#answer = Answer.where("task_id = ? and user_id = ?", #task.id, current_user.id)
else
#answer = Answer.new
end
end
end
# answers_controller.rb
def new
#task = Task.find(params[:task_id])
#answer = Answer.new
end
def create
#task = Task.find(params[:task_id])
#answer = Answer.new(answer_params)
#answer.task_id = #task.id
#answer.user_id = current_user.id
if #answer.save
redirect_to post_path(#task.post), notice: "Answer Added."
else
render :new
end
end
```
Views
```
<div class="answer-form">
<%= simple_form_for [#task, #answer], :url => task_answer_path(#task, #answer), method: :put do |f| %>
<% if #task.answers.present? %>
<%= f.input :content, id: "x", value: #task.answers.first.content,
input_html: {class: "hidden"}, name: "content", label: false %>
<trix-editor input="x" class="formatted_content trix-content"></trix-editor>
<div class="form-actions">
<%= f.submit "Submitting", class: "assignment-btn", data: {disable_with: "Submitting..."} %>
</div>
<% end %>
<% else %>
<%= simple_form_for [#task, #answer], :url => task_answers_path(#task), method: :post do |f| %>
<%= f.input :content, id: "x", value: "content",
input_html: {class: "hidden"}, name: "content", label: false %>
<trix-editor input="x" class="formatted_content trix-content"></trix-editor>
<div class="file-upload-block">
<input name="fileToUpload[]" id="fileToUpload" type="file">
</div>
<div class="form-actions">
<%= f.submit "提交", class: "assignment-btn", data: {disable_with: "Submitting..."} %>
</div>
<% end %>
<% end %>
</div>
```
I know what may be wrong, the line below was returning an ActiveRecord::Relation, not the instance itself, you need to append 'first' in the end of the answer query, like such:
#answer = Answer.where(task: #task, user: current_user).first
I made Forum model which belongs to Category and in show view of every category each forum from that category needs to be showed, but links are pointing at wrong paths (for example, in category 4 I have only one forum which points to category/1/forum/1 and category 1 doesn't even exist).
One more note: each category has it's position field (integer) and they're sorted with that field in ascending order. Category 4 have position 1, but why would that number be on the place of category id in url?
When I try to access /category/4/forum/1 I get the error "Couldn't find Category with 'id'=1"
CategoriesController
class CategoriesController < ApplicationController
def index
categories_ordered
end
def new
#category = Category.new
categories_ordered
end
def create
#category = Category.new(category_params)
categories_ordered
if #category.save
redirect_to forums_path, notice: "Kategorija je uspešno kreirana."
else
render "new"
end
end
def show
find_category
find_forums
end
def edit
find_category
end
def update
find_category
if #category.update(category_params)
redirect_to category_path(#category), notice: "Kategorija je uspešno ažurirana."
else
render "edit"
end
end
def destroy
find_category
#category.destroy
redirect_to forums_path, notice: "Kategorija je uspešno obrisana."
end
private
def category_params
params.require(:category).permit(:name, :description, :position)
end
def find_category
#category = Category.find(params[:id])
end
def find_forums
#forums = #category.forums.all
end
def categories_ordered
#categories = Category.all.order("position ASC")
end
end
ForumsController
class ForumsController < ApplicationController
def new
find_category
#forum = #category.forums.new
end
def create
#category = Category.find(params[:category_id])
#forum = #category.forums.create(forum_params)
if #forum.save
redirect_to category_path(#category), notice: "Forum je uspešno kreiran."
else
render "new"
end
end
def show
find_category
find_forum
end
def edit
find_category
find_forum
end
def update
find_category
find_forum
if #forum.update(forum_params)
redirect_to forum_path(#forum), notice: "Forum je uspešno ažuriran."
else
render "edit"
end
end
private
def forum_params
params.require(:forum).permit(:title, :description)
end
def find_category
#category = Category.find(params[:category_id])
end
def find_forum
#forum = #category.forums.find(params[:id])
end
end
categories#show
<% authorize %>
<h2><%= #category.name %></h2>
<p><%= #category.description %></p>
<div class="list-group">
<% #category.forums.each do |f| %>
<a href="<%= forum_path(f) %>" class="list-group-item">
<h4 class="list-group-heading"><%= f.title %></h4>
<p class="list-group-text">
<%= f.description %>
</p>
</a>
<% end %>
</div>
<% if is_admin? %>
<%= link_to new_forum_path, class: "btn btn-primary" do %>
<span class="glyphicon glyphicon-plus"></span> Dodaj forum
<% end %>
<%= link_to edit_category_path(#category), class: "btn btn-primary" do %>
<span class="glyphicon glyphicon-pencil"></span> Izmeni
<% end %>
<%= link_to category_path(#category), class: "btn btn-danger", method: :delete, data: { confirm: "Da li ste sigurni da želite obrisati ovu kategoriju?" } do %>
<span class="glyphicon glyphicon-trash"></span> Obriši
<% end %>
<% end %>
routes.rb
Rails.application.routes.draw do
root "welcome#index"
get "start" => "welcome#index", as: "index"
get "registration" => "users#new", as: "register"
get "login" => "sessions#new", as: "login"
post "login" => "sessions#create"
get "logout" => "sessions#destroy", as: "logout"
get "users" => "users#index", as: "users"
post "users" => "users#create"
get "profile" => "users#show", as: "profile"
get "user/:id" => "users#show", as: "user"
get "user/:id/edit" => "users#edit", as: "edit_user"
patch "user/:id" => "users#update"
delete "user/:id" => "users#destroy"
get "categories/add" => "categories#new", as: "new_category"
get "category/:id" => "categories#show", as: "category"
patch "category/:id" => "categories#update"
delete "category/:id" => "categories#destroy"
get "category/:id/edit" => "categories#edit", as: "edit_category"
get "terms" => "welcome#terms", as: "terms"
get "wh" => "bugs#new", as: "wh"
get "bugs" => "bugs#index", as: "bugs"
post "bugs" => "bugs#create"
get "bug/:id" => "bugs#show", as: "bug"
delete "bug/:id" => "bugs#destroy"
get "forum" => "categories#index", as: "forums"
get "category/:category_id/forum/add" => "forums#new", as: "new_forum"
get "category/:category_id/forum/:id" => "forums#show", as: "forum"
get "category/:category_id/forum/:id/edit" => "forums#edit", as: "edit_forum"
patch "category/:category_id/forum/:id" => "forums#update"
delete "category/:category_id/forum/:id" => "forums#destroy"
resources :users
resources :sessions
resources :categories do
resources :forums
end
resources :bugs
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
Error is partially solved; I just had to use different parameters with ForumsController (category_id for categories and id for forums).
def find_category
#category = Category.find(params[:category_id])
end
def find_forum
#forum = #category.forum.find(params[:id])
end
And change forum routes accordingly.
It looks like problem still isn't solved. I changed this parts but I still have problems with URLs. Now category and forums IDs are mixed in url (instead of /category/4/forum/1 it shows /category/1/forum/4).
Edit: Problem is finally solved! This answer gave me an idea what I should do. I just had to specify #category with paths too (just changing two lines):
<div class="list-group">
<% #category.forums.each do |f| %>
<a href="<%= forum_path(#category, f) %>" class="list-group-item">
<h4 class="list-group-heading"><%= f.title %></h4>
<p class="list-group-text">
<%= f.description %>
</p>
</a>
<% end %>
</div>
<% if is_admin? %>
<%= link_to new_forum_path(#category), class: "btn btn-primary" do %>
<span class="glyphicon glyphicon-plus"></span> Dodaj forum
<% end %>
I am trying to access an "edit" link to edit an object, but I'm getting this error:
Param is missing or the value is empty: preview
Basically, I have 2 models that I linked through association:
Game model
Review model
I'm rendering reviews in the Game's show page. When I try to edit a review, it's saying I'm missing params or the value is empty in the Reviews controller.
The routes are also nested. How can I fix this?
Thanks in advance :)
routes.rb
Rails.application.routes.draw do
devise_for :users
root "games#index"
resources :games do
resources :news
resources :reviews, except: [:show, :index]
resources :previews, except: [:show, :index]
end
resources :platforms
resources :genres
end
show.html.erb (Linked to Games controller)
<% if #news.last.created_at > preview.updated_at %>
<p><%= link_to "edit", edit_game_preview_path(#game.id, preview.id) %></p>
<% end %>
<p><%= link_to "delete", game_preview_path(#game.id, preview.id), method: :delete %></p>
<% end %>
Reviews partial (Form)
<%= form_for [#game, #previews.new] do |r| %>
<h3 class="post_review">Preview this game</h3>
<p><%= flash[:notice_submit] %></p>
<p><%= r.text_field :title, placeholder: "Enter your tagline" %></p>
<p><%= r.text_area :content, placeholder: "Enter your review here" %></p>
<p><%= r.text_area :vote %></p>
<p><%= r.hidden_field :game_id, value: #game.id %></p>
<%= r.submit %>
<% end %>
Reviews controller
class PreviewsController < ApplicationController
before_action :authenticate_user!
before_action :set_preview, only: [:show, :edit, :update, :destroy]
before_action :set_game
def new
#preview = Preview.new
end
def create
#preview = Preview.new(preview_params)
#preview.user_id = current_user.id
#preview.game_id = #game.id
#preview.username = current_user.username
if #preview.save
redirect_to :back
flash[:notice_submit] = "Thanks for you comment!"
else
redirect_to :back
flash[:notice_submit] = "Either you've already voted, or you're not filling in all forms."
end
end
def edit
#preview.update(preview_params)
redirect_to #game
end
def destroy
#preview.destroy
redirect_to #game
end
private
def set_preview
#preview = Preview.find(params[:id])
end
def set_game
#game = Game.find(params[:game_id])
end
def set_user
#user = User.find(params[:user_id])
end
def preview_params
params.require(:preview).permit(:title, :content, :vote)
end
end
You are getting this error because in your preview_params you are requiring a preview object.
I think your controller logic for the edit action is invalid. For the edit action, you just need to set_preview and then render the edit template. The current logic in your edit action should go in an update action.
def edit
end
def update
#preview.update(preview_params)
redirect_to #game
end
Also the first line of your form should be:
<%= form_for [#game, #preview] do |r| %>
I've created nested routes for a model called Userfolder. The routes are mapped like this:
userfolder_userfolders POST /userfolders/:userfolder_id/userfolders(.:format) userfolders#create
new_userfolder_userfolder GET /userfolders/:userfolder_id/userfolders/new(.:format) userfolders#new
Which is exactly the way I want it. But when I create a new Userfolder, Rails is redirecting the create action to "/userfolders" and not "/userfolders/:userfolder_id/userfolders". It is still following the initial Rails scaffolding routes.
Is there a way to change this? Or have I missed out on something entirely?
EDIT 1: Here is my Userfolder controller code.
class UserfoldersController < ApplicationController
before_action :set_userfolder, only: [:show, :edit, :update, :destroy]
before_action :set_parentfolder, except: [:show, :edit, :update, :destroy, :index]
# GET /userfolders
# GET /userfolders.json
def index
if Userfolder.first.nil?
Userfolder.create(:name => 'root', :parent_id => 0)
end
redirect_to Userfolder.first
end
# GET /userfolders/1
# GET /userfolders/1.json
def show
end
# GET /userfolders/:userfolder_id/userfolders/new(.:format)
def new
#userfolder = #parentfolder.children.build
end
# GET /userfolders/1/edit
def edit
end
# POST /userfolders/:userfolder_id/userfolders
def create
#userfolder = #parentfolder.children.build(userfolder_params)
respond_to do |format|
if #userfolder.save
format.html { redirect_to userfolder_path(#parentfolder.id), notice: 'Userfolder was successfully created.' }
else
render :action => 'new'
end
end
end
# PATCH/PUT /userfolders/1
# PATCH/PUT /userfolders/1.json
def update
respond_to do |format|
if #userfolder.update(userfolder_params)
format.html { redirect_to #userfolder, notice: 'Userfolder was successfully updated.' }
else
render :action => 'edit'
end
end
end
# DELETE /userfolders/1
# DELETE /userfolders/1.json
def destroy
parent_folder = #userfolder.parent
#userfolder.destroy
respond_to do |format|
format.html { redirect_to parent_folder, notice: 'Userfolder was successfully destroyed.' }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_userfolder
#userfolder = Userfolder.find(params[:id])
end
def set_parentfolder
#parentfolder = Userfolder.find(params[:userfolder_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def userfolder_params
params.require(:userfolder).permit(:name, :parent_id)
end
end
This is my routes.rb file:
Rails.application.routes.draw do
resources :userfiles
# 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 'userfolders#index'
resources :userfolders, :shallow => true, :except => [:new, :create] do
resources :userfolders, :only => [:new, :create]
end
EDIT 2:
This is the console output:
So the issue was with the _form.html.erb like I suspected.
This is the create controller:
def create
#userfolder = #parentfolder.children.build(userfolder_params)
respond_to do |format|
if #userfolder.save
format.html { redirect_to #parentfolder, notice: 'Userfolder was successfully created.' }
else
render :action => 'new'
end
end
end
And here is the _form.html.erb:
<%= form_for([#parentfolder, #userfolder]) do |f| %>
<% if #userfolder.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#userfolder.errors.count, "error") %> prohibited this userfolder from being saved:</h2>
<ul>
<% #userfolder.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :parent_id %><br>
<%= f.number_field :parent_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
By adding the <%= form_for([#parentfolder, #userfolder]) do |f| %>, I'm telling Rails to redirect to /userfolders/:userfolder_id/userfolders. Instead of redirecting to /userfolders.
I am having trouble setting the user_id on the creation of a post
def create
#post = Post.new(post_params)
#post.user_id = session[:id]
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: 'new' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
The error I get is specifically undefined method 'username' for nil:NilClass when redirected to the show action. A look at the database shows that no user_id is set.
I also tried passing the user_id as a hidden field. but this did not work either (a look at the logs showed the hidden field wasn't even being passed for some reason).
Would appreciate a point in the right direction,
Thank you !
EDIT: as requested here is the show controller
def show
#post = Post.find(params[:id])
#original_id = params[:original_id]
#comment = Comment.new
end
<%= form_for [:admin, #post] do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Below is the form
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :content %><br>
<%= f.text_area :content %>
</div>
<div class="field">
<%= f.label :category %><br>
<%= f.text_field :category %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Routes:
root 'posts#index'
resources :posts do
resources :comments, shallow: true
end
resources :users, only: [:create]
#Posts
get "/meta", to: "posts#meta"
#User Routes
get "/signup", to: "users#new"
get "/success", to: "users#index"
#login Routes
get "/login", to: "sessions#login"
post "/sessions/login_attempt", to: "sessions#login_attempt"
#session routes
get "/sessions/home", to: "sessions#home"
get "/sessions/logout", to: "sessions#logout"
#admin routes
#resources :posts, module: 'admin', except: [:show, :index]
namespace :admin do
root 'posts#new'
resources :posts, except: [:show, :index]
end
Inside of your create method add
#post = Post.build(params[:post])
#post.user_id = current_user.id
This will grab the current user id for the given post.
If you have a has_many relationship between posts and users, why not do something like this:
#user = User.find(params[:id])
#post = #user.posts.new(params[:post])
The params might be different but this is the 'more ruby' way do do things. It explicitly notes the relationships between the two models. The above code should be in the #new action and then you would save it within the create action.
I feel like an idiot now but the issue was I was using session[:id] as opposed to session[:user_id]
Set in my sessions controller
def login_attempt
authorized_user = RegisteredUser.authenticate(params[:username_or_email],params[:login_password])
if authorized_user
session[:user_id] = authorized_user.id
flash[:notice] = "Wow Welcome again, you logged in as #{authorized_user.username}"
redirect_to(:action => 'index', :controller => "users")
else
flash[:notice] = "Invalid Username or Password"
flash[:color]= "invalid"
render "login"
end
end