Rails: flash notice unless only certain attributes updated - ruby-on-rails

I want to show a flash notice in my Rails app all the time unless only certain attributes are updated.
def update
if #user.update_attributes(user_params)
if user_params == [:user][:certain_params]
redirect_to users_path
else
redirect_to users_path, notice: "#{#user.name} saved."
end
else
redirect_to edit_user_path(#user), flash: { error: #user.mapped_errors }
end
end
Something like this pseudocode?

Use the changed method to get an array of the attributes that are changed, create a flash message if the attributes are not the "non-notify" attributes.
def update
#user.assign_attributes(user_params)
changed_fields = #user.changed
if #user.save
flash[:notice] = "#{#user.name} saved." if changed_fields != ["photo"]
redirect_to users_path
else
redirect_to edit_user_path(#user), flash: { error: #user.mapped_errors }
end
end
This will show the saved notice if they change photo plus other attributes, or if they change other attributes but not photo. The message is suppressed only if only photo is changed.

def update
#user = User.find(params[:id])
# lets say you have these attributes to be checked
attrs = ["street1", "street2", "city", "state", "zipcode"]
attributes_changed = (#user.changed & attrs).any?
if #user.update_attributes(user_params)
flash[:notice] = "#{#user.name} saved." if attributes_changed
redirect_to users_path
else
redirect_to edit_user_path(#user), flash: { error: #user.mapped_errors }
end
end
For more info see
Rails 3 check if attribute changed
http://api.rubyonrails.org/classes/ActiveModel/Dirty.html

Related

param is missing or the value is empty: gallery

The problem is with "strong parameters" in rails.
I use dragonfly for uploading images.
The problem is that if I send an empty form I do not get any parameters for error handling. What can be the reason?
Controller:
There is still also a method "Create" which saves the image in the database and sends the user to a page with pictures.
def index
#gallery = Gallery.new
#galleries = Gallery.all
end
def create
#gallery = Gallery.new(gallery_params)
if #gallery.save
redirect_to galleries_path, flash: { success: 'Your Image was successfully save.' }
else
redirect_to :back, flash: { alert: "Your Image don't save." }
end
end
def gallery_params
params.require(:gallery).permit(:image)
end
Views:
= form_for #gallery do |f|
= f.file_field :image
= f.submit 'Submit', class: 'btn bth-primary btn-lg'
Parameters:
{"utf8"=>"✓", "authenticity_token"=>"8eotQtkj8SElqJLdHuOX8r+dWrCJRWTmVcyfd1mSLD/8MjWw/ElH/HCxZFSJ6oOWaxpbLbn4kAg5nlFycsgjHg==", "commit"=>"Submit"}
This is the expected behavior, see the documentation for ActionController::Parameters#require
What I usually do in those cases is catch the exception and display a flash message to notify the user. You could also manually add an error to the model.
def create
#gallery = Gallery.new(gallery_params)
if #gallery.save
redirect_to galleries_path, flash: { success: 'Your Image was successfully save.' }
else
redirect_to :back, flash: { alert: "Your Image don't save." }
end
rescue ActionController::ParameterMissing => e
redirect_to :back, flash: { alert: "Please attach an image." }
end

Rails: Store (merge) parameter after Devise Sign In

I have a form that should be submitted after Sign In but all the viewers can see and fill the form. So, I save the parameters in a session variable. After Sign In, I store the parameters successfully. The problem is that I want to add the user_id (which is foreign key) and store it beside the other parameters (before Sign In, the user_id is unknown).
Part of my Controller's code:
def create
if current_user.nil?
session[:trip] = params
redirect_to new_user_registration_path
else
#trip = Trip.new(trip_params)
respond_to do |format|
if #trip.save
...
private
def set_trip
#trip = Trip.find(params[:id])
end
def trip_params
params.require(:trip).permit(:from, :to, :departure_date, :arrival_date, :user_id)
end
As I mentioned, this code stores the new form parameters successfully. To add (insert or merge) the current_user.id, I tried these different ways separetely:
#trip = Trip.new(trip_params.merge(user_id: => current_user.id)
#trip = Trip.new(trip_params)
#trip.user_id = current_user.id
#trip = current_user.Trip.new(trip_params)
#trip = current_user.trips.new(trip_params)
I've tested all of these ways but still the user_id have not been saved!! Please, help me to understand the problem and its solution for Rails4.
It should work.
def create
if user_signed_in?
#trip = current_user.trips.new(trip_params)
respond_to do |format|
if #trip.save
format.html { redirect_to #trip, notice: 'Trip was successfully created.' }
format.json { render :show, status: :created, location: #trip }
else
format.html { render :new }
format.json { render json: #trip.errors, status: :unprocessable_entity }
end
end
else
session[:trip] = params
redirect_to new_user_session_path
end
end
To solve the problem, I've added this new method to the application_controller.rb:
def after_sign_in_path_for(resource)
# save list if there is a temp_list in the session
if session[:trip].present?
#trip = current_user.trips.new(session[:trip]["trip"])
#trip.save
session[:trip] = nil
return #trip
else
#if there is not temp list in the session proceed as normal
super
end
end
I wish it could be useful for the others.

Retrieve multiple records with find_by method

The method below works and authenticates a user who has been sent a token-link by email.
def login
inv = Invitation.find_by(email: params[:email])
if inv && inv.authenticated?(:invitation, params[:id])
#organization = inv.organization
unless #organization.nil?
render 'profiles/show' and return
else
flash[:danger] = "Error"
redirect_to root_path
end
else
flash[:danger] = "Invalid link"
redirect_to root_path
end
end
This method however seems to assume a person (inv) can only exist once in the Invitation database. This is not the case, the same person/email address can have multiple records in the database. Therefore, I need to rewrite the method to account for such a situation. How can I do this? Can I use .all as added on line 2 below, and use .each?
def login
inv = Invitation.find_by(email: params[:email]).all
if inv
inv.each do |person|
if person.authenticated?(:invitation, params[:id])
#organization = person.organization
unless #organization.nil?
render 'profiles/show' and return
else
flash[:danger] = "Error"
redirect_to root_path and return
end
end
flash[:danger] = "Invalid link"
redirect_to root_path
end
else
flash[:danger] = "Invalid link"
redirect_to root_path
end
end
Error messages:
This code produces the error message below but I'm not sure what else than .all to use:
NoMethodError: undefined method `all' for #<Invitation:0x0000000b869ee8>
You need to use find_all_by or where
inv = Invitation.find_all_by(email: params[:email])
or
inv = Invitation.where(email: params[:email])

Ruby on Rails: redirect_to not working after create and save

I want to redirect_to slider_path after a user submits their email. Currently, only the success message is displayed without a redirect. Here's the code:
class Splash::SubscribersController < ApplicationController
def create
#subscriber = Subscriber.new(params[:subscriber])
if #subscriber.save
success = true
message = "Success! We'll let you know when we launch."
else
success = false
message = "Fail."
end
respond_to do |format|
format.html {
if success
flash[:success] = message
redirect_to slider_path
else
flash[:error] = message
end
redirect_to root_path
}
format.json { render :json => { :success => success, :message => message }.to_json }
end
end
end
Just replace this part of your code:
if success
flash[:success] = message
redirect_to slider_path
else
flash[:error] = message
end
redirect_to root_path
with this:
if success
flash[:success] = message
redirect_to slider_path
else
flash[:error] = message
redirect_to root_path
end
Rails API states:
An action may contain only a single render or a single redirect. Attempting to try to do either again will result in a DoubleRenderError:
def do_something
redirect_to :action => "elsewhere"
render :action => "overthere" # raises DoubleRenderError
end
If you need to redirect on the condition of something, then be sure to add “and return” to halt execution.
def do_something
redirect_to(:action => "elsewhere") and return if monkeys.nil?
render :action => "overthere" # won't be called if monkeys is nil
end
Note the use of and return
Neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
Add a return statement after your redirect. If the action also renders a template by default, any redirects need to be followed by a return statement.
if success
flash[:success] = message
redirect_to slider_path
return # <= Add a return.
else
flash[:error] = message
end
redirect_to root_path

ambethia's reCAPTCHA plugin on Rails 3. Override flash message div defaults?

I have ambethia's reCAPTCHA plugin on Rails 3 working. Does anyone know how to override it's flash message markup? I'd like to reuse my own flash_error div id instead of using the plugin's flash_recaptcha_error div id:
<div id="flash_recaptcha_error">incorrect-captcha-sol</div>
Also, how would you clean up this controller#create?
def create
#post = Post.new(params[:post])
respond_to do |format|
if verify_recaptcha(:model => #post, :error => "reCAPTCHA incorrect. Try again.") && #post.save
flash.now[:notice] = "Created \"#{#post.title}\""
format.html { redirect_to(#post, :notice => 'Post was successfully created.') }
else
flash.now[:error] = "Incorrect word verification. Are you sure you\'re human?"
format.html { redirect_to(:back, :error => 'reCAPTCHA incorrect. Try again.') }
end
end
end
Thanks for reading my question.
Because flash[] is an array you could delete element inside it. When we use recaptcha gem, the flash array contain recaptcha_error element, so you just only delete this element with :
flash.delete(:recaptcha_error) inside your controller.
For example :
if verify_recaptcha(:model=>#object,:message=>"Verification code is wrong", :attribute=>"verification code") && #object.save
#your code if succes
else
flash.delete(:recaptcha_error)
#your code if its fail
end
Maybe it could help you. Thanks
If you're making a User Authentication System from scratch, you may have to do something like this:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
respond_to do |format|
if verify_recaptcha(:model => #user )
if #user.save
format.html { redirect_to root_url, :notice => "You have Signed up!" }
else
format.html { render :new }
end
else
flash.delete(:recaptcha_error)
format.html { redirect_to( root_path , :flash => { :error => 'Please retry the two words of the reCaptcha' } ) }
end
end
end
end

Resources