Rails form No Method Error - ruby-on-rails

I'm trying to put a simple form together, but I keep getting a no method error whenever I insert a form field into the html.
What's wrong here?
The Error:
undefined method `name' for #<Upload id: nil, created_at: nil, updated_at: nil>
new.html.erb
<h1>Uploads#new</h1>
<p>Find me in app/views/uploads/new.html.erb</p>
<% form_for :upload, :url => uploads_path do |f| %>
<p>
Name: <%= f.text_field :name %>
</p>
<p><%= submit_tag "Create Upload" %></p>
<% end %>
upload.rb
class Upload < ActiveRecord::Base
has_many :tasks
end
uploads_controller.rb
class UploadsController < ApplicationController
def index
#uploads = Upload.find(:all)
end
def new
#upload = Upload.new
end
def create
#upload = Upload.new(params[:project])
if #upload.save
flash[:notice] = "Film successfully uploaded"
redirect_to uploads_path
else
render :action => 'new'
end
end
end

From looking at the error, your upload model does not appear to have a name attribute. If you've added this, the maybe you have forgotten to migrate you database?

Related

Ruby on Rails 5 Nested comments not being created

I'm a beginner in rails and trying to create a Reddit type blog page. Currently, I'm working on nested comments so the user is able to reply to comments. In my app I have forums, posts and comments. Creating posts and forums has worked perfectly, also posting comments until I tried nesting replies. My code looks like this (Forums and Users models/controllers have been omitted) :
My Comment model:
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
belongs_to :user
has_many :comments, as: :commentable
end`
My Post model:
class Post < ApplicationRecord
belongs_to :forum
belongs_to :user
has_many :comments, as: :commentable, dependent: :destroy
end
My posts_controller:
class PostsController < ApplicationController
def index
#posts = Post.all
end
def show
#post = find_post
end
def new
#post = Post.new
end
def edit
#post = find_post
end
def create
#forum = Forum.find(params[:forum_id])
#post = #forum.posts.create(post_params.merge(user_id: current_user.id))
redirect_to forum_path(#forum)
end
def update
#post = find_post
if #post.update(post_params)
redirect_to forum_path
else
render 'show'
end
end
def destroy
#post = find_post
#post.destroy
redirect_to forum_path
end
private
def post_params
params.require(:post).permit(:title, :content)
end
private
def find_post
#forum = Forum.find(params[:forum_id])
#forum.posts.find(params[:id])
end
end
My comments_controller:
class CommentsController < ApplicationController
before_action :find_commentable
def index
#comments = Comment.all
end
def new
#comment = Comment.new
end
def create
#comment = #commentable.comments.create(comment_params.merge(user_id: current_user.id))
if #comment.save
#post = Post.find_by_id(params[:post_id])
redirect_to forum_post_path(#post.forum_id, #post), notice: 'Your comment was successfully posted!'
else
redirect_to forum_post_path(#post.forum_id, #post), notice: 'error :('
end
end
private
def comment_params
params.require(:comment).permit(:content)
end
private
def find_commentable
#commentable = Comment.find_by_id(params[:comment_id]) if params[:comment_id]
#commentable = Post.find_by_id(params[:post_id]) if params[:post_id]
end
end
My views/comments/_comment:
<li>
<%= comment.content %>
<small>Submitted <%= time_ago_in_words(comment.created_at) %> ago</small>
<h2>Add a Reply:</h2>
<%= form_with(model: [ comment, comment.comments.build ], local: true) do |form| %>
<p>
<%= form.text_area :content, placeholder: "Add a Reply" %><br/>
<%= form.submit %>
</p>
<% end %>
<ul>
<%= render partial: 'comments/comment', collection: comment.comments if comment.comments.any? %>
</ul>
<%= link_to 'Back', forum_post_path(#forum, #post) %>
My views/post/show:
<small>Submitted <%= time_ago_in_words(#post.created_at) %> ago</small>
<h3>Comments</h3>
<ul>
<%= render(partial: 'comments/comment', collection: #post.comments) if #post.comments.any?%>
</ul>
<h2>Add a comment:</h2>
<%= form_with(model: [ #post, #post.comments.build ], local: true) do |form| %>
<%= form.text_field :content, placeholder: "Add a comment" %><br/>
<%= form.submit "Add Comment" %>
<% end %>
<%= link_to 'Back', forum_path(#forum) %>
<%= link_to 'All posts', forum_posts_path(#post.forum_id) %>
<%= link_to 'All comments', post_comments_path(#post) %>
</li>
My routes:
resources :posts do
resources :comments
end
resources :comments do
resources :comments
end
The first errors I kept getting were that every time I submitted a comment in view/posts/show the comment wouldn't create. Now, views/comments/_comment lifts the error:
Showing /example/app/views/comments/_comment.html.erb where line #3 raised:
nil can't be converted to a Time value
<small>Submitted <%= time_ago_in_words(comment.created_at) %> ago</small>
after I submit a new comment. Any help regarding this error is appreciated or related to my main goal, I have been circling around this for a long time. Thanks!
The problem here is that new comment is initialized(for the comment which is being rendered) every time the partial is trying to render the comment.
Check out the following byebug output:
(byebug) pp comment.comments
[#<Comment:0x007f35ce11d900
id: 5,
content: "DEF",
commentable_id: 4,
commentable_type: "Comment",
user_id: 1,
created_at: Wed, 30 May 2018 06:53:51 UTC +00:00,
updated_at: Wed, 30 May 2018 06:53:51 UTC +00:00>,
#<Comment:0x007f35ce2a3388
id: nil,
content: nil,
commentable_id: 4,
commentable_type: "Comment",
user_id: nil,
created_at: nil,
updated_at: nil>]
This line is the culprit:
<%= form_with(model: [ comment, comment.comments.build ], local: true) do |form| %>
comment.comments.build initializes a new empty Comment which is your code then tries to render and throws the error as it does not have created_at.
And then the newly initialized comment is being rendered by the code.
Replacing app/views/comments/_comment#13 with the following will resolve the issue:
<%= render(partial: 'comments/comment', collection: comment.comments.where.not(content: nil)) if comment.comments.any? %>

Rails 5: fields_for nested_attributes does not save (fails at create controller)

I am trying to work in my first implementation using fields_for to manage creating has_many relationship in one form partial. This form partial itself is part of a nested resource
So far, I am able to render, save and edit the form successfully without the fields_for nested form.
When I include the fields_for in the form_for, white-list the params, and build the objects in #new, I get this error in the console as it failed to save and re renders the #new view:
(0.1ms) rollback transaction
What can I do to successfully save the form along with the nested_attributes?
routes.rb
....
resources :projects do
resources :step_ones
resources :step_threes
resources :step_twos
resources :step_fours
resources :step_fives
resources :timelines
end
step_four.rb
class StepFour < ApplicationRecord
belongs_to :project
has_many :ios_devices
accepts_nested_attributes_for :ios_devices
end
ios_device.rb
class IosDevice < ApplicationRecord
belongs_to :step_four
end
_form.html.erb
<div>
<%= form_for([#project, #step_four]) do |f| %>
....
<%= f.fields_for :ios_devices do |d| %>
<div class='form-group'>
<%= d.label :full_name, "Name:"%>
<%= d.text_field :full_name %>
<%= d.label :email, "Email:"%>
<%= d.text_field :email %>
<%= d.label :udid, "UDID:"%>
<%= d.text_field :udid %>
<% end %>
<%= hidden_field_tag :project_id, :value => #project.id %>
<div class='row'>
<span class='col-md-6'><%= button_to "Back", project_path(#project), method: :get, class:'btn btn-primary full-wide-button main-btn' %></span>
<span class='col-md-6'><%= f.submit 'Save Data', class: 'btn btn-primary full-wide-button'%></span>
</div>
<% end %>
</div>
step_fours_controller.rb
class StepFoursController < ApplicationController
def new
#project = Project.find(params[:project_id])
#step_four = StepFour.new
3.times { #step_four.ios_devices.build }
end
def create
#step_four = StepFour.new(step_four_params)
#project = Project.find(params[:project_id])
#step_four.ios_devices.each do |d|
puts d.full_name
puts d.email
puts d.udid
end
#step_four.project_id = params[:project_id]
if #step_four.save
flash[:success] = "Step Five Data Saved"
redirect_to #project
else
flash[:danger] = "Data Not Saved. Please Try Again"
render "new"
end
end
def show
#step_four = StepFour.where(project_id: (params[:project_id])).first
end
def update
#step_four = StepFour.where(project_id: (params[:project_id])).first
#project = Project.find(params[:project_id])
if #step_four.update_attributes(step_four_params)
flash[:success] = "Step Four Data Saved"
redirect_to #project
else
flash[:danger] = "Data Not Saved. Please Try Again"
render 'edit'
end
end
def edit
#step_four = StepFour.where(project_id: (params[:project_id])).first
#project = Project.find(params[:project_id])
end
def step_four_params
params.require(:step_four).permit(:iphone_name, :iphone_nickname, :android_name, ios_devices_attributes: [:id, :full_name, :email, :udid])
end
end
After realizing that the error was upon the save method, I tried to force the issue and raise an exception with a shebang ! . I received a Validation error that lead me to this question:
Error: Validation failed: Images imageable must exist , rails-5.0 , paperclip-5
I needed to add optional: true to the belongs_to: step_four in the ios_device model since, I believe that the object doesn't exist yet.
Now everything is working

Nested form attributes

I have one form working to save in the database but I want to save some fields that are going to be saved in a different record.
<%= form_for #complaint, url: {action: 'create'}, :html => {:multipart => true} do |f| %>
<%= f.text_field :complaint_info %>
<%= f.fields_for :witness do |witnesses_form| %>
<%= witnesses_form.text_field :name %>
<% end %>
<% end %>
In my controller:
def new
#complaint = Complaint.new
end
def create
#complaint = current_user.complaints.build(complaint_params)
if #complaint.save
redirect_to dashboard_complaint_path(#complaint)
else
render 'new'
end
end
private
def complaint_params
params.require(:complaint).permit(:complaint_info, witnesses_attributes: [:name])
end
on the model:
class Complaint < ActiveRecord::Base
belongs_to :user
has_many :witnesses
accepts_nested_attributes_for :witnesses
end
.
class Witness < ActiveRecord::Base
belongs_to :complaint
end
But I'm getting this error:
Unpermitted parameter: witness
Everything seems to be as it suppose to be, what am I missing here?
EDIT:
was able to save the record by adding:
#complaint.witnesses.build
to the create action in the controller but it is still not letting me save the :name there
<ActiveRecord::Relation [#<Witness id: 1, name: nil, phone: nil, complaint_id: 8, created_at: "2015-06-08 20:05:06", updated_at: "2015-06-08
EDIT 2:
Was able to fix it by moving the #complaint.witnesses.build from the create action to the new action and it fixed it, now I can create the record and lets me save the text_fields in it.
Can you try with changing your controller and views codes as following
In controller
def new
#complaint = Complaint.new
#witnesses = #complaint.witnesses.build
end
def edit
#witnesses = #complaint.witnesses
end
In views
<%= f.fields_for :witnesses, #witnesses do |witnesses_form| %>
<%= witnesses_form.text_field :name %>
<% end %>
I was able to fix it by adding #complaint.witnesses.build to the newaction instead of the create action.
So my controller now looks like this:
def new
#complaint = Complaint.new
#complaint.witnesses.build
end
def create
#complaint = current_user.complaints.build(complaint_params)
if #complaint.save
redirect_to dashboard_complaint_path(#complaint)
else
render 'new'
end
end
private
def complaint_params
params.require(:complaint).permit(:complaint_info, witnesses_attributes: [:name])
end

Cannot enter simply form information into SQLite DB (Rails)

So, I'm running into a fairly simple problem, where I cannot enter some simple form values into my SQLite DB (Rails).
Interestingly, the code doesn't fail - I submit the form, and am redirected successfully to the correct URL - and a record IS inserted into the DB, but the columns "name, type and user_id" are not filled with anything. To clarify, the columns are blank, for that new record.
If I comment out the code in the "create" and simply spit out the params (render plain: params[:plan].inspect) I do see all the correct parameters filled out, so I have a feeling there must be something wrong in the line:
#plan = Plan.new(params[:plan])
I'm really stuck here, any guidance would be much appreciated!
The create form
<h1> Create a new plan </h1>
<%= form_for :plan, url: plans_path do |f| %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :type %><br>
<%= f.text_field :type %>
</p>
<%= f.hidden_field :user_id, :value => current_user.id %>
<p>
<%= f.submit %>
</p>
<% end %>
plans_controller.rb
class PlansController < ApplicationController
def index
#plans = Plan.all
end
def show
#plan = Plan.find(params[:id])
end
def new
#plan = Plan.new
end
def create
#render plain: params[:plan].inspect
params.permit!
#plan = Plan.new(params[:plan])
if #plan.save
redirect_to #plan
else
redirect_to dashboard_path, :notice => "Plan NOT Created!"
end
end
end
The Model
class Plan < ActiveRecord::Base
end
Edit the plans_controller.rb:-
def create
#render plain: params[:plan].inspect
#plan = Plan.new(plan_params)
if #plan.save
redirect_to #plan
else
redirect_to dashboard_path, :notice => "Plan NOT Created!"
end
end
private
def plan_params
params.require(:plan).permit(:name,:type,:user_id)
end
Change the field name type as :-
rails g migration rename_fields_in_plans
class RenameFieldsInPlans < ActiveRecord::Migration
def change
rename_column :plans, :type, :plan_type
end
end
Then run the command:-
rake db:migrate

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