Update attribute on a has_many relationship - ruby-on-rails

I am printing a list of user's contacts and want to give the user the ability to mark each contact as "done". (Essentially marking them off their to do list).
How do I update the :done attribute for the specific contact?
This is form with a hidden field is not working:
<% if current_user.contacts.any? %>
<% current_user.contacts.each do |c| %>
<li id="<%= c.id %>">
<%= c.name %><br/>
<%= form_for(#contact) do |f| %>
<%= f.hidden_field :done, :value=>true %>
<%= f.submit "Mark as done", class: "btn btn-small btn-link"%>
<% end %>
</li>
<% end %>
I get this error:
Template is missing Missing template contacts/create, application/create with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in: * "C:/Sites/rails_projects/sample_app/app/views"
This is my contacts controller:
def create
#contact = current_user.contacts.build(params[:contact])
if #contact.save
flash[:success] = "Contact saved!"
redirect_to root_url
else
flash[:error] = "Something is wrong"
end
end

For some reason, perhaps due to validation rules, the #contact object can't be saved.
In this case, the else branch in your create action doesn't specify what to render, so it's looking for a create template. You may be able to simply add a line to render :action => :new or redirect_to :action => :new, assuming your new action doesn't require preloading additional data.
else
flash[:error] = "Something is wrong"
redirect_to :action => :new
end
You can also use respond_with instead of explicitly redirecting, which will render the new action if errors were found:
def create
#contact = current_user.contacts.build(params[:contact])
if #contact.save
flash[:success] = "Contact saved!"
else
flash[:error] = "Something is wrong"
end
respond_with #contact, :location => root_url
end

Related

No template found for UsersController#create, rendering head :no_content

OK, previously I had a problem with a no template error from users#create, now it complete 200 OK however does not redirect at all. Below is my edited users_controller.rb
I have a Signup, Login, Logout rails application with users as a resource. I am trying to save the first user in the database so I can then login but this error is server output when I try to "users#new" and "users#create" the full error is below, then my users_controller.rb and views/users -> new.html.erb
No template found for UsersController#create, rendering head :no_content
Completed 204 No Content in 35ms (ActiveRecord: 0.5ms)
users_controller.rb
def new
#user = User.new
end
def create
#user = User.new(user_params)
if (#user = User.find_by_email(params[:email]))
flash[:success] = "User already exists."
if #user.save
session[:user_id] = user.id
flash[:success] = "New User created."
redirect_to '/layouts/application'
else
render 'new'
end
end
end
new.html.erb
<h1>Sign Up</h1>
<%= form_with(model: #user) do |f| %>
<p> Username:</br> <%= f.text_field :username %> </p>
<p> Email:</br> <%= f.text_field :email %> </p>
<p> Password:</br> <%= f.password_field :password%></p>
<%= f.submit "Signup" %>
<% end %>
<% if #user.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in #user.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
</ul>
<% end %>
</div>
Do I have to have another html.erb file? And how can I tell what that has to be? Sorry for the obvious question, newb here.
As per your code if the User is not present it will not enter in the if block. Rails end up trying to find create.html as the current action is create.
To avoid this you must redirect it somewhere or render a template which you have done in the next if and else but it's not executing.
The condition is not letting it redirect to anywhere. Try moving the if block out like this.
def create
#user = User.new(user_params)
if User.exists?(email: params[:email]) # I think this should be `user_params[:email]` instead of `params[:email]`
flash[:error] = "User already exists."
redirect_to 'whereever/you/want/to/redirect' and return
end
if #user.save
session[:user_id] = user.id
flash[:success] = "New User created."
redirect_to '/layouts/application'
else
render 'new'
end
end

Ruby on Rails - Create polymorphic comment through partial

I'm currently trying to implement polymorphic comments within my app, but I'm running into problems with converting my partial form.
I was following this tutorial, step-by-step-guide-to-polymorphic-associations-in-rails, but it didn't go over this section.
Mainly, I have an Image that is commentable, and a partial at the bottom to allow users to comment on the Image.
However, when submitting the form, it can't find the #commentable object as params[:id] and params[:image_id] are both nil.
I'm having problems understanding how I'm supposed to pass this information, as the partial knows this information, but the controller does not.
// images/show.html.erb
<div class="container comment-form" >
<%= render 'comments/form', comment: #image.comments.build %>
</div>
// comments/_form.html.erb
<%= bootstrap_form_for(comment) do |f| %>
<%= f.text_area :message, :hide_label => true, :placeholder => 'Add a comment' %>
<%= f.submit 'Reply', :class=> 'btn btn-default pull-right' %>
<% end %>
// comments_controller.rb
def create
#commentable = find_commentable
#comment = #commentable.comments.build(comment_params) <<<<<
respond_to do |format|
if #comment.save
format.html { redirect_to (comment_path #comment), notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
Error on #comment = #commentable.comments.build(comment_params)
undefined methodcomments' for nil:NilClass`
I also noticed that there is no id in the request parameters.
Parameters:
{"utf8"=>"✓", "authenticity_token"=>"xxxxxx", "comment"=>{"message"=>"nice photo"}, "commit"=>"Reply"}
Thanks for your help.
When you pass a record to a form builder rails uses the polymorphic route helpers* to lookup the url for the action attribute.
To route to a nested resource you need to pass the parent and child(ren) in an array:
bootstrap_form_for([#commentable, #comment])
# or
bootstrap_form_for([#comment.commentable, #comment])
This would give the path /images/:image_id/comments for a new record and /images/:image_id/comments/:id if it has been persisted.
You are attempting to build your comment twice. Once in the show.html, with comment: #image.comments.build and then again in your create method with #comment = #commentable.comments.build(comment_params) <<<<<
The tutorial you linked to included the private method below. If your goal is to create a comment that belongs to your Image object, the method below would look for a param with your image_id, and would return Image.find(params[:image_id])
def find_commentable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
You could change your show.html to pass in your image_id as a hidden param with:
<div class="container comment-form" >
<%= render 'comments/form', image_id: #image.id %>
</div>

Implementing ancestry on a nested resource throwing an error

I am implementing ancestry on a nested resource.
resources :loads do
resources :messages
end
Here is my index action
def index
load = Load.find(params[:load_id])
#messages = load.messages.scoped
#message = load.messages.new
end
My index.html.erb is throwing the following error.
Missing partial messages/message with {:locale=>[:en],
:formats=>[:html], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "C:/Sites/final/cloud/app/views"
My index.html.erb is as follow
<% title "Messages" %>
<%= nested_messages #messages.arrange(:order => :created_at) %>
<%= render "form" %>
Here is my nested_message definition
module MessagesHelper
def nested_messages(messages)
messages.map do |message, sub_messages|
render(message) + content_tag(:div, nested_messages(sub_messages), :class => "nested_messages")
end.join.html_safe
end
end
Here is my _message.html.erb
<div class="message">
<div class="created_at"><%= message.created_at.strftime("%B %d, %Y") %></div>
<div class="content">
<%= link_to message.content, message %>
</div>
<div class="actions">
<%= link_to "Reply", new_load_message_url(:parent_id => message) %> |
<%= link_to "Destroy", [message.load, message], :confirm => "Are you sure?", :method => :delete %>
</div>
</div>
Any help appreciated.
This error states that your application has tried to search for a partial _messages.html.erb, as a result of this the partial must not be in your /app/views/messages which results in the message you are being shown. Check your messages directory and check if you have this partial. Going by your nested resources I am guessing your association between Load and Message is:
class Load < ActiveRecord::Base
has_many :messages
end
class Message < ActiveRecord::Base
belongs_to :load
end
Further more I noticed that you have the following line in your index action: #message = load.messages.new surely this does not seem right. Because what your telling your application to do is when the controller recieves a response to render the index action it should also create message by doing #message = load.messages.new which is why it is trying to render the partial.
To clarify things a bit more for you. If in your application you had a link_to to create a new user. Upon clicking the new user it will do something like:
def new
#user = User.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #user }
end
end
And will render `app/views/users/new.html.erb which inside this will most probably have a
<%= form_for #user do |f| %>
<%= render :partial => 'form', :locals => { :f => f } %>
<% end %>
This will call your partial which in normal cases would be _form.html.erb. The create action of a particular controller will come into play when you attempt to save the partial. Usually a create block for a controller will look like this:
def create
#title = "Create a user"
#user = User.new(params[:user])
if #user.save
redirect_to usermanagement_path
flash[:success] = "Created successfully."
else
#title = "Create a user"
render 'new'
end
end
Here inside the create action when your _form.html.erb or _message.html.erb is submitted it will try to create a new user by passing in the user through the params. I do thoroughly believe that your issue may potentially well be:
1) Your missing your _message.html.erb
2) Also you are calling a .new inside your index action.
Hope this clears this up for you.

error validations not showing in rails

I have hit a wall in displaying error messages. The error validation messages don't show up.
On my users show template:
<%= form_for([current_user, #pub_message]) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.hidden_field :to_id, :value => #user.id %>
<div class="micropost_message_field">
<%= f.text_area :content, placeholder: "Any thoughts? Questions? Comments?", :id => 'public_message_text' %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
which goes to my pub_messages#create
def create
#pub_message = current_user.pub_messages.build
#pub_message.to_id = params[:pub_message][:to_id]
#pub_message.user_id = current_user.id
#pub_message.content = params[:pub_message][:content]
if #pub_message.save
flash[:success ] = "Your post has been sent"
unless params[:pub_message][:slug].nil?
redirect_to lesson_path(params[:pub_message][:slug])
else
redirect_to user_path(params[:pub_message][:to_id])
end
else
#redirect_to :controller => :users, :action => :show, :id => params[:pub_message][:to_id]
#redirect_to user_path(params[:pub_message][:to_id])
render 'users/show'
end
end
however it wont' display the error messages. ive read from a number of other stackoverflow posts that error_messages will not survive a redirect_to so instead i have a render. however, since the render only displays the view, i'm missing all the variables. i tried just copying and pasting everything from my user#show action earlier but it seems like a bad practice. if i did that, i also ran into the issue that all my templates are missing. it seemed like i have to move all my templates to a shared folder in order for this to work but it seems wrong since some things are specific to just the user.
my error messages are being displayed correctly elsewhere but i just cant figure out what is wrong with my pub_messages.
i have something very similar called microposts, and it works.
def create
#user = current_user
#micropost = current_user.microposts.build(params[:micropost])
if #micropost.save
flash[:success] = "Micropost created!"
redirect_to root_path
else
#feed_items = current_user.feed.paginate(page: params[:page], per_page: 20)
render 'static_pages/home'
end
end
The only difference I think is that it does a render but also has all the templates it needs in a shared folder. Is that the only way for this to work?

Error handeling w/ form_for in associated resource

I can't seem to get the flow to work right here. I have a Ruby on Rails (2.3.9) application. For the purposes of this question we have only a couple of resources. Boxes and Messages.
Box has_many :messages
Message belongs_to :box
I have created a view located at /boxes/1/new_message where I have the below form_for code. I can successfully create a message from this view. The problem arrises when my validations kick in.
In this case, message.body can't be blank and is validated by message.rb. Once this validation happens, it kicks the user over to the Message.new action and upon successfully filling in the message.body the app can no longer find the #box.id to place in message.box_id.
I have tried just about everything I can think of by not sure how to allow a users to receive a validation and still successfully create a message for a box. See my code below for reference.
/views/boxes/new_message.html.erb
<% form_for [#box, Message.new] do |f| %>
<%= f.error_messages %>
<%= f.label :message_title %>
<%= f.text_field (:title, :class => "textfield-message grid_12 alpha") %>
<%= f.label :message_body %>
<%= f.text_area (:body, :class => "textarea-message grid_12 alpha ") %>
<%= f.submit "Add a Message", :class => 'input boxy' %>
<% end %>
messages_controller.rb
def create
#message = Message.new(params[:message])
#box = Box.find(params[:box_id])
#message = #box.messages.build(params[:message])
#message.user = current_user
respond_to do |format|
if #message.save
flash[:notice] = 'Message was successfully created.'
format.html {redirect_to #box }
else
format.html { render :action => "new" }
format.xml { render :xml => #flash.errors, :status => :unprocessable_entity }
end
end
end
def new
#message = Message.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #message }
end
end
I believe your
#box = Box.find(params[:box_id])
should be
#box = Box.find(params[:id])

Resources