Rails 4: No route matches - issue with relationships missing id key - ruby-on-rails

I am hoping someone can help me. I am getting the following issue:
No route matches {:action=>"show", :controller=>"stocks", :stockpile_id=>#<Stock id: 17, stockpile_id: 3, code: "rttrtrt", name: "", description: "", quantity: nil, cost_pence: nil, information: "", created_at: "2013-08-18 19:52:46", updated_at: "2013-08-18 19:52:46">, :id=>nil, :format=>nil} missing required keys: [:id]
When visiting the following URL: /admin/stockpiles/3/stocks/
My routes look like:
scope '/admin' do
root :to => 'admin#index', :as => 'admin'
resources :stockpiles,:companies
scope :path => 'stockpiles/:stockpile_id' do
resources :stocks
end
end
The data contained in the error message:
id | stockpile_id | code | name | description | quantity | cost_pence | information | created_at | updated_at
17 | 3 | rttrtrt | | | | | | 2013-08-18 19:52:46.856864 | 2013-08-18 19:52:46.856864
My Stock Model:
class Stock < ActiveRecord::Base
belongs_to :stockpile
end
Nothing interesting in the Stockpile model, just that it has many stocks..
Here is my controller:
class StocksController < ApplicationController
before_action :set_stock, only: [:show, :edit, :update, :destroy]
def index
#stockpile = Stockpile.find(params[:stockpile_id])
#stocks = #stockpile.stocks.all
end
def show
end
def new
#stockpile = Stockpile.find(params[:stockpile_id])
#stock = #stockpile.stocks.new
end
def edit
end
def create
#stockpile = Stockpile.find(params[:stockpile_id])
#stock = #stockpile.stocks.new(stock_params)
if #stock.save
redirect_to #stock, notice: 'Stock was successfully created.'
else
render action: 'new'
end
end
def update
if #stock.update(stock_params)
redirect_to #stock, notice: 'Stock was successfully updated.'
else
render action: 'edit'
end
end
def destroy
#stock.destroy
redirect_to stocks_url, notice: 'Stock was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_stock
#stockpile = Stockpile.find(params[:stockpile_id])
#stock = #stockpile.stocks.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def stock_params
params.require(:stock).permit(:code, :name, :description, :quantity, :cost_pence, :information)
end
end
And here is the view in question:
<div class="page-header">
<%= link_to new_stock_path(params[:stockpile_id]), :class => 'btn btn-primary' do %>
<i class="icon-plus icon-white"></i>
New Stock
<% end %>
<h1>Listing stocks</h1>
</div>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Stockpile</th>
<th>Code</th>
<th>Name</th>
<th>Description</th>
<th>Quantity</th>
<th>Cost pence</th>
<th>Information</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% #stocks.each do |stock| %>
<tr>
<td><%= stock.stockpile %></td>
<td><%= stock.code %></td>
<td><%= stock.name %></td>
<td><%= stock.description %></td>
<td><%= stock.quantity %></td>
<td><%= stock.cost_pence %></td>
<td><%= stock.information %></td>
<td><%= link_to 'Show', stock %></td>
<td><%= link_to 'Edit', edit_stock_path(stock) %></td>
<td><%= link_to 'Destroy', stock, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</tbody>
</table>
Help would be much appreciated - looks like something weird is going on because stockpile_id seems to be set to stock, and there seems to be no stock params or anything - so we get the missing id error.
Thanks.

It would appear that you need to pass in the stockpile as well as the stock..
<td><%= link_to 'Show', [#stockpile, stock] %></td>
Should do that.
As opposed to using the scope you can probably just use a nested resource in your routes
resources :stockpiles do
resources :stocks
end
and then you can DRY up your stock controller
class StocksController < ApplicationController
before_action :set_stockpile
.....
def set_stockpile
#stockpile = Stockpile.find params[:stockpile_id]
end

Related

ActionController::UrlGenerationError in Interfaces#index

I am trying to delete my interface,and it said
No route matches {:action=>"show", :controller=>"interfaces", :project_id=>#}, missing required keys: [:id].
Because I do not know which arguments should be put into <%=link_to '删除', project_interface_path()%>
I have tried many different arguments into a path.
interface_controller.rb
def destroy
#interface = #project.interfaces.find(params[:project_id])
redirect_to project_interfaces_path if #interface.destroy
end
def index
#interfaces = Interface.all
#project = Project.find(params[:project_id])
end
def new
#project = Project.find(params[:project_id])
#interface = Interface.new
end
def create
#project = Project.find(params[:project_id])
#interface = #project.interfaces.new(interface_params)
if #interface.save
redirect_to project_interfaces_path
else
render :new
end
end
interface/index.html.erb
<% #interfaces.each do |interface| %>
<tr>
<th scope="row">1</th>
<td><%=interface.name %></td>
<td><%=interface.desp %></td>
<td><%=interface.method_type_id %></td>
<td><%=interface.request_url %></td>
<td><%=interface.request_eg %></td>
<td><%=interface.response_eg %></td>
</tr>
<td><%= link_to '删除', project_interface_path(interface),method: :delete, data:{confirm:'确定要删除吗?'}, class: 'badge badge-dark' %></td>
This is my route file:
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root "method_types#index"
resources :method_types
resources :field_types
resources :projects do
resources :interfaces
end
end
Try this:
<%= link_to '删除', project_interface_path(#project.id, interface.id),method: :delete, data:{confirm:'确定要删除吗?'}, class: 'badge badge-dark' %></td>

Rails "No route matches POST /images/1" error

I looked through several other similar help questions, and I'm not seeing my error. I have destroy, new, create all working, but post and show throw errors. Also oddly enough, clicking the 'edit' button on the index view throws an error, but going directly to http://localhost:3000/images/1 gives me the 'show' page (no idea why it isn't giving an edit page).
relevant files:
images_controller.rb
class ImagesController < ApplicationController
def index
#images = Image.all
end
def new
#image = Image.new
end
def create
#image = Image.new(image_params)
if #image.save
redirect_to images_path, notice: "Your image #{#image.name} has been uploaded."
else
render "new"
end
end
def edit
#image = Image.find(params[:id])
end
def destroy
#image = Image.find(params[:id])
#image.destroy
redirect_to images_path, notice: "The image #{#image.name} has been removed from the database."
end
def show
#image = Image.find(params[:id])
end
private
def image_params
params.require(:image).permit(:name, :attachment)
end
end
routes.rb
Rails.application.routes.draw do
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
resources :images#, only: [:index, :new, :create, :update, :edit, :show, :destroy]
root "images#index"
end
Note: I have also added the lines
get 'images/edit'
get 'images/details'
But to no avail.
index.html.erb:
<% if !flash[:notice].blank? %>
<div class="alert alert-info">
<%= flash[:notice] %>
</div>
<% end %>
<br />
<%= link_to "New Image", new_image_path, class: "btn btn-primary" %>
<br />
<br />
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>View Link</th>
<th> </th>
</tr>
</thead>
<tbody>
<% #images.each do |image| %>
<tr>
<td><%= image.name %></td>
<td><%= link_to "#{image.name}", image.attachment_url %></td>
<td><%= button_to "Edit", image, method: :edit, class: "btn btn-primary", confirm: "edit #{image.name}?" %></td>
<td><%= button_to "Show", image, method: :show, class: "btn btn-primary"%></td>
<td><%= button_to "Delete", image, method: :delete, class: "btn btn-danger", confirm: "Are you sure that you wish to delete #{image.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>
I suppose there are no HTTP methods like this:
method: :edit, method: :show
Try to do smth like this:
link_to "Edit", edit_image_path(image)
link_to "Show", image_path(image)
And remove this line from routes.rb
get 'images/edit'
resources has already created rout to edit action for you. You can see it http://localhost:3000/rails/info/routes
button_to by default will make post request you need link_to "edit" to make get request. when you type in your browser http://localhost:3000/images/1 you are making get request so it works.
link_to "Edit", edit_image_path image
check these links for link_to and button_to
http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to
http://apidock.com/rails/ActionView/Helpers/UrlHelper/button_to

Rails - Updating records using Best in Place

I'm building a marketplace app where I'm trying to use the Best in Place gem to allow sellers to add a tracking number for each of their orders.
I get a NoMethodError which I'm not able to resolve.
NoMethodError in Orders#sales
undefined method `tracking' for nil:NilClass
The error points to the best in place line below in the view page. This view page is based on the method Sales (in the controller below) where I filter for orders for that particular seller.
Here is my routes.rb with order routing. Since orders need not be edited or destroyed, I didn't create an edit or delete route.
resources :listings do
resources :orders, only: [:new, :create, :update]
collection { post :import }
end
Here is a snippet from my orders controller
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
before_action :check_user, only: [:edit, :update]
def sales
#orders = Order.all.where(seller: current_user).order("created_at DESC")
end
def update
#order.update_attributes(params[:order])
end
def check_user
if current_user.id != #seller && current_user.name != "admin admin"
redirect_to root_url, alert: "Sorry, you are not the seller of this listing"
end
end
Here is my view page:
<table class="table table-striped table-bordered">
<tr>
<th class="col-md-2">Image</th>
<th class="col-md-2">Item</th>
<th class="col-md-1">Price</th>
<th class="col-md-2">Customer</th>
<th class="col-md-2">Date Sold</th>
<th class="col-md-2">Shipment Tracking #</th>
<th class="col-md-1">Carrier (UPS, USPS, etc.)</th>
</tr>
<% #orders.each do |order| %>
<tr>
<td><%= image_tag order.listing.image.url(:thumb) %></td>
<td><%= order.listing.name %></td>
<td><%= number_to_currency(order.listing.price) %></td>
<td><%= order.buyer.name %></td>
<td><%= order.created_at.strftime("%B %-d, %Y") %></td>
<td><%= best_in_place #order, :tracking, :type => :input %> </td>
<td><%= best_in_place #order, :carrier, :type => :input %></td>
</tr>
<% end %>
</table>
Been stuck on this for a while. Appreciate any help on this.
I think the problem is that you are calling #order inside your .each method.
Try:
<%= best in place order, :tracking, :type => :input %>
You will need to change the next line in your view as well.
I figured it out. The problem was that since I was using best_in_place in a non-Activerecord environment (as part of a table with a list of orders), I needed to pass the order id explicitly. I found this in the best_in_place documentation https://github.com/bernat/best_in_place#non-active-record-environments
I created a custom route for the update action
put 'orderupdate' => "orders#update"
Then in my do loop in the view, I used the custom path for the route above and passed the order id to that route.
<% #orders.each do |order| %>
<tr>
<td><%= order.id %></td>
<td><%= image_tag order.listing.image.url(:thumb) %></td>
<td><%= order.listing.name %></td>
<td><%= number_to_currency(order.listing.price) %></td>
<td><%= order.buyer.name %></td>
<td><%= order.created_at.strftime("%B %-d, %Y") %></td>
<td><%= best_in_place order, :tracking, :type => :input, :url => orderupdate_path(id: order.id) %> </td>
<td><%= best_in_place order, :carrier, :type => :input, :url => orderupdate_path(id: order.id) %> </td>
</tr>
<% end %>
Here is the update method in my controller:
def update
#order = Order.find(params[:id])
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to sales_url, notice: 'Order updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
Hope this helps someone!

Rails 4 uninitialized constant Admin::Category

I have generated Admin namespaced Controllers for all my default models as follows:
rails g scaffold_controller admin/categories name:string slug:string description:string icon_xlarge:string icon_large:string icon_medium:string icon_small:string status:integer
This generated the following files:
Harshas-MacBook-Pro:nomad harshamv$ rails g scaffold_controller admin/categories name:string slug:string description:string icon_xlarge:string icon_large:string icon_medium:string icon_small:string status:integer
Plural version of the model detected, using singularized version. Override with --force-plural.
create app/controllers/admin/categories_controller.rb
invoke erb
create app/views/admin/categories
create app/views/admin/categories/index.html.erb
create app/views/admin/categories/edit.html.erb
create app/views/admin/categories/show.html.erb
create app/views/admin/categories/new.html.erb
create app/views/admin/categories/_form.html.erb
invoke test_unit
create test/controllers/admin/categories_controller_test.rb
app/model/category.rb
class Category < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
has_and_belongs_to_many :venues
end
app/controller/admin/categories_controller.rb
class Admin::CategoriesController < ApplicationController
before_action :set_admin_category, only: [:show, :edit, :update, :destroy]
# GET /admin/categories
def index
#admin_categories = Admin::Category.all
end
# GET /admin/categories/1
def show
end
# GET /admin/categories/new
def new
#admin_category = Admin::Category.new
end
# GET /admin/categories/1/edit
def edit
end
# POST /admin/categories
def create
#admin_category = Admin::Category.new(admin_category_params)
if #admin_category.save
redirect_to #admin_category, notice: 'Category was successfully created.'
else
render :new
end
end
# PATCH/PUT /admin/categories/1
def update
if #admin_category.update(admin_category_params)
redirect_to #admin_category, notice: 'Category was successfully updated.'
else
render :edit
end
end
# DELETE /admin/categories/1
def destroy
#admin_category.destroy
redirect_to admin_categories_url, notice: 'Category was successfully destroyed.'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_admin_category
#admin_category = Admin::Category.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def admin_category_params
params.require(:admin_category).permit(:name, :slug, :description, :icon_xlarge, :icon_large, :icon_medium, :icon_small, :status)
end
end
app/view/admin/categories/index.html.erb
<h1>Listing admin_categories</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Slug</th>
<th>Description</th>
<th>Icon xlarge</th>
<th>Icon large</th>
<th>Icon medium</th>
<th>Icon small</th>
<th>Status</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #admin_categories.each do |admin_category| %>
<tr>
<td><%= admin_category.name %></td>
<td><%= admin_category.slug %></td>
<td><%= admin_category.description %></td>
<td><%= admin_category.icon_xlarge %></td>
<td><%= admin_category.icon_large %></td>
<td><%= admin_category.icon_medium %></td>
<td><%= admin_category.icon_small %></td>
<td><%= admin_category.status %></td>
<td><%= link_to 'Show', admin_category %></td>
<td><%= link_to 'Edit', edit_admin_category_path(admin_category) %></td>
<td><%= link_to 'Destroy', admin_category, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Category', new_admin_category_path %>
My Attempts
I edited the Controller as below
# GET /admin/categories
def index
#admin_categories = Category.all
end
# GET /admin/categories/1
def show
end
# GET /admin/categories/new
def new
#admin_category = Category.new
end
# GET /admin/categories/1/edit
def edit
end
# POST /admin/categories
def create
#admin_category = Category.new(admin_category_params)
if #admin_category.save
redirect_to #admin_category, notice: 'Category was successfully created.'
else
render :new
end
end
When I go to localhost/admin/categories and click "NEW category", I get the following error now:
My routes file:
Rails.application.routes.draw do
# Admin Routing
namespace :admin do
resources :categories, :cities, :countries, :lists, :oauths, :regions, :tags, :users, :user_groups, :venues, :venue_photos, :venue_reviews
end
end
You have resources :categories defined under the namespace :admin in your routes.rb,so this line in your views/admins/categories/_form.html.erb
<%= form_for(#admin_category) do |f| %>
should be
<%= form_for([:admin, #admin_category]) do |f| %>
For more info,refer this API
Update
The second error is because of this line
params.require(:admin_category).permit(:name, :slug, :description, :icon_xlarge, :icon_large, :icon_medium, :icon_small, :status)
It should be
params.require(:category).permit(:name, :slug, :description, :icon_xlarge, :icon_large, :icon_medium, :icon_small, :status)
To access models outside of the namespace you need to call ::Category.new instead of Admin::Category.new
As your error indicates, this is an issue with how you are calling your form. Your form needs to reference the admin namespace, like this:
<%= form_for [:admin, #category] do |f| %>
However, there are a number of things different about the way the scaffold built your docs from how I would recommend.
I would also suggest simplifying the code in the scaffolded controller to reference simple #category and #categories, rather than #admin_category and #admin_categories.
Also, the model should not be in the admin namespace, so Admin::Category.new should be Category.new. The rest of the model calls should be adjusted accordingly as well.

Link_to create with parameter before - ForbiddenAttributesError now

What I Want:
I need in a view a button or a link (it doesn't matter) to the create action of Reservation controller and to give it a parameter too.
And resolve the ForbiddenAttributesError that now gives me.
Here are my model and controller:
Reservation model
class Reservation < ActiveRecord::Base
belongs_to :user
belongs_to :dinner
end
Reservation controller
class ReservationsController < ApplicationController
load_and_authorize_resource
def show
#reservations = Reservation.joins(:user).where('dinner_id' => params[:dinner_id]).select("users.*,reservations.*")
#dinnerid = params[:dinner_id]
respond_to do |format|
format.html
format.json { render :json => #reservations }
end
end
def create
#reservation = Reservation.new(params[:reservation])
#reservation.user_id = current_user.id
respond_to do |format|
if #reservation.save
format.html { redirect_to #reservation, notice: 'Reservation was successfully created.' }
format.json { render :show, status: :created, location: #reservation }
else
format.html { render :show }
format.json { render json: #reservation.errors, status: :unprocessable_entity }
end
end
end
# Never trust parameters from the scary internet, only allow the white list through.
def reservation_params
params.require(:reservation).permit(:dinner_id)
end
end
EDIT: After the suggestion of #Rahul Singh this is my actual code with relative error:
<p id="notice"><%= notice %></p>
<table>
<thead>
<tr>
<th>Id</th>
<th>User id</th>
<th>Dinner id</th>
<th>User email</th>
<th>User name</th>
</tr>
</thead>
<tbody>
<% #reservations.each do |reservation| %>
<tr>
<td><%= reservation.id %></td>
<td><%= reservation.user_id %></td>
<td><%= reservation.dinner_id %></td>
<td><%= reservation.user.email %></td>
<td><%= reservation.user.name %></td>
</tr>
<% end %>
</tbody>
</table>
<br/>TRY 00a <br/>
<%= form_for(Reservation.new) do |f| %>
<%= f.hidden_field( :dinner_id, :value => #dinnerid.to_s) %>
<%= f.submit "Join1" %>
<% end %>
<br/> !!!!!!!!!!ERROR : ActiveModel::ForbiddenAttributesError
<br/>TRY 00b <br/>
<%= link_to "Join1", reservations_path(dinner_id:#dinnerid.to_s), method: :post %>
<br/> !!!!!!!!!!ERROR : param is missing or the value is empty: reservation
I provide a sreenshot for the error :
Error of the form : https://www.dropbox.com/s/i2x1m520ptqdj56/createReservationForm.jpg
Error of the link_to : https://www.dropbox.com/s/8xjwee5oo7q6uhk/createReservationLink_to.jpg
This should work
<%= form_for(Reservation.new) do |f| %>
<%= f.hidden_field( :dinner_id, :value => #dinnerid.to_s) %>
<%= f.submit "Join1" %>
<% end %>
clicking on Join1 button will submit form to ReservationsController create action.
and with link try this
<%= link_to "Join1", reservations_path(dinner_id:#dinnerid.to_s), method: :post %>
for above to work,add following in your routes.rb
resources :reservations
Change this line -> #reservation = Reservation.new(params[:reservation])
To this -> #reservation = Reservation.new reservation_params
and try again ;).
I'm wondering if it wouldn't be better to have your reservation routes as a nested resource of dinners.
It seems reservations can't exist without a dinner, so I'd make that explicit like this:
# config/routes.rb
resources :dinners do
resources :reservations
end
Run rake routes to see how this would change the routes.
You'd now have the dinner id passed along:
# app/views/dinners/show.html.erb
<%= button_to 'Reserve this dinner', dinner_reservations_path(#dinner) %>
The button would route to the create action because a button's default HTTP method is POST.
# app/controllers/reservations_controller.rb
class ReservationsController < ApplicationController
before_action :set_dinner
def create
#dinner.reservations.create! user: current_user
# would render reservations/create.html.erb
end
private
def set_dinner
#dinner = Dinner.find(params[:id])
end
end
This doesn't fix your immediate problem of just getting that link to work. But I think you'd be a lot better served structuring your app more like the above going forward.
Full disclosure: the person who asked this question contacted me on twitter personally, so I took some liberties in answering this question with a more general design suggestion.
I'm not sure this is the "best" approach but I think its the easiest one.
You could do something with string interpolation:
a href="/reservations?dinner=#{dinner.id}" Join
then you could get the paramter with
params[:dinner]

Resources