class CommentsController < ApplicationController
def create
#commentable= context_object()
#comment = #commentable.comments.build(params[:comment].merge(:user_id => current_user.id))
if #comment.save
respond_to do |format|
format.js
end
else
render :action => 'new'
end
end
private
def context_object
params[:constraint][:context_type].singularize.classify.constantize.find( context_id )
end
def context_id
params["#{ params[:constraint][:context_type].singularize }_id"]
end
end
This commenting module has served me well but I ran into a hitch this morning, possibly because of my use of nested resources. Essentially, I now have a URL like:
/projects/3/albums/6/attachments/84
When I comment on that page, I get the error:
ActiveRecord::RecordNotFound (Couldn't find Project without an ID):
app/controllers/comments_controller.rb:102:in `context_object'
app/controllers/comments_controller.rb:14:in `create'
My routes file looks like:
resources :projects do
resources : albums do
resources :attachments
end
end
resources :attachments do
resources :comments, :only => [:create, :update,:destroy],
:constraint => {:context_type => "conversations"}
end
Any ideas on how I can get the commenting module to play nicely with commenting on project>Album>Attachment ?
Thanks for the input,
Posting this as an answer in order not to clutter the comments to the original question.
Since you don't have the requirement to keep attachments available via /attachments - making the second resources block useless, do something like this:
resources :projects do
resources :albums do
resources :attachments do
resources :comments, :only => [:create, :update,:destroy],
:constraint => {:context_type => "conversations"}
end
end
end
That's going to change your routes helpers (_path and _url), go through your controller(s) and view(s) and change them to reflect your new helpers.
Specifically, attachment_comments_path becomes project_album_attachment_comments_path.
The full list of routes for those models can be viewed by running rake routes in a console. I'd also recommend you take a closer look to the Rails routing guide.
Related
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.
Bumping into a redirect problem with nested resources and polymorphic associations. I think I can find a way forward however I'd like to find out what can be considered as best practice.
I have the following nested resources:
namespace :navigate do
resources :boks, :only => [:show] do
resources :groups, :only => [:show]
resources :categories, :only => [:show]
resources :tools, :only => [:show, :index]
resources :artifact_types, :only => [:show]
resources :artifacts, :only => [:show, :index]
resources :processus do
resources :notes, module: :processus
end
end
end
Notes being a polymorphic association (that I will also later use with the Tool model).
Most of my code is inspired but the excellent gorails.com episode: https://gorails.com/episodes/comments-with-polymorphic-associations
The controller that I use to manage notes is:
class Navigate::NotesController < Navigate::NavigateController
before_action :authenticate_user!
def create
#note = #noteable.notes.new note_params
#note.user = current_user
#note.save
redirect_to [:navigate, #bok, #noteable], notice: "Your note was succesfully created."
end
def update
#note = #noteable.notes.where(user: current_user).first
if #note.update(note_params)
redirect_to polymorphic_url([:navigate,*** HOW TO REFERENCE BOK ***, #noteable]), notice: "Your note has been updated."
else
flash.now[:alert] = "Unable to update your note."
render :edit
end
end
private
def note_params
params.require(:note).permit(:content, :public)
end
end
Note the * HOW TO REFERENCE BOK * part. This is where my problem is. Once I update the "Note" I want to redirect to #noteable related controller (here Processus) but in order to construct the URL I need to have an #bok object which I don't have in this instance because I actually don't need it.
I can also retrieve the correct #bok model but I wonder if there is another way to deal with this redirect?
My URL for redirection should be http://localhost:3000/navigate/boks/1/processus/2 but in order to construct it I would need a Bok object which I haven't go in my controller above (as I don't need it).
Any ideas? Thanks!
You can't reference a route for a nested object without the id of the object it is nested into.
I have Q+A model inside an events model and having issue with understanding how the nested routes work. I'm getting a No route matches {:action=>"create", :controller=>"event_questions" and missing required keys: [:event_id]`
My question form sits inside my show.hrml.erb for my event model right now. Some of the relationship stuff is from neo4j gem so it isn't standard but the issue shouldn't be related to that. From what I know, I am posting to /events/events_id/event_questions
events_controller.rb
def show
#event = Event.find(params[:id])
#event_question = EventQuestion.new
end
event.rb
has_many :out, :event_questions, type: 'questions_of'
event_question.rb
has_one :in, :events, origin: :event_questions
events/show.html.erb
<%= form_for [:event, #event_question] do |f| %>
#form stuff
<% end %>
event_questions_controller.rb
def create
#event_question = EventQuestion.new(event_question_params)
if #event_question.save
#event = Event.find(params[:event_id])
#event_question.update(admin: current_user.facebook_id)
#event_question.events << #event
redirect_to #event
else
redirect_to :back
end
end
routes.rb
resources :events do
resources :event_questions, only: [:create, :destroy]
end
I think it's in your routes. Change it to look like this:
resources :events do
resources :questions, controller: 'event_questions`, only: [:create, :destroy]
end
That'll give you http://youraddress/event/:event_id/questions and put it in the expected controller. Make sure it's event_questions.rb and not events_questions.rb. From terminal, also run rake routes and it'll show you the actions, paths, and controllers responsible for them.
Got it to work with
form_for(#event_question, :url => event_event_questions_path(#event)) do |f|
I'm not sure how to pass the #event via the other way (in the question), but assuming you can, both methods should work.
I am trying to redirect user to show_city_url or show_city_path but i get an exception that they are both undefined.In the city controller i have three actions show,like, and dislike. unlike_city_path and like_city_path works but show_city_path doesnt.Also when i put this in all_cities action redirect_to :controller=>"city",:action=>"show" works.What am i doing wrong?Thank you.
class HomeController < ApplicationController
def all-cities
redirect_to show_city_url
end
end
In the Routes
resources :city do
member do
post :like
post :dislike
get :show
end
end
according to your comments:
resources :cities, :controller => 'city' do
collection do
get :show, :as => :show
end
member do
post :like
post :dislike
end
end
now you can call show_cities_url and you'll land in the show action of your CityController.
PS: Following the Rails' convention makes your life easier ;)
RoR Guide: Rails Routing from the Outside In
I have a controller with the 7 RESTful actions plus an additional 'current' action, which returns the first active foo record:
class FooController < ApplicationController
def current
#user = User.find(params[:user_id])
#foo = #user.foos.where(:active => true).first
#use the Show View
respond_to do |format|
format.html { render :template => '/foos/show' }
end
end
#RESTful actions
...
end
The Foo Model :belongs_to the User Model and the User Model :has_many Foos.
If I structure the routes as such:
resources :users do
resources :foos do
member do
get :current
end
end
end
The resulting route is '/users/:user_id/foos/:id'. I don't want to specify the foo :id, obviously.
I've also tried:
map.current_user_foo '/users/:user_id/current_foo', :controller => 'foos', :action => 'current'
resources :users do
resources :foos
end
The resulting route is more like I would expect: '/users/:user_id/current_foo'.
When I try to use this route, I get an error that reads:
ActiveRecord::RecordNotFound in FoosController#current
Couldn't find Foo without an ID
edit
When I move the current action to the application controller, everything works as expected. The named route must be conflicting with the resource routing.
/edit
What am I missing? Is there a better approach for the routing?
I think you want to define current on the collection, not the member (the member is what is adding the :id).
try this.
resources :users do
resources :foos do
collection do
get :current
end
end
end
Which should give you a route like this:
current_user_foos GET /users/:user_id/foos/current(.:format) {:controller=>"foos", :action=>"current"}
Also map isn't used anymore in the RC, it will give you a deprecation warning.