Rails: ActionController::ParameterMissing - ruby-on-rails

I'm building an app that lets :users place :orders at :places. I am defining orders_params in PlacesController, but Rails says ParameterMissing ("params is missing or the value is empty: order")
How can I fix this, so that one can create an :order for :place_id through app/place/PLACE_ID/book ?
PlacesController:
def book
#place = Place.find(params[:id])
#order = Order.new(order_params)
if #order.save
flash[:success] = "Success"
redirect_to #place
else
render 'book'
end
end
private
def place_params
params.require(:place).permit(:place_name)
end
def order_params
params.require(:order).permit(:place_id, :user_id)
end
Routes.rb
get 'book' => 'places#show#book'
get '/places/:id/book' => 'places#book', as: :place_book
resources :places
OrdersController
class OrdersController < ApplicationController
def new
end
def create
#place = Place.find(#order.place_id)
#order = Order.new(user_id: current_user.id, place_id: #place)
if #order.save
flash[:success] = "Order placed"
redirect_to #place
else
render 'book'
end
end
def show
end
def edit
end
def update
end
def destroy
end
private
def order_params
params.require(:order).permit(:place_id, :user_id)
end
end
Model: Order.rb
belongs_to :user
has_one :place
validates :user_id, presence: true
validates :place_id, presence: true
## OTHER VALIDATIONS
View: app/views/places/book
<%= form_for(#order) do |f| %>
<!-- SOME FORM_FORS -->
<%= f.submit "Place order", class: "btn btn-primary" %>
<% end %>

Related

Create website and child page simultaneously in Rails 5

On my homepage, I'm trying to set it up so when you click the "Get started" button, a website record is created, but also a page belonging to that website is created, and you're redirected to the page.
This is what I have so far. The website record is being created but the page is not being created.
Models
class Page < ApplicationRecord
belongs_to :website
end
class Website < ApplicationRecord
has_many :pages, :dependent => :destroy
accepts_nested_attributes_for :pages
end
Homepage controller
class MarketingPagesController < ApplicationController
def home
#website = Website.new
#website.pages.build
end
end
Website controller
class WebsitesController < ApplicationController
def create
#website = Website.new(creation_params)
if #website.save
redirect_to #website.Page.first
else
render :new
end
end
private
def shared_params
[:name]
end
def creation_params
params.require(:website).permit(*shared_params)
end
def update_params
params.require(:website).permit(*shared_params)
end
end
Page Controller
class PagesController < ApplicationController
def create
#page = Page.new(creation_params)
if #page.save
redirect_to #page
else
render :new
end
end
def show
#page = Page.find(params[:id])
#templates = Template.all
end
private
def shared_params
[:name, :website_id]
end
def creation_params
params.require(:page).permit(*shared_params)
end
def update_params
params.require(:page).permit(*shared_params)
end
end
Website form on homepage
<%= form_for #website do |f| %>
<%= f.hidden_field :name, value: "Untitled site" %>
<%= f.fields_for :pages do |builder| %>
<%= builder.hidden_field :name, value: "Untitled page" %>
<% end %>
<%= f.submit "Create Website" %>
<% end %>
You are using the association incorrectly
# Change
#website.Page.first
# to
#website.pages.first
Change this snippet in WebsiteController
if #website.save
redirect_to #website.pages.first
else
render :new
end
you have not white listed page params in website controller. modify your shared_params in website controller to :
def shared_params
[:name, pages_attributes: [:id, :name]]
end
and of course do changes suggested by #Deepak

Rails app reviews are not saving to database

I am building a book review application from on online tutorial. I am trying to save a book review with a form. I have a book table and a reviews table. If the book review saves, I've told the review form to redirect to the book show page. If not, render 'new' again. I get zero errors when I try to save. It just puts me back on the new review page. I went into the console, and the reviews are not being saved. I don't know what's going on. Can someone help?
Here is my books controller:
class BooksController < ApplicationController
before_action :authenticate_user!, only: [:new, :edit, :index, :show]
def index
#books = Book.all
end
def new
#book = current_user.books.new
end
def create
#book = current_user.books.build(book_params)
if #book.save
redirect_to books_path
else
render 'new'
end
end
def show
#book = Book.find(params[:id])
end
def edit
#book = Book.find(params[:id])
end
def update
#book = Book.find(params[:id])
if #book.update(book_params)
redirect_to book_path(#book)
else
render "edit"
end
end
def destroy
#book = Book.find(params[:id])
#book.destroy
if #book.destroy
redirect_to books_path
else
render 'show_books_path'
end
end
private
def book_params
params.require(:book).permit(:title, :description, :author, :category_id, :book_img)
end
end
Here is my reviews controller:
class ReviewsController < ApplicationController
before_action :find_book
def new
#review = Review.new
end
def create
#review = Review.new(review_params)
#review.book_id = #book.id
#review.user_id = current_user.id
if #review.save
redirect_to book_path(#book)
else
render 'new'
end
end
def edit
end
def update
end
def destroy
end
private
def review_params
params.require(:review).permit(:rating, :comment)
end
def find_book
#book = Book.find(params[:book_id])
end
end
Here is my review model:
class Review < ApplicationRecord
belongs_to :books
belongs_to :users
end
Here is my book model:
class Book < ApplicationRecord
belongs_to :user
has_many :reviews
has_attached_file :book_img, styles: { book_index: "250x350>", book_show: "400x600>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :book_img, content_type: /\Aimage\/.*\z/
end
I'm using a devise form. Here is what I have:
<%= simple_form_for([#book, #book.reviews.build]) do |f| %>
<p>Rating</p>
<%= f.input :rating, label: false, :class => "input" %>
<p>Comment</p>
<%= f.text_area :comment, label: false, :class => "input" %>
<%= f.button :submit, :class => "submit" %>
<% end %>
Here is my routes file:
Rails.application.routes.draw do
devise_for :users
resources :books do
resources :reviews
end
root "books#index"
end
I'm really not sure what's going on here. When I go into the console, the reviews are not being saved. Eventually, I want to display them, but I haven't gotten to that step. Any help would be very appreciated!
I see that in your Review model you have this:
class Review < ApplicationRecord
belongs_to :books
belongs_to :users
end
When it should be like this:
class Review < ApplicationRecord
belongs_to :book
belongs_to :user
end
belongs_to associations have to use the singular term

Empty item displaying from nested resource

I'm new to Rails and am building a todo app.
For some reason an empty Item instance is displaying within all lists by default. Item.count is returning 0, but <%= render #list.items %> always has one "instance" of _item.html.erb.
I have #list assigned to List.find(params[:id]) in the list controller's show method and am calling <%= render #list.items %> in its show view.
I have this link in _item.html.erb
<%= link_to "Delete", [item.list, item],
method: :delete,
data: { confirm: "Are you sure?" }
%>
and it will display the delete link, but link to lists/*/items (as opposed to list/*/items/*) in the empty item, which gives a routing error. The link works fine in actual items though.
Controllers:
lists_controller.rb:
class ListsController < ApplicationController
before_action :set_list, only: [:show, :edit, :update, :destroy]
def index
#lists = policy_scope(List).where(author: current_user)
end
def show
#item = #list.items.build
end
def new
#list = List.new
authorize #list
end
def create
#list = List.new(list_params)
#list.author = current_user
authorize #list
if #list.save
flash[:notice] = "Your list was created."
redirect_to #list
else
flash[:error] = "Your list was not created."
render "new"
end
end
def edit
end
def update
if #list.update(list_params)
flash[:notice] = "Your list was updated."
redirect_to #list
else
flash[:error] = "Your list was not updated."
render "edit"
end
end
def destroy
if #list.destroy
flash[:notice] = "Your list was deleted."
redirect_to root_path
else
flash[:error] = "Your list was not deleted."
redirect_to #list
end
end
private
def list_params
params.require(:list).permit(:title, :description, :author_id)
end
def set_list
#list = List.find(params[:id])
authorize #list
end
end
items_controller.rb:
class ItemsController < ApplicationController
before_action :set_list
def create
#item = #list.items.create(item_params)
authorize #item
if #item.save
flash[:notice] = "Your item was added."
redirect_to #list
else
flash.now[:error] = "Your item was not added."
end
end
def destroy
#item = #list.items.find(params[:id])
authorize #item
if #item.destroy
flash[:notice] = "Your item was deleted."
redirect_to #list
else
flash.now[:error] = "Your item was not deleted."
end
end
private
def item_params
params.require(:item).permit(:name, :list_id)
end
def set_list
#list = List.find(params[:list_id])
end
end
Models:
list.rb:
class List < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
belongs_to :author, class_name: "User"
has_many :items, dependent: :destroy
end
item.rb:
class Item < ActiveRecord::Base
validates :name, presence: true
belongs_to :list
end
Routes:
Rails.application.routes.draw do
root "lists#index"
resources :lists do
resources :items
end
devise_for :users
end
Reference migration:
class AddListsToItems < ActiveRecord::Migration
def change
add_reference :items, :list, index: true, foreign_key: true
end
end
The issue was caused by the way I passed the instance variable to the form.
This line in ListsController is building a new item on each page refresh.
def show
#item = #list.items.build
end
I removed that assignment, as well as its passing to the form.
<%= render "items/form", list: #list, item: #item %> becomes <%= render "items/form", list: #list %>
simple_form_for([list, item] becomes simple_form_for([#list, #list.items.build]
#item = #list.items.build is your problem.
The issue is that building a nested item will always yield an "empty" item, especially if it's nested.
Whilst you can use the code in the new action with impunity, using in show will basically just create a blank object that you have to contend with.
--
If you want to create a new item object when viewing your #list, you'll be better building / invoking on the fly (as you're doing already):
<%= form_for [#list, #list.items.new] ...
try
<%= render 'item' %>
and on your _item.html.erb (which is rendered), use the following code:
<%= #list.items %>

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" %>

Having a comment obtain a community_id as well

I've tried figuring out the issue behind not being able to save the community_id I hope someone can help me with.
MODELS
User
has_one :profile
has_many :communities, dependent: :destroy
has_many :comment, dependent: :destroy
Community
extend FriendlyId
friendly_id :title, use: [:slugged, :finders]
has_many :comments
belongs_to :user
Comment
belongs_to :user
belongs_to :community
belongs_to :profile
CONTROLLERS
Communities
def index
#communities = Community.all
#comment = Comment.new
#comments = Comment.all
end
def create
#community = Community.new(community_params)
#community.user_id = session[:user_id]
if #community.save
flash[:notice] = "Post Created"
else
flash[:alert] = "Error post not created"
end
redirect_to "/"
end
def new
#community = Community.new
end
def edit
#community = Community.friendly.find(params[:id])
end
def show
#comment = Comment.new
#comments = Comment.all
#community = Community.friendly.find(params[:id])
#current_user = User.find(session[:user_id])
end
def update
#community = Community.friendly.find(params[:id])
if #community.update(params[:comment])
flash[:notice] = "post updated"
else
flash[:alert] = "post not updated"
end
end
def destroy
#community = Community.friendly.find(params[:id])
if #community.destroy
flash[:notice] = "Post was thrown away"
else
flash[:alert] = "Post was not deleted"
end
redirect_to "/"
end
private
def community_params
params.require(:community).permit(:user_id, :title, :bio)
end
Comments
def index
#comments = Comment.all
end
def create
#comment = Comment.new(comment_params)
#comment.user_id = session[:user_id]
if #comment.save && #comment.community_id
flash[:notice] = "Comment has been posted"
else
flash[:alert] = #comment.errors.full_messages
end
redirect_to :back
end
def new
#comment = Comment.new
end
def show
#comment = Comment.find(params[:id])
end
def destroy
#comment = Comment.find(params[:id])
#comment.destroy
redirect_to :back
end
private
def comment_params
params.require(:comment).permit(:text, :user_id, :community_id, :profile_id)
end
VIEWS
comments/_new
<%= form_for #comment do |f| %>
<%= f.hidden_field :community_id %>
<%= f.text_area :text, placeholder: "Enter New Comment Here ...", :cols => 50, :rows => 3, :class => 'text_field_message', :id => 'new_comment' %>
<%= f.submit :class => 'new_comment_button' %>
<% end %>
Whenever I check my console I notice the user_id gets registered with the comment but community_id is nil. Could someone point me in the right direction or help me understand where I made an error. Thank you for all your help.
Firstly,
#app/models/user.rb
has_many :comments, dependent: :destroy #-> this should be plural.
You have no value in your community_id input attribute:
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def new
#comment = Comment.new
end
end
#app/views/comments/new.html.erb
<%= form_for #comment do |f| %>
<%= f.hidden_field :community_id, params[:community_id] %>
<% end %>
I am assuming you're passing your :community_id parameter through the routes (IE url.com/communities/:community_id/comments/new)
I would do the following:
#config/routes.rb
resources :communities do
resources :comments
end
#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
def new
#comment = Comment.new
end
def create
#comment = Comment.new comment_params
#comment.save
end
private
def comment_params
params.require(:comment).permit(:text).merge(user_id: current_user.id, community_id: params[:community_id])
end
end
This will give you the ability to use the following view:
#app/views/comments/new.html.erb
<%= form_for #comment do |f| %>
<%= f.text_area :text, placeholder: "Enter New Comment Here ...", :cols => 50, :rows => 3, :class => 'text_field_message', :id => 'new_comment' %>
<%= f.submit :class => 'new_comment_button' %>
<% end %>

Resources