Flash messages not appearing in display - ruby-on-rails

There's a few of these questions in SO but none address my specific issue so I'm posting it.
I'm trying to display flash notices for success and errors in my rails project but they aren't displaying and I don't know why.
class CheckinsController < ApplicationController
def index
#checkins = Checkin.all
#checkin = Checkin.new
end
def create
#checkin = Checkin.create(params[:checkin])
if #checkin.errors.empty?
render json: #checkin, status: 201,
:notice => 'Thanks for posting your comments.'
else
flash[:notice] = "Please enter a name."
redirect_to checkins_path
end
end
end
Note that yes, there's a discontinuity of :notice and flash[:notice] but it's the only way the controller doesn't break it.
My model looks like this and is doing what it should, that is, prevents a save if the name field in the form is vacant:
class Location < ActiveRecord::Base
attr_accessible :name, :description
has_many :checkins
validates :name, presence: true
end
And I have this in my application.html.erb file:
<div id="notice"><%= flash[:notice] %></div>
Technically this should work, it should display the notice when the error is found. Is there something I'm missing?
I've also tried using...
<% flash.each do |name, msg| -%>
<%= content_tag :div, msg, class: name %>
<% end -%>
per RoR docs to no avail.
One thing to note is that it's also not rendering its CSS either. Seems related but I can't figure out how.

This has been answered here: Rails Flash.now not working
Basically you need to call the method in a different manner in the view.
flash.now[:notice]
Would be the correct invocation.

Related

How to validate emails with error messages

[Update] I still dont know what to put in my else of my create conroller to put and error message.
I am trying to validate the format of users email.
This is the html the error is coming from
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this article
from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
I experimented with this from an old ruby video but it didn't seen to pan out.
This is my user.rb model
class User < ApplicationRecord
has_secure_password
validates :email, presence: true, uniqueness: true
validates :password, length: { minimum: 4 }
validates :email, format: { with: /(\A([a-z]*\s*)*\<*([^#\s]+)#((?:[-a-z0-9]+\.)+[a-z]{2,})\>*\Z)/i }
end
I get these errors currently
No route matches {:action=>"show", :controller=>"users", :id=>nil},
missing required keys: [:id]
and
undefined method `errors' for nil:NilClass
whenever the password or email makes an error from the requirements.
my create action in my sessions controller:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.create(password: params[:password], email: params[:email], firstname: params[:firstname], lastname: params[:lastname])
if #user.save
redirect_to user_path(#user)
else
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
def show
#user = User.find(params[:id])
end
end
When there is no user with the requested email address, your #user variable will be nil in the controller (since this is the returned value of the find_by_email method if nothing is found)
In that case, you are explicitly rendering your new view which then attempts to render errors on the #user object. However, since the variable is nil instead of the User object you are apparently expecting there, nil.errors fails with the error you are seeing there.
To solve this, you should either check in your view if you have an actual #user object, or render a more suitable view from your controller.
3 issues here
def create
#user = User.create(password: params[:password], email: params[:email], firstname: params[:firstname], lastname: params[:lastname])
redirect_to user_path(#user)
end
That function tries to create a user and regardless of success it then goes on to redirect to the show action
1) You need to check if the User.create actually succeeds then take appropriate action
2) You have no route for the show action so you need to fix that but
3) None of your actions are specifying the format. What happens if someone is using an XML feed Are you sure you want to show the user, Just show a list of users, there won't be anything much to see
Several people including asked for the full stack trace which you seem to have ignored. This would be so much easier to track down the origination of your error had you done so, including the params sent to the create action
def create
if #user = User.create(password: params[:password], email: params[:email], firstname: params[:firstname], lastname: params[:lastname])
redirect_to user_path(#user)
else
format.html { render :action => "new" }
end
end
Now you have to track down why the create failed
You should also show the errors to the user by using a flash message

Having trouble trying to pass an id into the next form

I have a model of payments and visits. I have associated them in the model shown below. A visit can only have one payment.
I have it set up that a user fills out a visit form and then once completed is redirected to the payment form. What I would like to happen, is the for the visit id to be automatically passed into a hidden_field in the visit_id form on the next page.
class Visit < ActiveRecord::Base
has_one :payment
end
class Payment < ActiveRecord::Base
belongs_to :visit
end
It seems fairly basic, I just can't seem to wrap my mind around the associations correctly. I've searched around and seen a few people trying to explain it but whatever I try is not working correctly. Thanks in advance!
One way to do it would be, in your VisitsController
def create
#visit = Visit.create(visits_params)
if !#visit.save
render :new, error: "Something went wrong"
else
#payment = #visit.build_payment
end
end
Then in your visits/create.html.erb, simply put
<%= form_for #payment do |f| %>
<%= f.hidden_field :visit_id %>
<% end %>
It should work but it doesn't feel right from a RESTFUL perspective. A better way to do it would be to have, in your config/routes.rb
resources :visits do
resources :payments
end
That will generate the following route:
GET /visits/:visit_id/payments/new
Then in the VisitsController
def create
#visit = Visit.create(visit_params)
if !#visit.save
render :new, error: "Something went wrong"
else
redirect_to new_payment_path(visit_id: #visit.id)
end
end
And in your PaymentsController
def new
#visit = Visit.find(params[:visit_id])
#payment = #visit.build_payment
end
In your payments/new.html.erb don't forget to put
<%= form_for #payment do |f| %>
<%= f.hidden_field :visit_id %>
<% end %>
And there you have it... Let me know if that doesn't make any sense.

how to set flash error in rails app

I'm doin some simple app,i't gonna be some kind of translation app,so i have a search option and adding translations option.I have a problem with my search.When I click on search without any word there,it's shows me a list of translations.i would like to have a flash error there,like a i have it,when i look for a word which is not in database.
my model
class Translation < ActiveRecord::Base
attr_accessible :text_english, :text_polish
validates_presence_of :text_english, :text_polish
validates :text_polish, :text_english, :uniqueness => true
def self.search(search)
if search
where("text_english LIKE ? OR text_polish LIKE ?", "%#{search.strip}%", "%#{search.strip}%")
else
scooped
end
end
end
in my controller
# GET /translations/search
def search
#translations = Translation.search(params[:search])
if !#translations.empty?
respond_to do |format|
format.html
end
else
flash[:error] = "NO TRANSLATIONS"
redirect_to new_translation_url
end
end
end
and my search form in index
<h1>Words</h1>
<%= form_tag search_translations_path, method: :get do %>
<div class="field">
<%= text_field_tag :search, params[:search] %>
<button type="submit" class="btn">Search</button>
<% end %>
thanx for any help.
You have several options, one that is fairly simple would be to add a couple of lines to your controller to account for no params[:search]
# GET /translations/search
def search
if params[:search].blank?
flash[:error] = "A WORD TO TRANSLATE IS REQUIRED"
redirect_to new_translation_url
else
#translations = Translation.search(params[:search])
if !#translations.empty?
respond_to do |format|
format.html
end
else
flash[:error] = "NO TRANSLATIONS"
redirect_to new_translation_url
end
end
end
The important thing to remember is to not allow any path in your code that could redirect or render twice. Hence the if params[:search].blank? .. else

Couldn't find ArticlesSkill with ID=1 for Article with ID=

I am trying to create an article.
class Article < ActiveRecord::Base
belongs_to :article_skill
attr_accessible :articles_skill_attributes
accepts_nested_attributes_for :articles_skill
end
class ArticlesSkill < ActiveRecord::Base
attr_accessible :description, :name
has_many :articles
end
This is my form in the article/new.html.erb
<%= article_form.fields_for :articles_skill, #article.articles_skill do |b|%>
<label class="medium"><span class="red">*</span> Skill</label>
<%= b.select :id, options_for_select(ArticlesSkill.all.collect{|m| [m.name, m.id]}) %>
<%end%>
Here the article_form is the builder for the #article form object.
If I try to save the #article object its showing this error.
Couldn't find ArticlesSkill with ID=1 for Article with ID=
I've been struggling with this problem for a few days. Did a lot of searching.. it took going to the rails console and searching by the exception being thrown instead to make any progress with this.
Check out this answer on this question for why it's happening, and possible workarounds.
Use rails nested model to *create* outer object and simultaneously *edit* existing nested object?
Be aware that using the first option presented here creates a security hole as described in http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-3933
The second parameter in your fields_for call seems unnecessary. ActiveRecord is performing a lookup on the association articles_skill for #article when it reaches that param, but since the #article is new and has yet to be saved, it has no ID and triggers an error.
<%= article_form.fields_for :articles_skill do |b|%>
<label class="medium"><span class="red">*</span> Skill</label>
<%= b.select :id, options_for_select(ArticlesSkill.all.collect{|m| [m.name, m.id]}) %>
<% end %>
I can suggest only a workaround. It works, but I don't like it - I want some out-of-the-box solution.
I assume you have a function:
def articles_skill_params
params.require(:articles_skill).permit(:description, :name,
article_attributes: []) end
Add a function
def articles_skill_params2
params.require(:articles_skill).permit(:description, :name)
end
Add another function:
def set_article
article_id = articles_skill_params[:article_attributes][:id]
article = Article.find(article_id)
#articles_skill.articles << article
#articles_skill.save
end
Change your ArticlesSkillController#create:
def create
#articles_skill = ArticlesSkill.new(articles_skill_params2)
set_article
respond_to do |format|
if #articles_skill.save
format.html { redirect_to #articles_skill, notice: 'Article skill was successfully created.' }
format.json { render :show, status: :created, location: #articles_skill }
else
format.html { render :new }
format.json { render json: #articles_skill.errors, status: :unprocessable_entity }
end
end
end
As you can see, we simply exclude the nested attributes from the parent object creation (thus eliminating the error), then manually add them later.
If you just want people to be able to select an existing skill you don't need nested attributes at all (that's useful for when you might want people to be able to create an article skill from the same form that creates an article). You just want to set article_skill_id to an existing value, so you can just do
<%= form_for(#article) do |f| %>
...
<label class="medium"><span class="red">*</span> Skill</label>
<%= f.select :article_skill_id, ArticlesSkill.all.collect{|m| [m.name, m.id]}) %>
<% end %>

Ruby on rails 2 level model

I need some help creating a very simple forum in a existing model.
What I want in a Game page, have a mini forum, where is possible create some topics and some comments to this topics. In the beginning I'm only implement topics.
This is the error I have:
Mysql2::Error: Column 'user_id' cannot be null: INSERT INTO `topics` (`game_id`, `question`, `user_id`) VALUES (1, 'asd', NULL)
This is my main model:
game.rb
class Game < ActiveRecord::Base
attr_accessible :name
validates :user_id, presence: true
validates :name, presence: true, length: { maximum: 50 }
belongs_to :user
has_many :topics, dependent: :destroy
end
topic.rb
class Topic < ActiveRecord::Base
validates_presence_of :question
validates_presence_of :game_id
attr_accessible :question, :user_id
validates :question, length: {maximum: 50}, allow_blank: false
belongs_to :game
belongs_to :user
end
topic_controller.rb
def create
#game = Game.find(params[:game_id])
#topic = #game.topics.create(params[:topic])
#topic.user_id = current_user.id
respond_to do |format|
if #topic.save
format.html { redirect_to #game, notice: 'Topic was successfully created.' }
else
format.html { render action: "new" }
end
end
end
game/show.html.erb
<h2>Topics</h2>
<% #game.topics.each do |topic| %>
<p>
<b>Question:</b>
<%= topic.question %>
</p>
<% end %>
<h2>Add a topic:</h2>
<%= form_for([#game, #game.topics.build]) do |f| %>
<div class="field">
<%= f.label :question %><br />
<%= f.text_field :question %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Thanks ;)
I believe the issue you're experiencing is the difference between create and new in Rails.
Using new merely initializes the model, allowing you to save/validate later; using create will perform all of those steps in one command, causing the database row to be created.
So when you attempt to perform
#game.topics.create(params[:topic])
Rails attempts to create a Topic using params[:topic] and setting the game_id to #game.id, after which it immediately attempts to validate this new Topic that it created and save it to the database.
Potential options that you can consider:
1) Use #game.topics.new(params[:topic])
2) merge {:user_id => current_user.id} in: #game.topics.create(params[:topic].merge({:user_id => current_user.id})
I'd personally suggest option 1 (i.e. using new instead), but I have seen option 2 used before.
EDIT: Another issue that it looks as though you might be experiencing: should current_user be #current_user in your code?
Side note:
generally, if create fails to create database row, it will still work (returning the initialized model instead), but in your case it looks like this won't happen due to database-level restrictions on user_id being NOT NULL, causing an uncaught error.
You may want to consider reading the Rails Guide on nested resources. I've been where you are now , take a look at this discusion.
I guess you're accessing the site without being logged in, so user_id will not be set. You should ensure that there is a logged in user for all actions that are modifying or creating a topic. A simple approach can be found in this Railscast.
I think current_user.id is not setting properly, Do inspect these issue are almost all the other issues, ruby debugger is the beset way
in your GEM file add
GEM file
gem 'debugger'
run bundle install
then in your controller
def create
#game = Game.find(params[:game_id])
#topic = #game.topics.create(params[:topic])
#topic.user_id = current_user.id
debugger
respond_to do |format|
if #topic.save
format.html { redirect_to #game, notice: 'Topic was successfully created.' }
else
format.html { render action: "new" }
end
end
end
and this will stop you in the the debugger line, then from the console you could see if the values are set or not. check this for more

Resources