How to add comments to a specific post? - ruby-on-rails

I am very new to rails and I don't know much about where my problem lies. Just started a few days ago and right now I am trying to add comments to a specific post. Well, technically these are not comments but more of logs added to a certain request when other people have interacted with the request like Request A has log B, log C, log D so its basically the same as a comment sytem.
I already can create the logs and display them but my main problem is showing the right logs for the right request. My logs already have the correct request id but I don't know how to get the specific logs to display for the specific request
This is my historys_controller.rb
class HistorysController < ActionController::Base
before_action :require_login
def index
#historys = History.where(job_order: 1)
end
def require_login
unless session['user_credentials_id']
redirect_to '/'
end
end
end
It is still set as 1 as a temporary placeholder and trying something like
History.where(job_order: #job_order.id)
and
History.where(job_order: params [:id])
does not work so what should I put there?
EDIT
history.rb
class History < ApplicationRecord
belongs_to :job_order, polymorphic: true
belongs_to :actor, class_name: "User"
end
routes.rb
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'user_sessions#new'
get '/sign_in', to: 'user_sessions#new', as: :sign_in
get '/signup' => 'users#signup', as: 'signup_user'
delete '/sign_out', to: 'user_sessions#destroy', as: :sign_out
post '/register' => 'users#register', as: 'register_user'
get '/users/activate/:id' => 'users#activate', as: 'activate_user'
get '/users/deactivate/:id' => 'users#deactivate', as: 'deactivate_user'
get '/job_order_tracking_system' => 'job_orders#dashboard', as: 'job_order_tracking_system'
get '/job_orders/approve_job_order/:id' => 'job_orders#approve_job_order', as: 'approve_job_order'
get '/job_orders/reject_job_order/:id' => 'job_orders#reject_job_order', as: 'reject_job_order'
get '/job_orders/start_job_order/:id' => 'job_orders#start_job_order', as: 'start_job_order'
get '/job_orders/done_job_order/:id' => 'job_orders#done_job_order', as: 'done_job_order'
get '/job_orders/cancel_job_order/:id' => 'job_orders#cancel_job_order', as: 'cancel_job_order'
resources :job_orders do
resources :historys
end
resources :users
resources :offices
resources :user_sessions, only: [:create, :destroy]
resources :notifications do
collection do
post :mark_as_read
end
end
# resources :historys
end

you want the histories for a specific job order?
Do
class JobOrder < ApplicationRecord
has_many :histories
end
Then you can get all the related histories with
#job_order.histories
And in your view you can do somthing like...
<% #job_order.histories.each do |history| %>
<%= history.name %>
<%= history.comment %>
<br/>
<% end %>
Incidentally, use the correct spelling for the plural of "history"... your controller should be HistoriesController Rails is smarter than you realise.

I also noticed you've got some spacing between params and [:id]. It should look this way: params[:id].

Related

Rails - no method error for new form

I'm sure that there is a simple solution to this problem, but I can't for the life of me see what I am doing wrong - it's been a few months since I've worked on a Rails project, I must be forgetting something important.
I'm just trying to create a basic Rails form, but I am getting a no method path error when I navigate to the new form page.
This is for my Report model...
routes.rb
resources :report, only: [:new, :create], path_names: {new: ''}
report_controller.rb
def new
#report = Report.new
end
report/new.html.erb
<%= form_for #report do |f| %>
<% end %>
Navigating to http://localhost:3000/report yields
undefined method `reports_path'
Just to be comprehensive, here's the model...
class Report < ActiveRecord::Base
belongs_to :user
belongs_to :weather
belongs_to :feature
end
and the routes
report_index POST /report(.:format) report#create
new_report GET /report(.:format) report#new
I'm sure this is an amateur mistake... but I can't see what it is!
You need to change your routes to include a :show path if you want to be able to go to /report.
The path that I believe you are looking for is localhost:3000/reports/new
Oh for the love of god. It was a pluralization issue. The files should appear and be named as follows:
routes.rb
resources :reports, only: [:new, :create], path_names: {new: ''}
reports_controller.rb
class ReportsController < ApplicationController
def new
#report = Report.new
end
end
And the view files should all be in a folder called 'reports', not 'report'. The model is just the singular report.rb.

rails custom rest route with parameter

I have a questions controller and an associated model and a number of rest routes. Here is how it's set up in routes.rb:
resources :questions
I want to add a custom route that has the format /questions/widget/ID (where ID is the id of the question for which I want to generate a widget). I want this to be processed by the "widget" action in my questions controller. I've tried a number of things such as:
resources :questions do
member do
get 'widget/:id'
end
end
But nothing is working. I'm sure I'm missing something simple. Any ideas? Thanks in advance.
You do not have to specify the id since you are inside resources. It should look like:
resources :questions do
member do
get 'widget'
end
end
You can get more information from the Rails Guide. Look at section 2.9.1.
Edit: I just noticed that you are trying to match get /questions/widget/:id. This will set up a route for get /questions/:id/widget. This is more in line with Rails convention. If you really want it the other way, you need to set up a custom match statement:
match "/questions/widget/:id" => "questions#widget"
However, I would stick with convention.
I know it is old, but looking to fix another routing problem I ended here, it is possible, to do what you are asking for, here is an example
resources :articles do
get 'by_tag/:tag' => :by_tag, on: :collection
get 'by_author/:author' => :by_author, on: :collection
resources :comments, except: :show
end
now you have /artices/by_tag/:tag . The trick was to use on:collection.
Obviously don't forget to add the by_tag action and by_author.
class ArticlesController < ApplicationController
.....
def by_tag
...
end
end
Check this route works with
melardev#local~$ rails routes
Why don't you use this routes:
resources :questions do
resources :widgets
end
it will create path like questions/:question_id/widgets/new for you to create new widget for question with specific id of question.
This is what ended up working for me:
resources :post do
get "author/:author", to: "posts#author", on: :collection, as: "author"
end
Which outputs the following route:
author_posts GET /posts/author/:author(.:format) posts#author
Then in your controller, you need to create the author action:
class PostsController < ApplicationController
def author
#roles = Post.where(author: params[:author])
render :index # to reuse the index view
end
end
Then in your view:
<%= link_to post.author, author_posts_path(post.author), data: { turbo_frame: "_top" } %>

Rails: Point several nested routes to one customer controller action

How do you point different nested routes to one controller action?
A user can be a member of several groups like company, project, group ect. for which It can request to join, leave or be removed by an admin.
I want to access the remove action for several models and destroy the belongs_to record in the profile model
I already have a polymorphic model that takes requests from a profile to a model( e.g. company) and upon acceptance of the request the profile will belong to the model. once the request is accepted the request recored is destroyed. I feel that the remove action that will destroy the relationship between the profile and the model should be part of the requests_controller, but I guess could be part of the profile_controller.
What I'm thinking I need to end up with is either
/_model_/:id/profile/:id/remove
/company/:id/profile/:id/remove
but how do I get this to point the remove action in my requests controller
or
/_model_/:id/requests/remove
/company/:id/request/remove
I am using the following code in my routes
resources :companies do
resource :requests do
put 'remove', :on => :member
end
resources :requests do
put 'accept', :on => :member
end
end
This is producing a double up of the routes
remove_company_requests PUT /companies/:company_id/requests/remove(.:format)
company_requests POST /companies/:company_id/requests(.:format)
new_company_requests GET /companies/:company_id/requests/new(.:format)
edit_company_requests GET /companies/:company_id/requests/edit(.:format)
GET /companies/:company_id/requests(.:format)
PUT /companies/:company_id/requests(.:format)
DELETE /companies/:company_id/requests(.:format)
accept_company_request PUT /companies/:company_id/requests/:id/accept(.:format)
GET /companies/:company_id/requests(.:format)
POST /companies/:company_id/requests(.:format)
new_company_request GET /companies/:company_id/requests/new(.:format)
edit_company_request GET /companies/:company_id/requests/:id/edit(.:format)
company_request GET /companies/:company_id/requests/:id(.:format)
PUT /companies/:company_id/requests/:id(.:format)
DELETE /companies/:company_id/requests/:id(.:format)
As
My I suggest that you create a new controller to handle this? The advantage is that you can map the route to this controller on any models you want the "remove association" on.
For example:
# RemoveController.rb
class RemoveController < ApplicationController
def destroy
# inplement the logic for deletion. You can use refection to implement
# this function only once for all the applied associations.
end
end
# routes.rb
resources :companies do
resource :requests do
resource :remove, :controller => :remove, :only => [:destroy]
end
end
The above routes would generate:
company_requests_remove DELETE /companies/:company_id/requests/remove(.:format) remove#destroy
You can nest the above line for the remove controller on any nested routes you want and they will all point back to the RemoteController's destroy object, only with different parameters to help you implement the destroy action.
Edit: to add create for specific relationship that you don't want to duplicate you can do this:
# routes.rb
resources :companies do
resource :requests do
resource :remove, :controller => :relationship, :only => [:destroy]
resource :create, :controller => :relationship, :only => [:create]
end
end
company_requests_remove DELETE /companies/:company_id/requests/remove(.:format) relationship#destroy
company_requests_create POST /companies/:company_id/requests/create(.:format) relationship#create
But I think you might need to be careful about breaking the convention of create in the respective controller. I'm not sure if there are any downside to this. The remove part since is only removing association and not the records itself, it doesn't seem to break the convention.
Try
puts 'remove', :on => :member, :controller => :requests, :action => :remove

How to route to different actions depending on the request method in Rails?

As we all know, a simple
resources :meetings
will generate 7 actions for me. Two of these are index and create. A really cool thing about these two!: The URL for both is /meetings, but when I GET /meetings I am routed to the def index action and when I POST /meetings, I am routed to the def create action. Nice.
Now I want to do this:
resources :meetings do
member do
get 'scores'
post 'scores'
end
end
And, you guessed it!, I want them to route to different actions in MeetingsController: GETting /meetings/1/scores will route to def scores and POSTing to meetings/1/scores will route to def create_scores.
Try:
resources :meetings do
member do
get 'scores' => :scores
post 'scores' => :create_scores
end
end
I suppose you will be also interested in having named routes:
resources :meetings do
member do
get 'scores' => :scores, :as => 'scores_of'
post 'scores' => :create_scores, :as => 'create_scores_of'
end
end
Then you get scores_of_meeting_path and create_scores_of_meeting_path helpers.
Above may be DRYed more with:
get :scores, :as => 'scores_of'
Define the routes such as this:
resources :meetings do
member do
get 'scores', :action => "scores"
post 'scores', :action => "post_scores"
end
end
But it sounds to me like it would be much easier to create another controller to handle this, as scores to me feels like another resource entirely, even if they don't have their own model association.
Ha! Never underestimate the ability of asking a question well to lead you to its answer.
resources :meetings do
member do
get 'scores', :to => "meetings#scores"
post 'scores', :to => "meetings#create_scores"
end
end

Routing and nested resources

I have a set of nested resources -- :users and :messages.
resources :users, :only => [:show,:index] do
resources :messages
end
And also a formtastic form in the "new.html.haml" template for the Message model and it needs to use these resources:
=semantic_form_for [#user,#message] do |f|
=f.input :title
The problem is in the actual action path that is generated from [#user,#message], and it looks like this:
/users/4cdc7f9dfae434029a0000aa/messages
This is wrong because I am using a named route, so this should look like "/users/nickname/messages"
How can I make sure that #user produces a proper path output?
Edit: Here is the name routes I am using to slugify the user.
match "/users/:nickname/messages" => "messages#index"
match "/users/:nickname/messages/new" => "messages#new", :as=>:new_message
match "/users/:nickname/messages" => "messages#create", :as=>:create_message
I guess what you want is to use the nickname as the url slug. What you need for that is just the regular nested resources;
# in routes.rb
resources :users do
resources :messages
end
which would give you the same routes except they would have :id instead of :nickname in there.
Now for the actual trick that lets you use the user's nickname as the url identifier:
# user.rb
class User < ActiveRecord::Base
def to_param
self.nickname
end
end
You would automatically get the nickname in the url, and have it passed on to your controllers as params[:id] so you have to act accordingly in your controller
# users_controller.rb
…
def show
#user = User.find_by_nickname(params[:id])
end
…
This should do the trick
=semantic_form_for :message, :url => create_message_path(:nickname => #user.nickname) do |f|
# ...

Resources