I'm building a comments section on my blog, and so far I have it working to the point where I can successfully submit comments and have them appear on my page.
However, there is always a blank comment on the page whether I have 10 comments or the database is empty.
*** views/artist/lyrics/show.html.erb ***
<%= form_for(#lyric.comments.build, url: artist_album_lyric_comments_path(#artist, #album, #lyric)) do |f| %>
<%= f.text_area :content %>
<%= f.submit "comment" %>
<% end %>
<% if #lyric.comments.any? %>
<% #lyric.comments.each do |comment| %>
<%= comment.username %>
<%= comment.content %>
<% end %>
<% else %>
No one has commented.
<% end %>
*** /controllers/users/comments_controller.rb ***
def create
#comment = Comment.new(comment_params)
#comment.user_id = current_user.id
#comment.username = current_user.username
#comment.lyric_id = Lyric.friendly.find(params[:lyric_id]).id
if #comment.save
redirect_to (:back)
else
redirect_to root_url
end
end
The Comment model is nested and I think that has something to do with it. It's Artist => Album => Lyric => Comment
When I remove the Comment form from the page the blank comment disappears and the <else> statement runs.
In your form_for tag, you are building a comment on #lyric. I believe this is showing up when you are calling #lyric.comments immediately after. Try:
<% #lyric.comments[0..-2].each do |comment| %>
That will grab all the comments from the first to the second to last (basically all of them except the new one you just created).
Edit:
Also change <% if #lyric.comments.any? %> to <% if #lyric.comments.any? && !#lyric.comments[0].new_record? %>
I used this on my code before. Try this:
<% #lyric.comments.each do |comment| %>
<% next if comment.new_record? %>
<%= comment.username %>
<%= comment.content %>
<% end %>
I changed this line:
<%= form_for(#lyric.comments.build, url: artist_album_lyric_comments_path(#artist, #album, #lyric)) do |f| %>
to:
<%= form_for(Comment.new, url: artist_album_lyric_comments_path(#artist, #album, #lyric)) do |f| %>
It runs the else statement and gets rid of the new record on the page.
Related
This problem is specific to the example tutorials mentioned in the Getting Started guide of Rails 5.1.4
Upon following Section 5.11 [Updating Articles] from the rails getting started guide, it is expected that the line containing <% if #article.errors.any? %> in the app/views/articles/edit.html.erb file will get invoked if an article with empty title or empty text are tried to be saved. Meaning, the error messages should show up.
However, the article is prevented from getting updated (as expected) but the error messages do not show up (as not expected).
Is anyone familiar with this problem from the getting started tutorials explained in Rails Guide 5.1.4 ?
EDIT::: Following are the controller file and the view file. I have added some puts statements to print to the console
The articles_controller,rb file:
def edit
#article = Article.find(params[:id])
end
def update
#article = Article.find(params[:id])
if #article.update(valid_article_params)
puts 'article successfully updated...'
redirect_to #article
else
puts 'article could not be updated...'
render 'edit'
end
end
private
def valid_article_params
params.require(:article).permit(:title, :text)
end
The edit.html.erb file:
<h1>Edit article</h1>
<%= form_with(model: #article) do |form| %>
<% if #article.errors.any? %>
<% puts 'there are some errors here in edit.html.erb' %>
<div id="error_explanation">
<h3>
<%= pluralize(#article.errors.count, "error") %> prohibited this article from being saved:
</h3>
<ul>
<% #article.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% puts 'errors shown from edit.html.erb' %>
<% end %>
<p>
<%= form.label :title %><br>
<%= form.text_field :title %>
</p>
<p>
<%= form.label :text %><br>
<%= form.text_area :text %>
</p>
<p>
<%= form.submit %>
</p>
<% end %>
<%= link_to 'Back', articles_path %>
Add local: true to your form as follows:
<%= form_with(model: #article) do |form| %>
To:
<%= form_with(model: #article, local: true) do |form| %>
The reason is stated in the same guide:
by default form_with submits forms using Ajax thereby skipping full page redirects. To make this guide easier to get into we've disabled that with local: true for now.
I check and the Guide contains an error. The section 5.11 is missing local: true
The problem is you forgot to add local: true. By default, all request when using form_with is ajax. So you need to turn it off
form_with(model: #article, local: true)
Read more about form_with here link1 and link2
This is the error I get:
Showing /home/ubuntu/workspace/UMUV/app/views/users/show.html.erb where line #6 >>raised:
undefined method `name' for nil:NilClass
This is my conditional in users/show:
<% if #profile_info.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
This is in the users/controller:
def show
#user = User.find(params[:id])
#profile_info = Profile.find_or_initialize_by(user_id: params[:id])
end
I basically want to know how to not have an error when i visit a user's profile page and the user hasn't updated their profile yet. Showing the page is working fine if i update the user's profile through "edit page" manually.
Please help with the conditional. I also have a feeling i can create method in user.rb or users/controller, but really dont know how to implement this conditional to do what i want it to.
Thank you
In your show page you can replace this :
<% if #profile_info.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
with this:
<% if #profile_info.present? %>
<%= #profile_info.region.try(:name) %>
<% else %>
<%= #user.try(:email)%>
<% end %>
and also go through this post: http://everydayrails.com/2011/04/28/rails-try-method.html
Well you can always test an initalized object vs a saved object using new_record? -- which would make your above view look more like:
<% if #profile_info.new_record? %>
<%= #user.email%>
<% else %>
<%= #profile_info.region.name %>
<% end %>
also you might be able to take advantage of try on part of your page, which fails gracefully if an attribute doesn't exist, like
#profile_info.region.try(:name)
Since your error is with the name #profile_info.region.name not being present you could change your conditional to:
<% if #profile_info.region.name.present? %>
<%= #profile_info.region.name %>
<% else %>
<%= #user.email%>
<% end %>
Or if you really want to test #profile_info.present? you could nest conditionals like this:
<% if #profile_info.present? %>
<% if #profile_info.region.name.present? %>
<%= #profile_info.region.name %>
<% end %>
<% else %>
<%= #user.email%>
<% end %>
I hope that helps!
def update
if #note.update_attributes(note_params)
redirect_to :back, notice: "Note was updated."
else
render :edit
end
end
Is there a way to redirect back twice?
Here you go:
This is where the link for editing goes:
<p id="notice"><%= notice %></p>
<% url = "#{request.protocol}#{request.host_with_port}#{request.fullpath}" %>
<%= link_to 'Create New Page and Return Here', edit_page_path(1, :url => Base64.encode64(url) ) %>
<br>
After submit your url will be something like this:
http://localhost:3000/pages/1/edit?url=aHR0cDovL2xvY2FsaG9zdDozMDAwL2R1bW1pZXM%3D%0A
In the edit form:
I called it pages/_form.html.erb, Pass the URL as a hidden params.
<%= form_for(#page) do |f| %>
<% if #page.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#page.errors.count, "error") %> prohibited this page from being saved:</h2>
<ul>
<% #page.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :permalink %><br>
<%= f.text_field :permalink %>
</div>
<%= hidden_field_tag :url, params[:url].to_s %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
In controller that you have update method, in this case pages_controller.rb, simply Base64 it back and redirect the user:
def update
redirection = nil
if params[:url].present?
redirection = Base64.decode64(params[:url].to_s)
end
if #page.update(page_params)
if redirection.present?
path = redirection
else
path = #page
end
redirect_to path, notice: 'All Done.'
else
render :edit
end
end
Now user updates the form and redirected back to the first show or index page or any page that she is coming from.
Hope this help.
PS: You might want to clean it up a bit and pass the url from the controller, and put some checks on it. So you don't define any var at the view level. In the above code I just tried to solve this issue not really a design pattern oriented :)
I'm working my way through the rails "Getting Started" tutorial, and I'm stuck at the point where they introduce partials. For some reason the partial doesn't work as described when rendered from new.html.erb, although it does work when rendered from edit.html.erb. When clicking "New" to get to the new.html.erb, I'm getting the following error:
Error:
"First argument in form cannot contain nil or be empty"
for the first line in the following partial:
_form.html.erb:
<%= form_for #post do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited
this article from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :title %><br/>
<%= f.text_field :title %>
</p>
<p>
<%= f.label :text %><br/>
<%= f.textarea :text %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
new.html.erb:
<h1>New Post</h1>
<%= render 'form' %>
<%= link_to 'Back', posts_path %>
edit.html.erb:
<h1>Edit post</h1>
<%= render 'form' %>
<%= link_to 'Back', posts_path %>
posts_controller.rb:
...
def new
end
...
def edit
#post = Post.find(params[:id])
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
redirect_to #post
else
render 'edit'
end
end
...
It looks as though the new.html.erb doesn't know about the #post variable if it's a new post. The original new.html.erb looked like this:
<h1>New Post</h1>
<%= form_for :post, url: posts_path do |f| %>
...
... other than the use of symbols instead of #post, it's identical to the partial form.
Any ideas?
You don't set #post instance variable in your Posts#new action (and that's why it's nil). You should have:
def new
#post = Post.new
end
in your PostsController.
I can't figure out how to do this.. I'm in the user-controller that's inside a namespace called admin, and this is how my form looks like:
<%= form_for [:admin, #user] do |f| %>
<% if #user.errors.any? %>
<div class="reg-error">
<h4>Could not send registration!</h4>
<ul>
<% for message in #user.errors.full_messages %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :email %><br>
<%= f.text_field :email %><br><br>
<%= f.label :rank %><br>
<%= f.select :rank, options_for_select([1, 2, 3, 4, 5]) %><br><br>
<%= f.submit "Send registration", :confirm => "Are you sure?" %>
<% end %>
As you can see I'm using [:admin, #user] for the form, but it doesn't work with just replacing #user.errors.any? with [:admin, #user].errors.any?
The form it self works just fine, but it just won't display the validation errors.
How do I do this?
UPDATE - SOLVED
I didn't show you my controller, and I found the error there..
if #user.save
UserMailer.invitation_mail(#user).deliver
redirect_to admin_manage_users_path, :notice => "Successfully added a new account! Mail has been sent"
else
#user = User.new
#registered_users = User.where(:reg_key => nil)
#pending_users = User.where("users.reg_key IS NOT NULL")
render "show"
end
Since I had a #user = User.new in the else statement, It resetted the error messages some how. Totally missed that one. I'll leave it here if someone else would do this simple mistake too.. Thanks for the replys tho.
Try making just the following changes:
form_for #user do |f|
if #user.errors.any?
...
#user.errors_full_messages.each do |message|
<li><%= message %></li>
If that doesn't work can you show me what your controller looks like. For instance, in your users_controller new method are you doing something like:
#user = Admin::User.new