rails nested resources no route matches missing required key [:id] - ruby-on-rails

I have a very simple case of nested resources but I am having trouble to get them to work.
My models:
class TodoList < ActiveRecord::Base
has_many :todo_items, dependent: :destroy
class TodoItem < ActiveRecord::Base
belongs_to :todo_list
My controller:
class TodoItemsController < ApplicationController
before_action :set_todo_list
before_action :set_todo_item, only: [:show, :edit, :update, :destroy]
def show
end
private
def set_todo_item
#todo_item = #todo_list.todo_items.find(params[:id])
end
def set_todo_list
#todo_list = TodoList.find(params[:todo_list_id])
end
My show.html.erb:
<%= link_to 'Edit', edit_todo_list_todo_item_path([#todo_item.todo_list, #todo_item]) %>
I got the error
"No route matches {:action=>"edit", :controller=>"todo_items", :id=>nil, ..., missing required keys: [:id].
I know the todo_item_id is missing, but I couldn't figure out why. When I debug, I saw that both #todo_list and #todo_item were getting values. But as soon as the #todo_item was assigned, this error would rise. What did I do wrong? How can I correct this? Any insights will be appreciated.

Try this:
<%= link_to 'Edit', edit_todo_list_todo_item_path(#todo_item.todo_list, #todo_item) %>
or:
<%= link_to 'Edit', edit_todo_list_todo_item_path(todo_list_id: #todo_item.todo_list.id, id: #todo_item.id) %>

Related

undefined method `each' for nil:NilClass error for index

I created a seed which I made sure worked by testing it in the rails console beforehand. Now I am trying show the instance variable #services in my view, but I have an error that says it's nill.
Any ideas?
Thank you
//home.html.erb
<div>
<% #services.each do |service| %>
<%= service.name %>
<% end %>
</div>
//services_controller.rb
class ServicesController < ApplicationController
before_action :set_service, only: [:index, :show]
def index
#services = Service.all
end
def show
set_service
end
private
def set_service
#service = Service.find(params[:id])
end
end
//service.rb
class Service < ApplicationRecord
validates :name, presence: true
validates :description, presence: true
has_many :reviews
end
This is the error that's being rendered
undefined method `each' for nil:NilClass
add root URL mapping, and point it to services index action, as in root 'services#index' in config/routes.rb
move content of home.html.erb to views/services/index.html.erb
change before_action :set_service, only: [:index, :show] to before_action :set_service, only: :show
See the comments on question :)
Change this code:
before_action :set_service, only: [:index, :show]
To this:
before_action :set_service, only: [:show]

undefined local variable or method `product' for #<#<Class:0x007fe77c4f3c68>:0x007fe77c69cb78>

I´m having a problem with an app that I´m building.
in products/show.html.erb I have this code to add product to cart.
<%= button_to product_items_path(product_id: product) do %>
<i class="fa fa-shopping-cart"></i>Add to Cart
<% end %>
And it always gives me this error undefined local variable or method 'product' for #<#<Class:0x007fe77c4f3c68>:0x007fe77c69cb78>
This error is happening in the first line According to Better Error gem
I'am using ActiveAdmin but I'm pretty sure that the error is not appearing because of that.
I'm not sure why this is happening, to me the code seems good but I must be overseeing something.
It would be great if someone could take look and maybe see what I´m not seeing.
This is the `ProductItemsController.rb``
class ProductItemsController < ApplicationController
include CurrentCart
before_action :set_cart, only: [:create]
before_action :set_product_item, only: [:show, :destroy]
def create
product = Product.find(params[:product_id])
#product_item = #cart.add_product(product.id)
if #product_item.save
redirect_to root_url, notice:'Product added to Cart'
else
render :new
end
end
private
def set_product_items
#product_item = ProductItem.find(params[:id])
end
def product_item_params
params.require(:product_item).permit(:product_id)
end
end
And here is the ProductsController.rb
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
def show
end
private
def set_product
#product = Product.find(params[:id])
end
def product_params
params.require(:product).permit(:name, :description, :price_usd, :price_isl, :image, :category_id)
end
end
this is the routes.rbfile
Rails.application.routes.draw do
resources :categories
resources :labels
resources :products
resources :carts
resources :product_items
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
root 'pages#index'
Only instance variables are available to the view.
def create
#product = Product.find(params[:product_id]) # Prefix variable name with #
#product_item = #cart.add_product(product.id)
if #product_item.save
redirect_to root_url, notice:'Product added to Cart'
else
render :new
end
end
And your view:
<%= button_to product_items_path(#product) do %>
<i class="fa fa-shopping-cart"></i>Add to Cart
<% end %>
You should be able to just pass in the object to the _path helper.

Rails: ActionController::UrlGenerationError, No route matches, missing required keys

The following error is displayed when I try to create new data.
ActionController::UrlGenerationError (No route matches {:room_id=>nil, :action=>"index", :controller=>"events"} missing required keys: [:room_id]):
models
models/rooms.rb
has_many :events, inverse_of: :room, dependent: :destroy
has_many :amounts, inverse_of: :room, dependent: :destroy
accepts_nested_attributes_for :events, allow_destroy: true
models/events.rb
has_one :amount, inverse_of: :schedule, dependent: :destroy
accepts_nested_attributes_for :amount, allow_destroy: true
routes.rb
...
resources :events, only: [:new, :create, :edit, :update]
resources :rooms do
resources :events
end
...
When I click link_to for new_room_event_path(1), the above error is displayed.
It generates root/rooms/1/events/new.
view
<% if logged_in? %>
<% if current_user?(#user) %>
<% if schedule.rooms.blank? %>
<%= link_to "Add event", new_room_event_path(1), class: "btn btn-sn btn-primary" %>
<br>
<% end %>
<% end %>
<% end %>
The reason why I designate new_room_event_path(1) is that this is first time to create data.
events_controller.rb
before_action :load_room
def new
#event = Event.new
#event.room = #room
#event.build_amount
#event.amount.schedule = #room.schedule
#event.amount.room = #room
end
private
def load_room
if Room.exists?(id: params[:room_id])
#room = Room.find(params[:room_id])
else
#room = Room.new
end
end
It could be appreciated if you could give me any suggestion.
First, I would recommend removing the resources :events, only: [:new, :create, :edit, :update] from the routes file since you are using events as a nested resource under rooms.
Second, if you are creating a room that doesn't exist, it would probably be better to send them to the actual new_room_path where a room can be created, and you can make it a nested form if you want them to be able to add event(s) at the same time as creating the new room. If the room does already exist, then you can use the nested route as it was designed with new_room_event_path(room)
Looks like you were missing an association to room from your event model, don't forget
# models/event.rb
belongs_to :room
And then from your EventsController you can do this and not worry about a nil room
# controllers/events_controller.rb
before_action :set_room
before_action :set_event, only: [:show, :edit, :update, :destroy]
private
def set_room
#room = Room.find(params[:room_id])
end
def set_event
#event = Event.find(params[:id])
end
See http://guides.rubyonrails.org/routing.html#nested-resources for more details on nested resources
In your events controller, in the new action, change it to #room = #event.room. Your error is saying that it can't find a room_id. The way you have written it in your controller you are asking your new method to set #event.room to #room, but it's the first time the method has seen #room and has no idea what it is. By saying #room = #event.room, the new action understands as you have already, in the lines above, defined what #event is and so assigns the room_id to that #event.

Problems using namespaced models and controllers in Rails

I'm developing a Ruby on Rails app and I'm trying to organize my code a bit better. Part of the app is a knowledgebase which is organized into categories and articles - pretty standard stuff.
Here is the way I have everything set up (at least what I think is important):
routes.rb
namespace :knowledgebase do
resources :categories
resources :articles
end
models/knowledgebase/article.rb
class Knowledgebase::Article < ActiveRecord::Base
self.table_name = 'knowledgebase_articles'
belongs_to :category, class_name: 'Knowledgebase::Category', foreign_key: 'knowledgebase_category_id'
end
models/knowledgebase/category.rb
class Knowledgebase::Category < ActiveRecord::Base
self.table_name = 'knowledgebase_categories'
has_many :articles, class_name: 'Knowledgebase::Article'
end
controllers/knowledgebase/articles_controller.rb
class Knowledgebase::CategoriesController < ApplicationController
load_and_authorize_resource
before_action :authenticate_user!
before_action :set_category, only: [:show, :edit, :update, :destroy]
def new
#category = ::Knowledgebase::Category.new
end
def create
#category = ::Knowledgebase::Category.new(category_params)
if #category.save
redirect_to knowledgebase_categories_url, notice: '...'
else
render :new
end
end
# ...
private
def set_category
#category = ::Knowledgebase::Category.find(params[:id])
end
def category_params
params.require(:category).permit(:title)
end
end
views/knowledgebase/categories/_form.html.erb
<%= form_for #category do |form| %>
<%= form.text_field :title
<%= form.submit %>
<% end %>
My Problem: when I try to submit the form (either new or edit) I get the error:
param is missing or the value is empty: category
When I setup the form like this: <%= form_for ([:knowledgebase, #category]) do |form| %> I get the following error:
undefined method `knowledgebase_knowledgebase_categories_path' for #<#<Class:0x007fecd7a78908>:0x007fecd707ad20>
The same goes for articles. I'm using Rails 4.2.3.
If anybody could help me or guide me into the right direction I would be really thankful - I have googled for three days now I tried everything I could think of.
Update 1
This is the params log generated:
{"utf8"=>"✓",
"authenticity_token"=>"fjOs...VA==",
"commit"=>"Category erstellen",
"knowledgebase_category"=>{"title"=>"Test Title"}}
As you look into the params hash, it has knowledgebase_category not category. So try changing category_params to the below
def category_params
params.require(:knowledgebase_category).permit(:title)
end
An Advice:
Always look into the generated params in the log. It really helps a lot in finding the solution to most of the errors.

Creating a new link_to for a nested resource

I'm trying to use the link_to helper function to create a new order for a particular product. Here is my:
product model
class Product < ActiveRecord::Base
has_many :orders
end
routes.rb
resources :products, :only => [:show, :new, :create, :index, :update, :destroy] do
resources :orders, :only => [:create]
end
view for product/show.html.erb
<%= link_to 'New Order', new_product_orders_path(#product) %>
controller for orders
class OrdersController < ApplicationController
def create
#order = Order.new
end
end
relevant rake routes:
product_orders POST /products/:product_id/orders(.:format) orders#create
But when I do that I get undefined method `new_product_orders_path'
Whats the correct way to do this in Rails 4?
In your routes add new action here
resources :orders, :only => [:create, :new]
Also your controller is missing new action, in your create action you need to save your record
class OrdersController < ApplicationController
before_filter :set_product
def new
#order = #product.orders.new
end
def create
#order = #product.orders.new(params[:order])
#order.save
end
private
def set_product
#product = Product.where("id =?", params[:product_id]).first
end
end
I think you need
resources :products, :only => [:show, :new, :create, :index, :update, :destroy] do
resources :orders, :only => [:create, :new]
end
You can also check your routes by typing '/rails/info/routes' at the end of your server path.

Resources