No Route error when passing parameters through link_to - ruby-on-rails

Error:
No route matches {:action=>"new", :controller=>"comments", :parent_id=>1}
routes.rb:
MyApp::Application.routes.draw do
resources :posts do
resources :comments
end
resources :topics do
resources :posts
end
root :to => "posts#index"
end
models:
class Topic < ActiveRecord::Base
has_many :posts, :dependent => :destroy
attr_accessible :name, :post_id
end
class Post < ActiveRecord::Base
belongs_to :topic, :touch => true
has_many :comments, :dependent => :destroy
accepts_nested_attributes_for :topic
attr_accessible :name, :title, :content, :topic, :topic_attributes
end
class Comment < ActiveRecord::Base
has_ancestry
attr_accessible :name, :content
belongs_to :post, :touch => true
end
view:
<%= link_to "Reply", new_post_comment_path(#post, :parent_id => comment.id) %>
controller:
class CommentsController < ApplicationController
respond_to :html, :xml
def show
#post = Post.find(params[:id])
#comments = #post.comments.order("updated_at").page(params[:page])
end
def create
#post = Post.find(params[:post_id])
#comment = #post.comments.build(params[:comment])
if #comment.save
flash[:notice] = "Replied to \"#{#post.title}\""
redirect_to(#post)
else
flash[:notice] = "Reply failed to save."
redirect_to(#post)
end
end
def new
#post = Post.find(params[:post_id])
#comment = Comment.new(:parent_id => params[:parent_id])
# #comment = #post.comments.build
end
def destroy
#post = Post.find(params[:post_id])
#comment = #post.comments.find(params[:id])
#comment.destroy
redirect_to post_path(#post)
end
end
By reading the code you might have gathered that I am trying to get the ancestry gem to work with nested resources. I've been using the Railscasts episode on the Ancestry gem to guide me. Thanks for reading my question.

Try to pass comment id
link_to "Reply", new_post_comment_path(#post, :parent_id => comment.id).

You need to use the nested path: link_to "Reply", new_post_comment_path(#post, :parent_id => comment).
rake routes can be your friend.

Related

How implement the Has Many Through Association on Controllers and methods

in my app I'm creating the categories in admin(so the admins creates, updates and destroys the categories name) and then when the users will create the posts they will select( or I'm thinking for switch with checkbox) a category for the posts.
I decide to do this implementation with a has many through for posts and categories. But I' having doubts for implements:
the post_params;
the methods for add the categories and then destroy the categories
and the parts for create, update and destroy the posts.
How can I implement this? It's a better way do different? So if someone help me with this I will appreciate.
Post.rb
class Post < ActiveRecord::Base
has_many :categorizations
has_many :categories, through: :categorizations
...
def add_category(category)
categorizations.create(category_id: category.id)
end
def remove_category(category)
categorizations.find_by(category_id: category.id).destroy
end
category.rb
class Category < ActiveRecord::Base
has_many :categorizations
has_many :posts, through: :categorizations
validates :name,
presence: true,
length: { minimum: 3, maximum: 30 },
uniqueness: true
end
categorization.rb
class Categorization < ActiveRecord::Base
belongs_to :post
belongs_to :category
validates :post_id, presence: true
validates :category_id, presence: true
end
controllers/admin/PostsController
class Admin::PostsController < Admin::ApplicationController
def new
#post = Post.new
#categories = Category.all.map{ |c| [c.name, c.id]}
end
def create
#post = Post.new(post_params)
#post.author = current_user
#post.categories << params[:category_id]
if #post.save
flash[:notice] = "Post has been created."
redirect_to #post
else
flash[:alert] = "Post has not been created."
render "new"
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
flash[:notice] = "Post has been deleted."
redirect_to posts_path
end
private
def post_params
params.require(:post).permit(:title,
:subtitle,
:content,
:attachment,
:attachment_cache,
:remote_attachment_url,
:categorizations_attributes => [:id,
:post_id,
:category_id,
:_destroy,
:categories_attributes => [:id,
:name]
]
)
end
end
controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update]
def index
#posts = policy_scope(Post)
end
def show
authorize #post, :show?
end
def edit
authorize #post, :update?
end
def update
authorize #post, :update?
if #post.update(post_params)
flash[:notice] = "Post has been updated."
redirect_to #post
else
flash.now[:alert] = "Post has not been updated."
render "edit"
end
end
private
def set_post
#post = Post.find(params[:id])
rescue ActiveRecord::RecordNotFound
flash[:alert] = "The post you were looking for could not be found."
redirect_to posts_path
end
def set_category
#category = Category.find(params[:category_id])
end
def post_params
params.require(:post).permit(:title, :subtitle, :content, :attachment, :attachment_cache, :remove_attachment, :remote_attachment_url, :category_id)
end
end
posts/_form.html.slim
= simple_form_for([:admin, #post], :html => { :multipart => true }) do |f|
= select_tag(:category_id, options_for_select(#categories), :prompt => "Select ad Category")
routes
Rails.application.routes.draw do
namespace :admin do
root 'application#index'
resources :posts, only: [:new, :create, :destroy]
resources :categories
resources :users do
member do
patch :archive
end
end
end
devise_for :users
root "posts#index"
resources :posts, only: [:index, :show, :edit, :update]
end
In your form
= select_tag(:category_ids, options_for_select(#categories), :prompt => "Select ad Category", multiple: true)
In your controller
params.require(:post).permit(:title, :subtitle, :content, :attachment, :attachment_cache, :remove_attachment, :remote_attachment_url, :category_ids)
Also need to give some advise, in your posts_controller.rb
remove below line
rescue ActiveRecord::RecordNotFound
Insterad of this write it in application_controller.rb , so it will work for whole application.
What I do for fix was put on the PostsController this:
class Admin::PostsController < Admin::ApplicationController
before_action :set_categories, only: [:new, :create]
.
.
.
private
def set_categories
#categories = Category.all.select(:id, :name)
end
def post_params
params.require(:post).permit(:title,
:subtitle,
:content,
:attachment,
:attachment_cache,
:remote_attachment_url,
category_ids:[]
)
end
And on the form I changed for use checkboxes and with that I can select and add more categories for a Post:
= f.association :categories, label: "Select the Categories", as: :check_boxes , collection: #categories.map{|c| [c.name, c.id]}, include_hidden: false
Add on the class Post and Category a dependent: :destroy for destroy the joins properly.
has_many :categorizations, dependent: :destroy
has_many :categories, through: :categorizations
And was necessary delete the validation for post_id on categorization so I just comment because when was uncommented when I try to create a Post it wasn't possible, So I do this:
class Categorization < ActiveRecord::Base
belongs_to :post
belongs_to :category
#validates :post_id, presence: true
validates :category_id, presence: true
end
And work's!

No route matches {:action=>"new", :controller=>"lessons"} missing required keys: [:course_id]

I am new to Ruby on Rails.I am facing a problem using nested resources.
I am building a learning app where there are courses and lessons.
Every course will have many lessons and a lesson belongs to only one course.
I am unable to create a lesson for a course currently.
Example : http://localhost:3000/courses/19/lessons/new is a page where i want to create and display lessons for course 19.
Routes.rb
Rails.application.routes.draw do
devise_for :users
resources :courses
resources :courses do
resources :lessons
end
resources :lessons
root 'pages#landing'
get 'pages/home' => 'pages#home' ,as: :home
get '/user/:id' => 'pages#profile',as: :profile
get '/users' => 'courses#index',as: :user_root
end
Course.rb
class Course < ActiveRecord::Base
belongs_to :user
has_many :lesson
validates :user_id , presence: true
end
Lesson.rb
class Lesson < ActiveRecord::Base
belongs_to :course
validates :course_id , presence: true
end
CourseController.rb
class CoursesController < ApplicationController
def index
#courses = Course.all;
end
def new
#course = Course.new;
end
def create
#course = Course.new(course_params);
#course.user_id = current_user.id;
if #course.save
redirect_to course_path(#course)
else
flash[:notice]="Course could not be created ! "
redirect_to new_course_path
end
end
def edit
end
def update
end
def destroy
#course = Course.find(params[:id]);
#course.destroy;
end
def show
#course = Course.find(params[:id]);
end
private
def course_params
params.require(:course).permit(:title, :description, :user_id)
end
end
LessonController.rb
class LessonsController < ApplicationController
def index
#lessons = Lesson.all;
end
def new
#lesson = Lesson.new;
end
def create
#lesson = Lesson.new(lesson_params);
#course = Course.find_by(id: [params[:course_id]]);
if #lesson.save
redirect_to new_course_lesson_path , flash[:notice] = "Lesson successfully saved !"
else
redirect_to new_course_lesson_path , flash[:notice] = "Lesson cannot be created ! "
end
end
def show
#lesson = Lesson.find(params[:id])
end
private
def lesson_params
params.require(:lesson).permit(:title,:description,:video,:course_id)
end
end
Lessonform.html.erb
<%= form_for ([#course,#lesson]) do |f| %>
<%= f.label :lesson_Title %>
<%= f.text_field :title ,placeholder: "Enter the lesson Title" ,:class=>"form-control" %><br />
<%= f.label :Description %>
<%= f.text_area :description ,placeholder: "Enter the lesson Description",rows:"8",:class=>"form-control" %><br />
<center>
<%= f.submit "Create lesson",:class =>"btn btn-lg btn-primary" %>
</center>
<% end %>
One problem i see is that you have defined route resources :lessons twice. Once, inside courses scope and second time outside.
The error seems to occur because in your view #course is nil. So, please check you set #course in a before_action inside lessons_controller#new action.
EDIT
class LessonsController < ApplicationController
before_action :set_course, only: [:new, :create]
def new
#lesson = #course.lessons.build
end
private
def set_course
#course = Course.find_by(id: params[:course_id])
end
end
Also replace has_many :lesson with has_many :lessons inside Course model.
First change you need to make in your Course model as you have singular lesson when defining many association:
has_many :lessons
Also let me know if their are any chances of lessons page being called without courses? If no then please remove:
resources :lessons
I guess also the two defining of courses in routes in creating issue. Please try removing the:
resources :courses
Let me know if you still face any issue.

STI and Polymorphic Association possible in rails 4? Not working for me

I'm somewhat of a newbie with ruby on rails and went off of samurails.com single table inheritance with rails 4 tutorial to add different comment types. This worked great but the problem I'm running into is when I try to use polymorphic associations to get comments and the specific type to function under other models such as project and challenge. A regular comment works, but the specific types do not.
I haven't seen anything that clearly says how to make this work or another option of going about it so any help would be greatly appreciated.
class Comment < ActiveRecord::Base
has_merit
acts_as_votable
belongs_to :commentable, :polymorphic => true
belongs_to :user
belongs_to :commenttype
belongs_to :project
def self.types
%w(Question Idea Problem)
end
def commentable_type=(sType)
super(sType.to_s.classify.constantize.base_class.to_s)
end
scope :questions, -> {where(type: 'Question')}
scope :ideas, -> {where(type: 'Idea')}
scope :problems, -> {where(type: 'Problem')}
end
class Question < Comment
end
class Idea < Comment
end
class Problem < Comment
end
class Project < ActiveRecord::Base
belongs_to :user
has_many :comments, :as => :commentable, :class_name => "Comment"
has_many :questions, :as => :commentable, :class_name => "Question"
has_many :ideas, :as => :commentable, :class_name => "Idea"
has_many :problems, :as => :commentable, :class_name => "Problem"
delegate :questions, :ideas, :problems, to: :comments
end
class CommentsController < ApplicationController
before_action :set_commentable, only: [:index, :new, :create]
before_action :set_type
before_action :set_comment, only: [:show, :edit, :update, :destroy]
def index
#comments = type_class.all
end
def show
end
def new
#comment = type_class.new
end
def edit
end
def create
#comment = #commentable.comments.new(comment_params)
#comment.user = current_user
if #comment.save
redirect_to :back, notice: "#{type} was successfully added."
else
render action: 'new'
end
end
def update
if #comment.update(comment_params)
redirect_to #comment.commentable, notice: "#{type} was successfully updated."
else
render action: 'edit'
end
end
def destroy
#user = current_user
#comment = #commentable.comments.where(comment_user: current_user).first
#commentable.comment.destroy
respond_to do |format|
format.html { redirect_to #commentable, notice: "Comment was deleted." }
format.js
end
end
private
def set_comment
#comment = type_class.find(params[:id])
end
def set_type
#type = type
end
def type
Comment.types.include?(params[:type]) ? params[:type] : "Comment"
end
def type_class
type.constantize
end
def set_commentable
#commentable = find_commentable
end
# add more commentable models here
def find_commentable
if params[:challenge_id]
Challenge.find(params[:challenge_id])
else
end
end
def find_commentable
if params[:project_id]
Project.find(params[:project_id])
else
end
end
def comment_params
params.require(type.underscore.to_sym).permit(:body, :type, :user_id, :commentable_id, :commentable_type, :commentable, :comment_type)
end
end
module CommentsHelper
def sti_comment_path(type = "comment", comment = nil, action = nil)
send "#{format_sti(action, type, comment)}_path", comment
end
def format_sti(action, type, comment)
action || comment ? "#{format_action(action)}#{type.underscore}" : "#{type.underscore.pluralize}"
end
def format_action(action)
action ? "#{action}_" : ""
end
end
<%= form_for [commentable, Comment.new], :html => { :multipart => true } do |f| %>
<%= f.text_area :body, class: "form-control", placeholder: "What's on your mind?" %>
<%= f.label :type %><br>
<%= f.select :type, Comment.types.map {|r| [r.humanize, r.camelcase]}, {}, disabled: #type != "Comment" %>
<%= f.submit "Post", class: "btn pull-right" %>

undefined local variable or method `event_params' error with Rails 4 and nested form

I am dealing with a nested form on my current project and found a very simple blog post that has helped me alot http://iroller.ru/blog/2013/10/14/nested-model-form-in-rails-4/. The problem is that I cannot seem to update the event (which should in turn create the nested answers). I have spent most of the day today trying to work around this and I haven't been able to make any real progress.
Error
undefined local variable or method `event_params' for #<EventsController:0x007f9847af6d10>
Thanks guys and girls sorry for the dumb question. And please let me know if you would like any more information.
Models
class Event < ActiveRecord::Base
belongs_to :user
has_many :questions
accepts_nested_attributes_for :questions
end
class Question < ActiveRecord::Base
belongs_to :user
belongs_to :event
has_many :answers
accepts_nested_attributes_for :answers
end
class Answer < ActiveRecord::Base
belongs_to :user
belongs_to :question
end
Routes.rb
Rails.application.routes.draw do
root 'home#index'
devise_for :users, path_names: {sign_in: "login", sign_out: "logout"}, controllers: {omniauth_callbacks: "omniauth_callbacks"}
resources :answers
resources :users, only: [:new, :create]
resources :questions do
resources :answers #-> domain.com/questions/1/answers/new
end
resources :events, only: [:index, :new, :show, :update] do
patch ":id", action: :index
collection do
get :favorite
get "question/:id", action: :question
end
end
get 'users/new', to: 'users#new'
post 'users/new', to: 'users#create'
get 'events/favorite', to: 'events#favorite', via:[:get], as: 'favorite'
post 'events/:id' => 'events#update'
get 'answers/new' => 'answers#new'
get 'events/question' => 'events#question'
end
methods from events_controller
def question
#event = Event.find(params[:id])
end
def update
#event = Event.find(params[:id])
if #event.update(event_params)
redirect_to events_path, notice: "Answers saved"
else
redirect_to events_question_path, notice: "Answers not saved"
end
end
def event_params
params.require(:event).permit(:owner_id,
questions_attributes: [:poll, :event_id],
answers_attributes: [:response, :event_id, :question_id, :user_id])
end
questions.erb
<%= simple_form_for(#event) do |f| %>
<%= f.error_notification %>
<%= f.object.name %>
<%= f.simple_fields_for :questions, f.object.questions do |q| %>
<%= q.object.poll%>
<%= q.simple_fields_for :answers, q.object.answers.build do |a|%>
<%= a.text_field :response %>
<% end %>
<%end %>
<%= f.button :submit%>
<% end %>
You have no method event_params, or probably it is not available for class. In your case it is in the another method:
def favorite
#arr = []
cookies.each do |cookie|
#arr.push(cookie)
endhtm
#info = []
for i in 0...#arr.length
if #arr[i][0].index('id')
#info.push(#arr[i][1])
end
#info
end
if #info == []
flash[:error] = "You don't have any events saved yet. Please select events of interest to you."
redirect_to events_path
else
#events = Event.all_events_by_asc_order.where(id: #info)
end
end
def event_params
params.require(:event).permit(
questions_attributes: [:poll, answers_attributes: [:response]])
end
end
Should be:
def favorite
#arr = []
cookies.each do |cookie|
#arr.push(cookie)
endhtm
#info = []
for i in 0...#arr.length
if #arr[i][0].index('id')
#info.push(#arr[i][1])
end
#info
end
if #info == []
flash[:error] = "You don't have any events saved yet. Please select events of interest to you."
redirect_to events_path
else
#events = Event.all_events_by_asc_order.where(id: #info)
end
end
end
def event_params
params.require(:event).permit(
questions_attributes: [:poll, answers_attributes: [:response]])
end
There is endhtm, seems like it was end + something.

Polymorphic Commenting

I'm currently developing an app which allows users to post from their own account, but if they're an administrator of a group or venue, they can also post as that entity. I'm struggling converting the polymorphic association ideas from some of the other questions out there as generally they're all based around being able to comment on multiple things and not from multiple things.
I think my main issue is that I have my user's post form on the homepage, so it does not have an ID in the URL.
My post controller looks like this:
class PostsController < ApplicationController
before_action :authenticate_user!, only: [:create, :destroy]
before_filter :load_postable
def index
end
def new
#post = Postabe.posts.new(post_params)
end
def create
#post = #postable.posts.build(post_params)
if #post.save
flash[:success] = "Post created!"
redirect_to root_url
else
#feed_items = []
render 'static_pages/home'
end
end
def destroy
#post.destroy
redirect_to root_url
end
private
def post_params
params.require(:post).permit(:content)
end
def load_postable
resource, id = request.path.split('/')[1, 2]
resource_name = resource.singularize.classify
if resource_name == "User"
#postable = current_user
else
#postable = resource_name.constantize.find(id)
end
end
end
and my _post_form.html.erb partial:
<%= form_for ([#postable, #postable.post.new]), remote: true do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Create a Post..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
my related routes:
devise_for :users, :controllers => { :omniauth_callbacks => "omniauth_callbacks", :registrations => "registrations" }
resources :users, :only => [:index] do
member do
get :favourite_users, :favourited_users
end
resources :posts
end
resources :venues do
resources :posts
end
resources :groups do
resources :posts
end
Models as follows:
class Post < ActiveRecord::Base
belongs_to :postable, polymorphic: true
end
class User < ActiveRecord::Base
has_many :posts, as: :postable, dependent: :destroy
end
class Venue < ActiveRecord::Base
has_many :posts, as: :postable, dependent: :destroy
end
class Group < ActiveRecord::Base
has_many :posts, as: :postable, dependent: :destroy
end
It seems that I keep getting the error
Couldn't find Post without an ID
but I don't know why it's looking for a Post ID if it's not been created yet. Any help would be appreciated!
You have before_filter :load_postable in your controller. By default it will run for all the actions in your controller, even when the id is not specified. The error is thrown by #postable = resource_name.constantize.find(id), id is nil for index method.
Change this line to:
before_filter :load_postable, except: [:index]

Resources