Simple Rails form: undefined method `categories_path' - ruby-on-rails

As a first-time Rails user, I have to say I'm loving the Rails way of doing things. However, I'm running into an issue trying to create a simple form. I get the following error:
undefined method `categories_path' for #<#<Class:0x007f0440365880>:0x007f0430256cd8>
I tried creating a categories_path method in the controller (though I'm not sure what it would be for), but that didn't fix the error. Any rails experts out there know what's going on?
Here's the relevant code:
views/category/new.html.erb
<%= form_for #category do |f| %>
<%= f.label :category %>
<%= f.text_field :name %><br />
<%= f.submit %>
<% end %>
routes.rb
Jackeyes::Application.routes.draw do
scope "/admin" do
resources :product, :category
end
end
category_controller.rb
class CategoryController < ApplicationController
def index
#category = Category.all
end
def new
#category = Category.new
end
def create
#category = Category.new(params[:category])
#category.save
end
end

Make your resources plural:
resources :products, :categories
And try again.

Related

undefined method `upload_path' - 'new' action in Ruby on Rails

This should be super simple, but I can't see what I'm doing wrong.
The form in the 'new' page for uploads is getting an error.
'Uploads' belong to 'Event'
'Event' has many 'Uploads'
routes.rb is (as far as I know) correct.
I'm planning on using Refile to upload files to S3 (as per this tutorial... not sure if this is relevant at all though)
Upload.rb
class Upload < ActiveRecord::Base
belongs_to :event
attachment :upload_file
end
Event.rb
class Event < ActiveRecord::Base
has_many :uploads
end
uploads_controller.rb
class UploadsController < ApplicationController
before_action :set_event
def new
#upload = #event.uploads.create
end
private
def set_event
#event = Event.find(params[:event_id])
end
end
Routes.rb
Rails.application.routes.draw do
devise_for :users
root 'pages#home'
resources :events do
resources :coupons
resources :uploads
member do
post :check
end
end
views/uploads/new.html.erb (example)
<%= form_for #upload do |f| %>
<%= f.text_field :name %>
<% end %>
When I navigate to the 'new' page, I get the following error:
undefined method `upload_path' for #<#:0x007fb8709229f0>
Why can't I add a new Upload associated with Event? I know I'm missing something super simple, but I can't put my finger on it.
As uploads is nested in events, you get url for your upload path as follow:
/events/1/uploads/new
In this case, you have to specify #event in your form_for method like this:
<%= form_for [#event, #upload] do |f| %>
Or simply
<%= form_for #event.upload do |f| %>
<%= f.text_field :name %>
<%= f.submit %>
<% end%>

Nested attributes wouldn't save in database

I have two models one Topic and Topic_Content.
With the following code
Route
resources :topics do
resources :topic_contents
end
Topic
class Topic < ActiveRecord::Base
has_one :topic_content
accepts_nested_attributes_for :topic_content
end
TopicContent
class TopicContent < ActiveRecord::Base
belongs_to :topics
end
Controller
class TopicsController < ApplicationController
def new
#topic = Topic.new
end
def create
# render text: params[:topic].inspect
#topic = Topic.new(topic_params)
#topic.save
end
private
def topic_params
params.require(:topic).permit(:title, topic_content_attributes: [:text])
end
end
View
<%= form_for #topic do |f| %>
<%= f.label 'Topic:' %>
<%= f.text_field :title %>
<%= f.fields_for :topic_contents do |tf| %>
<%= tf.label :text %>
<%= tf.text_area :text %> 
<% end %>  
<%= f.submit %>
<% end %>
The title will be saved correct in the topic table but the topic_content(text) wouldn't saved in the database, and I couldn't find the problem.
I'm not a Rails expert, but I'm certain you need to build the association in your controller.
In your new and edit actions you need to have:
def new
#topic = Topic.new
#topic_content = #topic.build_topic_content
end
Because this is a has_one/belongs_to you need to have it look that way. If it was a many association you'd build it with something like #topic_content = #topic.topic_contents.build.
I'm pretty sure it's just a matter of building the association in the right controller, which, I believe, for you, is the topic controller.
Your view should be as follow:
f.fields_for :topic_content do |content_fields|
^

Rails 4 Routing Error - no rout matches [POST] "/categories/new"

While learning Rails 4 I stuck while trying to add categories to posts of my simple blog. I have generated model, ran the migration and added a controller. No matter what I do now when trying to create a category, I keep running into same mistake: no route matches [POST], which is weird, as I seem to have all the code in place. Please help!
categories controller
class CategoriesController < ApplicationController
def index
#categories = Category.all
end
def new
#category = Category.new
end
def create
#category = Category.new(category_params)
#category.save
redirect_to new_category_path, alert: "Category created!"
end
def show
#category = Category.find(params[:id])
end
def destroy
#category = Category.find(params[:id])
#category.destroy
redirect_to categories_path
end
private
def category_params
params.require(:category).permit(:name)
end
end
routes.rb
Blog::Application.routes.draw do
get 'tags/:tag', to: 'posts#index', as: :tag
resources :categories
resources :posts do
resources :comments
end
root 'welcome#index'
end
category.rb
class Category < ActiveRecord::Base
validates :name, presence: true
has_many :posts
end
new.html.erb
<%= form_for :category do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
/categories/new
No route matches [POST] "/categories/new"
You should have in your view
<%= form_for #category do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
#category object is used by form_for method to figure out form url.
If you pass only Symbol to form_for method, without specifying url explicitly, form will be generated with url being the current url.
Although the #category works, if you read a bit further you will see that they will explain why the your code sends No route matches [POST] "/categories/new".
The guide actually explains that you need to specify the url: posts_path for the form to use the right route.
There's one problem with this form though. If you inspect the HTML
that is generated, by viewing the source of the page, you will see
that the action attribute for the form is pointing at /posts/new. This
is a problem because this route goes to the very page that you're on
right at the moment, and that route should only be used to display the
form for a new post.
The form needs to use a different URL in order to go somewhere else.
This can be done quite simply with the :url option of form_for.
Typically in Rails, the action that is used for new form submissions
like this is called "create", and so the form should be pointed to
that action.
Edit the form_for line inside app/views/posts/new.html.erb to look
like this:
<%= form_for :post, url: posts_path do |f| %>
In this example, the
posts_path helper is passed to the :url option. What Rails will do
with this is that it will point the form to the create action of the
current controller, the PostsController, and will send a POST request
to that route.

rails - update_attributes for just part of the model; file uploading

I want to add the ability of a user to have several pictures associated with his / her user account.
I have the following classes:
class User < ActiveRecord::Base
has_many :assets
accepts_nested_attributes_for :assets
end
class Asset < ActiveRecord::Base
belongs_to :assetable, :polymorphic => true
belongs_to :user
end
I want to have a screen that just has the upload image functionality:
def add_profile_picture
#user=User.find(params[:id])
1.times {#user.assets.build}
end
form:
<%= form_for #user do |u| %>
<%= u.fields_for :assets do |asset| %>
<%= asset.file_field :asset %>
<%= asset.text_field :description %><br />
<% end %>
<%=u.submit %>
<% end %>
When I submit, it looks like the id value goes in ok in development.log:
"id"=>"1"
but I get the error:
undefined method `update_attributes' for nil:NilClass
Since I just have the asset fields, is there anything special I need to do? Also, because the belongs_to :user exists, could that be causing problems?
Basically:
asset:
user_id:
assetable_type:
assetable_id:
Any help would be appreciated. Don't do much Rails forms stuff.
thx
edit #1
class UsersController < ApplicationController
def add_profile_picture
#user=User.find(params[:id])
1.times {#user.assets.build}
end
thx
Okay - there are a few problems with your code here. I would highly recommend you read both the Action Controller Overview and the Rails Routing guides to get some more information about this.
In any case, you're getting the error because the form you have there will be trying to use the users#update action in the UsersController.
You've got a couple options. One is to create the necessary routes for the custom action, or you can create a nested resource, and make a form for adding the asset.
In this case, you'd do something like this:
in routes.rb
resources :users do
resources :assets, :only => [:new, :create] # Or any other actions you might want. It's best practise to limit these.
end
Then, in the AssetsController, you can do something similar to this:
def new
#asset = Asset.new
end
def create
#asset = Asset.new(params[:asset])
#asset.user_id = params[:user_id] if params[:user_id]
#asset.save!
end
and your form will look something like this:
<%= form_for #asset do |f| %>
<%= f.file_field :asset %>
<%= f.text_field :description %><br />
<%=f.submit %>
<% end %>

Ruby on Rails - routing error when using nested resources with form helper

So I have a relationship where service has_many statuses
I have this in my routes.rb file
resources :services do
resources :statuses
end
and this is my statuses_controller file
class StatusesController < ApplicationController
def new
#status = Status.new(:parent_id => params[:parent_id])
end
def create
#service = current_user.services.find(params[:id])
#status = Status.new(params[:status])
if #status.save
flash[:notice] = "New status created."
else
flash[:error] = "Error creating new status."
end
redirect_to service_statuses_path
end
end
and I'm getting an error:
undefined method `statuses_path' for #<#<Class:0x000001045dbb28>:0x00000104554e48>
when trying to load:
http://localhost:3000/services/2/statuses/new
with the file views/statuses/new.html.erb
<%= form_for [#service, #status], :path =>service_statuses_path do |f|%>
<%= f.label :status %>
<%= f.text_field :state %><br />
<%= f.submit %>
<% end %>
Why is it giving me an undefined method `statuses_path' still?
Not sure this is the cause of error. But you have to change the method call
service_statuses_path
to
service_statuses_path(#service, #status)
which will generate the path like below.
/services/service_id/statuses/status_id

Resources