I have a form that saves data, but it gets routed to the wrong URL.
If my form is in
localhost:3000/users/1/styles/1
And when I submit the form, I get redirected to this:
localhost:3000/styles/1
and then I get an error:
Couldn't find User without an ID
views/comments/_form.html.erb
<%= form_for [#commentable, #comment] do |f| %>
<%= f.text_area :content, rows: 3 %>
<%= f.submit %>
<% end %>
styles_controller.rb
def show
#user = User.find(params[:user_id])
#style = #user.styles.find(params[:id])
#commentable = #style
#comments = #commentable.comments
#comment = Comment.new
end
comments_controller.rb
before_filter :get_commentable
def new
#comment = #commentable.comments.new
end
def create
#comment = #commentable.comments.new(params[:comment])
#comment.user = current_user
if #comment.save
redirect_to #commentable, notice: "Comment created."
else
render :new
end
end
private
def get_commentable
#commentable = params[:commentable].classify.constantize.find(commentable_id)
end
def commentable_id
params[(params[:commentable].singularize + "_id").to_sym]
end
routes.rb
resources :styles do
resources :comments, :defaults => { :commentable => 'style' }
end
Please let me know if there's other information that is needed. Why am I getting rerouted to a different url? My comment does save into my database.
Thank you
If you want to go back to localhost:3000/users/1/styles/1 after creating comment, you should change
if #comment.save
redirect_to #commentable, notice: "Comment created."
else
to
if #comment.save
redirect_to [User.find(params[:user_id]), #commentable], notice: "Comment created."
else
Edit: Should use User that owns the style not current user
Related
I am trying to create a nested resource so that products can have notes associated with them. I have set up the associations within the model etc, but when I try to use the form to create a new note, I get the following error:
NoMethodError in Notes#create
Showing /Users/myusername/myapp/app/views/notes/_form.html.erb where line #2 raised:
undefined method `notes_path' for #<#<Class:0x00007fb3630b1ad0>:0x00007fb361eab868>
This is the line it is referring to:
<%= simple_form_for [#product, #note] do |f| %>
This are the new & create actions in the notes controller:
def new
#product = Product.find(params[:product_id])
#note = #product.notes.build
end
def create
#note = Note.new(product: #product)
respond_to do |format|
if #note.save
format.html { redirect_to product_notes, notice: 'Note was successfully created.' }
else
flash.now[:error] = "It doesnt work"
render 'new'
end
end
end
and the form partial:
<%= simple_form_for [#product, #note] do |f| %>
<%= f.error_notification %>
<%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>
<div class="form-inputs">
<%= f.input :content %>
<%= f.input :author %>
<%= f.check_box :visible %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
I am going round in circles with making changes, and cannot seem to find any documentation on nested resources that isn't deprecated. Can anybody assist, please?
Edited to add:
I changed my controller action to something based on PGill's answer and can now get the page to load without an action controller error. However, it now re-renders the new note form, with errors saying that the form fields cannot be blank. They were not blank when I submitted them - what's happening to cause this?
Updated controller action:
def create
#product = Product.find(params[:product_id])
#note = #product.notes.new
respond_to do |format|
if #note.save
format.html { redirect_to product_notes_path(#product), notice: 'Note was successfully created.' }
else
format.html { render :new, notice: 'Note failed to be created.' }
end
end
end
When I was previously getting errors, it had this as the request parameters, so they are getting passed?
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"lotsofletters",
"note"=>{"content"=>"test", "author"=>"test", "visible"=>"0"},
"commit"=>"Create Note",
"product_id"=>"1"}
Referring to your edit; of course you should get empty fields errors because you are creating a new object #note without providing any attributes for it:
#note = #product.notes.new
it should be like
#note = #product.notes.build(params[:note])
also take care to provide a sanitizer for note in notes controller :
private
def note_params
params.require(:note).permit(:content, :author, :visible, :product_id)
end
so your code in create will look like:
def create
#product = Product.find(params[:product_id])
#note = #product.notes.build(note_params)
respond_to do |format|
if #note.save
format.html { redirect_to product_notes_path(#product), notice: 'Note was successfully created.' }
else
flash.now[:error] = "It doesnt work"
render 'new'
end
end
end
private
def note_params
params.require(:note).permit(:content, :author, :visible, :product_id)
end
#product is nil in create
Your form is failing validations and rendering new
update the create action to
def create
#product = Product.find(params[:product_id])
#note = #product.notes.new
respond_to do |format|
if #note.save
format.html { redirect_to product_notes_path(#product), notice: 'Note was successfully created.' }
else
flash.now[:error] = "It doesnt work"
render 'new'
end
end
end
redirect_to should be product_notes_path(#product) notes#index
I have a User model that has_many Photos (another model). In the routes.rb file it's photos is a nested resource of user. So, I have a form_for that uploads to the controller #create action. I'm having trouble saving the photo into the database under the user. How can I do this? It says it saves correctly, because it redirects, but then it doesn't show that it has a photo (I also used the console to check not just my view). What am I doing wrong?
class PhotosController < ApplicationController
def new
#photo = Photo.new(:user_id => params[:user_id])
end
def create
byebug
#photo = Photo.new(params[:user_id])
if #photo.save
flash[:notice] = "Successfully added photo."
redirect_to new_user_photo_path
else
render :action => 'new'
end
end
end
EDIT----------
Adding in the form_for that gets us to the #create action. Hope this helps :) I've been reading more about this, and I'm still not sure what to do to fix.
<%= form_for #photo, :url => user_photos_path(current_user.id, #photo), :html => {:multipart => true} do |f| %>
<div class="form-group">
<%= f.file_field :image %>
</div>
<%= f.submit 'Upload', class: 'btn btn-success' %>
or
<%= link_to 'Cancel', users_path %>
<% end %>
class PhotosController < ApplicationController
def new
#user = User.find(params[:user_id])
#photo = Photo.new(:user_id => params[:user_id])
#photos = #user.photos
end
def create
#photo = User.find(params[:user_id]).photos.new(photo_params)
if #photo.save
flash[:notice] = "Successfully added photo."
redirect_to new_user_photo_path
else
render :action => 'new'
end
end
# GET /photos
def index
redirect_to new_user_photo_path
end
# GET /photos/1
def show
#photo = Photo.find(params[:id])
end
def edit
#photos = Photo.all
#photo = Photo.new
end
def destroy
#photo = User.find(params[:user_id]).photos.find(params[:id])
#photo.destroy
flash[:notice] = "Successfully deleted photo"
redirect_to new_user_photo_path
end
def photo_params
params.require(:photo).permit!
end
end
I'm trying to follow Ryan Bates polymorphic models tutorial (Rails 3), to implement comments in my photo model. I'm having trouble when trying to create a new comment for photos since I'm in Rails 4 and I have to deal with :comment strong parameters.
Error: undefined method `user_comments_path' for #<#:0x00000107c8a200>
I have nested resources
#Nesting Resources
resources :users do
resources :photos do
resources :comments
resources :tags
end
end
So the route should be /users/friendly-id/photos/friendly-id/comments, but it's getting badly constructed, I have <%= form_for [#user, #commentable, #comment] do |f| %> in my form.
Photo Controller
#create
def show
#photo = Photo.friendly.find(params[:id])
#user = #photo.user
#tag = Tag.new
#tag.photo_id = #photo.id
#category = Category.all
#commentable = #photo
#comments = #commentable.comments
#comment = Comment.new
#zone = Zone.all
respond_to do |format|
format.html #show.html.erb
format.json {render json: #photo}
end
end
Form
<%= form_for [#user, #commentable, #comment] do |f| %>
<% if #comment.errors.any? %>
<div class="error_messages">
<h2>Please correct the following errors.</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Comments controller
class CommentsController < ApplicationController
before_filter :load_commentable
def index
#comments = #commentable.comments
end
def new
#comment = #commentable.comments.new
end
def create
#comment = #commentable.comments.new(comment_params)
if #comment.save
redirect_to #commentable, notice: "Comment created."
else
render :new
end
end
private
def load_commentable
resource, id = request.path.split('/')[1, 2]
#commentable = resource.singularize.classify.constantize.find(id)
end
def comment_params
require(:comment).permit(:photo_id, :user_id, :content)
end
###Error 2: When I put friendly.id instead of only id in `load_commentable` method I get a Forbidden Attribute error.
end
Please someone help! Thank you
I have an Items model that has_many Photos (which belongs_to Items), both namespaced under Admin.
Uploading via the form works as expected via the Photo's new or edit action(, but not when rendered from the Item show page, I get an "undefined method `model_name' for NilClass:Class" error.When I create a new photo record I pass in the item_id and I'm not sure what to pass into the form on the items page.
PhotosController;
class Admin::PhotosController < Admin::BaseController
def new
#photo = Photo.new(:item_id => params[:item_id])
end
def create
#photo = Photo.new(params[:photo])
if #photo.save
flash[:notice] = "Successfully created photo."
redirect_to [:admin,#photo.item]
else
render :action => 'new'
end
end
def edit
#photo = Photo.find(params[:id])
end
def update
#photo = Photo.find(params[:id])
if #photo.update_attributes(params[:photo])
flash[:notice] = "Successfully updated photo."
redirect_to [:admin,#photo.item]
else
render :action => 'edit'
end
end
def destroy
#photo = Photo.find(params[:id])
#photo.destroy
flash[:notice] = "Successfully destroyed photo."
redirect_to [:admin,#photo.item]
end
end
photos/_form.html.haml;
= form_for [:admin,#photo], :html => {:multipart => true,id: 'upload'} do |f|
= f.hidden_field :item_id
%p
= f.label :name
%br/
= f.text_field :name
%p
= file_field_tag :image, multiple: true, name:'photo[image]',id: 'photo_image'
%p= f.submit
items/show.html.haml;
= render 'admin/photos/form'
doh! figured it out
the render call should be;
= render 'admin/photos/form', :photo => #item.photos.build
and the form
= form_for [:admin,photo]
or you can create a #photo variable in your items_controller#show like
#photo = #item.photos.build
and in your partial
form_for[:admin,#photo]
i think this would be better, because all of your variables get assigned in the controller and not one in the controller and the other in the view.
I created an twiiter like app, where friends can post, but i want a include the name of the person who created the post in the list showing all the post.
here is my code
class PostsController < ApplicationController
def index
#posts = Post.all(:order => "created_at DESC")
respond_to do |format|
format.html
end
end
def create
#post = Post.create(:message => params[:message])
respond_to do |format|
if #post.save
format.html { redirect_to posts_path }
format.js
else
flash[:notice] = "Message failed to save."
format.html { redirect_to posts_path }
end
end
end
end
`
Assuming, of course, that the 'user has many posts' association is set, and the user model has a 'username' field, you can do this in your view :
<% #posts.each do |post| %>
<%= post.user.username %>
<% end %>