How to fix parameter missing after creation - ruby-on-rails

I'm working on subscribing application but I've been stacking with creating subscription on the show/page of product. Because of the error
ActionController::ParameterMissing (param is missing or the value is empty: subscription):
routes.rb
resources :products do
resources :subscriptions, only: [:create]
end
products/show.html.erb
<div class="subscribe">
<%= form_with(model: #subscription, url: product_subscriptions_path(product_id: #product.id)) do |f| %>
<div>
<%= f.text_field :email %>
<%= f.submit "Register", class: "btn"%>
</div>
<% end %>
</div>
products_controller.rb
def show
#product = Product.find_by_id(params[:id])
#subscription = Subscription.new
end
subscription_controller.rb
def create
#product = Product.find(params[:product_id])
#subscription = #product.subscriptions.build(create_params)
#subscription.save
end
def create_params
params.require(:subscription).permit(:email, :product_id)
end

The url helper needs two parameters here, as it is a nested route.
url: product_subscriptions_path(product: #product, subscription: #subscription))

Related

Transmit params with form_tag

In my views I have a form and trying to update quantity for an order line:
<div class="quantity">Quantity</br>
<%= form_tag(order_line_path(line.id), method: "patch") do %>
<%= number_field_tag 'qty', '1', within: 1...line.book.stock %>
<%= submit_tag "Update", class: "btn btn-primary" %>
<% end %>
</div>
The instance variable in the rest of my view is a collection of order lines, so I cannot use it.
Then I have in my controller the update method:
def update
#order = current_order
#order_line = #order.order_lines.find(params[:id])
#order_line.update_attributes(order_line_params)
end
And my strong params definition:
def order_line_params
params.require(:order_line).permit(:qty)
end
I get this error :
param is missing or the value is empty: order_line
Could someone please have a look?
Thanks!
The reason you are getting param is missing or the value is empty: order_line is that you are using form_tag which gives a "flat" params hash.
However this is easily avoidable if you just use form_with/form_for.
# routes.rb
resources :orders do
resources :line_items, shallow: true
end
# app/views/order_items/edit.html.erb
# use `form_with(model: #order_item)` in Rails 5
<%= form_for(#order_item) do |f| %>
<%= f.label :qty, within: 1...f.object.book.stock %>
<%= f.number_field :qty, %>
<%= f.submit %>
<% end %>
class OrderItemsController < ApplicationController
before_action :set_order_item, only: [:show, :edit, :update, :destroy]
# ...
# GET /order_items/:id/edit
def edit
end
# PATCH /order_items/:id
def update
if #order_item.update(order_item_params)
redirect_to #order_item, notice: 'Line updated'
else
render :edit
end
end
private
def set_order_item
#order_item = OrderItem.find(params[:id])
end
def order_item_params
params.require(:order_item).permit(:qty)
end
end
But what you're really looking for unless you are doing the update/creation of nested items with AJAX is most likely a combination of accepts_nested_attributes and fields_for which will let the user mass edit the line items:
class Order < ApplicationRecord
accepts_nested_attributes_for :order_items
end
<%= form_for(#order) do |f| %>
<%= fields_for(:order_items) do |oif| %>
<%= f.label :qty, within: 1...f.object.book.stock %>
<%= f.number_field :qty, %>
<% end %>
<%= f.submit %>
<% end %>
class OrdersController < ApplicationController
# PATCH /orders/:id
def update
if #order.update(order_params)
redirect_to #order, notice: 'Order updated.'
else
render :new
end
end
private
def order_params
params.require(:order).permit(order_items_attributes: [:qty])
end
end

NoMethodError in Users#show (Ruby Rails)

I'm running into a NoMethodError in my Users#show when trying to include a form partial for submitting a task item (_form.html.erb). My other partial (_item.html.erb) is rendering properly. My item model and my user model are related to each other, user has_many :items, and item belongs_to :user.
Any and all help would be greatly appreciated!
Below is my routes.rb
Rails.application.routes.draw do
get 'welcome/index'
get 'welcome/about'
root 'users#show'
resources :users do
resources :items, only: [:new, :create]
end
devise_for :users
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end
Below is my terminal output
ActionView::Template::Error (undefined method `items_path' for #<#<Class:0x007fefeca61dd0>:0x007fefeca58b18>
Did you mean? items_create_path):
1: <h4> Create a new to-do item </h4>
2:
3: <%= form_for #item do |f| %>
4: <%= f.label :name %>
5: <%= f.text_field :name, class: 'form-control', placeholder: "Enter task here" %>
Items Controller
class ItemsController < ApplicationController
def new
#item = Item.new
end
def create
#item = Item.new
#item.user = current_user
#item.name = params[:item][:name]
if #item.save
flash[:notice] = "Item saved"
redirect_to #item
else
flash.now[:alert] = "Item was not created, please try again."
render :new
end
end
end
Users Controller
class UsersController < ApplicationController
def show
if !current_user.nil?
#user = current_user
#item = Item.new
#items = #user.items
else
redirect_to new_user_registration_path
end
end
end
Users#show page
<h2> Your to-do list</h2>
<div class="col-md-8">
<div class='items'>
<%= render partial: "items/item", local: { item: #item} %>
</div>
</div>
<div class="col-md-8">
<div class='new-item'>
<%= render partial: "items/form", local: { item: #item } %>
</div>
</div>
In your routes.rb file, you have items defined as a nested resource. You can check all of your routes by running this command on your terminal: rake routes.
For your routes specifically, you say:
resources :users do
resources :items, only: [:new, :create]
end
This would give you routes for GET /users/:user_id/items/new and POST /users/:user_id/items. However, in your form, it looks like you're trying to do this: <%= form_for #item do |f| %>. You don't have a route defined for an item by itself. You'll need to supply a user as well.
Try this for your form:
<%= form_for [#user, #item] do |f| %>
And something like this in your ItemsController:
class ItemsController
def new
#user = current_user
#item = Item.new
end
end
Your items route is nested under users. therefore you have to pass both to the form_for - a user and an item.
Something like this will probably work:
<%= form_for(current_user, #item) do |f| %>

No route matches [POST] "/jobs"

I have a Job model that contains a Company_id as a foreign key. On the Job new page, I want to create a new job using simple form like this
<%= simple_form_for (#job) do |f| %>
<%= f.input :title, label: "Title of job" %>
<%= f.submit 'Create', class: "btn btn-success" %>
<% end %>
This is my nested route
resources :companies do
resources :jobs, only: [:show, :new, :create, :update, :destroy]
end
In my jobs controller new and create method, I have
def new
#job = Job.new
end
def create
#job = Job.new(job_params)
#company = params[:company_id]
#job.company_id = #company
if #job.save
redirect_to company_job_path
else
render :new
end
end
This is the route to the job show page
company_job GET /companies/:company_id/jobs/:id(.:format) jobs#show
and the job create page
company_jobs POST /companies/:company_id/jobs(.:format) jobs#create
I keep getting the error below when I try to create a job using simple form.
No route matches [POST] "/jobs"
Any help would be appreciated.
Just add <%= simple_form_for [#company, #job] do |f| %> instead of <%= simple_form_for (#job) do |f| %> I suppose you have #company set when form is rendered.
According your nested routes you need to set company before jobs
so either use before action set company of find company before use this
in controller
before_action :set_company
def new
##company = Company.find(params[:company_id])
#job = #company.jobs.new
end
private
def set_company
#company = Company.find(params[:company_id])
end
in view pass full url
<%= simple_form_for #job, :url => company_jobs_path(#company, #job), :method => :post%>
<%= f.input :title, label: "Title of job" %>
<%= f.submit 'Create', class: "btn btn-success" %>
<% end %>

Nested resource parameters not being set properly in form_for

I'm getting a curious error after submitting my form. Been trying to solve this for several hours..
No route matches {:action=>"show", :controller=>"items", :item_id=>"141", :matter_id=>"3"} missing required keys: [:id]
The parameters are:
{"utf8"=>"✓",
"authenticity_token"=>"w0D7XmX2X2/ZMU19T6RlMvWCEClXnCFFOR+4EdIFvWg=",
"comment_item"=>{"item_id"=>"",
"name"=>"kaljdf",
"body"=>"yet another comment test"},
"commit"=>"Post Comment",
"matter_id"=>"3",
"item_id"=>"141"}
I have the following models:
class Matter < ActiveRecord::Base
has many :discoveries
delegate :items, to: :discoveries
end
class Discovery < ActiveRecord::Base
belongs_to :matter
scope :items, -> { where(type: 'Item') }
end
class Item < Discovery
has_many :comment_items
end
class CommentItem < ActiveRecord::Base
belongs_to :item
end
Controllers:
class ItemsController < DiscoveriesController
def show
#item = Item.find(params[:id])
#comment_item = CommentItem.new
end
def edit
#item = Item.find(params[:id])
end
def new
#item = Item.new
end
end
class CommentItemsController < ApplicationController
before_action :set_comment_item, only: [:show, :edit, :update, :destroy]
def new
#item = Item.find(params[:item_id])
#comment_item = #item.comment_item.new
end
def create
#item = Item.find(params[:item_id])
#comment_item = #item.comment_items.new(comment_item_params)
if #comment_item.save
flash[:notice] = 'Comment was successfully created'
redirect_to matter_item_url(matter_id: params[:matter_id])
else
flash[:notice] = "Error creating comment: #{#comment.errors}"
redirect_to matter_item_url(#matter, #item)
end
end
def destroy
#comment_item = CommentItem.find(params[:id])
#comment_item.destroy
redirect_to(#comment_item.item)
end
private
def set_comment_item
#comment_item = CommentItem.find(params[:id])
end
def comment_item_params
params.require(:comment_item).permit(:name, :body, :item_id, :matter_id)
end
end
The show action for the item resource:
<p>
<strong>Matter:</strong>
<%= #item.matter_id %>
</p>
<p>
<strong>Content:</strong>
<%= #item.content %>
</p>
<hr />
<%= form_for #comment_item, url: matter_item_comment_items_path(matter_id: #item.matter, item_id: #item.id) do |f| %>
<% if #comment_item.errors.any? %>
<ul>
<% #comment_item.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
<%= f.hidden_field :item_id %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :body %><br />
<%= f.text_area :body %>
</p>
<p>
<%= f.submit "Post Comment" %>
</p>
<% end %>
<%= render :partial => 'comment_item', :collection => #item.comment_items %>
<%= link_to 'Edit', edit_matter_item_path(id: #item.id) %> |
<%= link_to 'Back', matter_items_path %>
Routes
resources :items do
resources :comment_items
end
resources :matters do
resources :items do
resources :comment_items
end
end
When looking at CommentItems in the console, I see that the comments are in fact being added to the model with their correct ID's, but they don't seem to be passed as parameters.. What am I missing?
I've reviewed Rails 4 form_for double nested comments and Rails 3.2 - Nested Resource Passing ID but I didn't have much luck..
I'd really appreciate your help!
No route matches {:action=>"show", :controller=>"items", :item_id=>"141", :matter_id=>"3"} missing required keys: [:id]
your request is going to ItemsController instead of CommentItemsController
see :controller => "items"

Error: param is missing or the value is empty: thing

I'm using rails 4.0.8. I added a comment section to a model called 'Things', but I keep getting the same error "param is missing or the value is empty: thing" when I press the submit comment button. It says the error is in the Things#Controller. What am I doing wrong?
UPDATE: I removed the url path from the form, but a new error returns "Couldn't find Thing without an ID". The error is in Comments#Controller.
VIEW FOR THING/SHOW
<div id= "thing">
<h1>
<%= #thing.name %>
</h1>
<br>
<div id= "commentsection">
Comments
<div id= "comments">
<br>
<% #thing.comments.each do |c| %>
<%= c.username %>
<br>
<%= c.text %>
<% end %>
<%= form_for #comment, :url => thing_path do |f| %>
<%= f.label :username %>
<%= f.text_field :username %>
<%= f.label :comment %>
<%= f.text_field :text %>
<%= f.submit "Enter", class: "btn btn-small btn-primary" %>
<% end %>
</div>
</div>
</div>
THINGS CONTROLLER
class ThingsController < ApplicationController
def show
#thing = Thing.find(params[:id])
#thing.comments.build
#comment = Comment.new
end
def index
end
def new
#thing = Thing.new
#things = Thing.all
end
def create
#thing = Thing.new(thing_params)
if #thing.save
redirect_to #thing
else
render 'new'
end
end
private
def thing_params
params.require(:thing).permit(:name, :avatar)
end
end
COMMENTS CONTROLLER (I put asterisks around the line where the error is)
class CommentsController < ApplicationController
def show
#comment = Comment.find(params[:id])
end
def new
#comment = Comment.new
#comments = Comment.all
end
def create
****#thing = Thing.find(params[:thing_id])****
#comment = #thing.comments.create(comment_params)
redirect_to thing_path(#thing)
end
end
private
def comment_params
params.require(:comment).permit(:user, :text, :upvotes, :downvotes, :thing_id)
end
end
ROUTES
Website::Application.routes.draw do
get "comments/new"
get "comments/show"
get "things/new"
root 'home_page#home'
get "all/things/new" => 'things#new'
get "all/allthings"
resources :things
resources :good_comments
get "things/show"
get "things/results"
end
You are posting the #comment form to post '/things' path.
<%= form_for #comment, :url => thing_path do |f| %>
It should just be <%= form_for #comment do %> (Rails is smart enough to plug in the comments_path) or if you feel like being more explicit (even though it's not necessary)
<%= form_for #comment, url: :comments_path do %>
Another note though, if you want that Comment to be tied to that specific Thing then in your models it should be
Class Thing
has_many :comments
end
Class Comment
belongs_to :thing
end
Then make sure in your database comment has a thing_id foreign_key field and then your form for comment should actually look like
<%= form_for #thing, #comment do %>
<% end %>

Resources