Create.js.erb Not Showing In AJAX with Rails - ruby-on-rails

I am trying to get AJAX working on a form in my rails application and am about 75% of the way there. I have a form where a person can create an activity and tag that activity with skills. I would like to provide the ability for them to create a new skill right within the form. I can replace the "Create a New Skill" link with a form and then save the record without any problem. My issue is after the record is saved, rails keeps redirecting me back to the my home page rather than back to the page with the form. The redirect is normal behavior if the user was creating a skill through the typical HTML form.
The link on my page to create a new skill that turns into a form:
<%= link_to "Create A New Skill", new_skill_path, :id => "new-skill-link", remote: true %>
The new skill form that replaces the link:
<%= form_for Skill.new, :remote => true do |f| %>
<%= f.text_field :description %>
<%= f.submit "Save", :class => 'btn-large btn-primary' %>
<% end %>
My skills controller (the New and Create methods):
def new
#skill = Skill.new
#tags = current_user.tags
respond_to do |format|
format.html
format.js
end
end
def create
#skill = current_user.skills.new(params[:skill])
params[:skill][:tag_ids] ||= []
respond_to do |format|
if #skill.save
flash[:success] = "Skill was successfully created!"
format.html { redirect_to home_page_url }
format.js { render action: "create" }
else
flash.now[:error] = "There was an error saving your skill."
format.html { render action: "new" }
format.js { render action: "new" }
end
end
end
My new.js.erb:
$("#new-skill-link").hide().after('<%= j render("skills/remote_form") %>');
My create.js.erb:
$("#new-skill").remove();
$("#new-skill-link").show();
$(".skill-list ul").append('<%= j render(#skill) %>');
It seems that rails is interpreting the request as HTML so it is responding with the HTML page. I tried adding :format => :js to the skill form but rails just rendered the javascript in my browser without interpreting it.
When I look at the log on the web server, I don't see any errors. I get:
Started POST "/skills" for 127.0.0.1 at 2012-12-31 20:02:16 -0700
Processing by SkillsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"xxxxx", "skill"=>{"description"=>"Example Skill"}, "commit"=>"Save"}
User Load (62.8ms) SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'xxxxx' LIMIT 1
(0.1ms) begin transaction
SQL (15.4ms) INSERT INTO "skills" ("created_at", "description", "updated_at", "user_id") VALUES (?, ?, ?, ?) [["created_at", Tue, 01 Jan 2013 03:02:16 UTC +00:00], ["description", "Example Skill"], ["updated_at", Tue, 01 Jan 2013 03:02:16 UTC +00:00], ["user_id", 1]]
(1.4ms) commit transaction
Redirected to http://localhost:3000/home_page
Completed 302 Found in 96ms (ActiveRecord: 79.7ms)
Any thoughts?

The reason is, you should not do redirects inside the create method, because the AJAX request is kind of lost in the middle (you could see this via Firebug/FF).
Following is a sample code:
Ex: assuming I have a scaffold called project
projects_controller.rb
class ProjectsController < ApplicationController
#project = Project.new(params[:project])
if #project.save
flash.now[:success] = ["#{#project.name} sucessfully created"]
else
flash.now[:errors] = #project.errors.full_messages
end
end
in view/projects
_form.html.erb
<div id="message"></div>
<%= form_for #project :remote => true, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.text_field :name, :class => 'span3', :placeholder => "Project name" %>
<%= f.submit nil, :class => 'btn btn-success' %>
<% end %>
create.js.erb
$("#message").html("<%= escape_javascript raw(flash_display) %>");
in helper
module ApplicationHelper
def flash_display
response = "<div class='alert #{alert_class}'>"
response += "<button type='button' class='close' data-dismiss='alert'>x</button>"
flash.each do |name, msg|
msg.each do |m|
response = response + content_tag(:p, m)
end
end
response += "</div>"
flash.discard
response
end
private
def alert_class
css_class = case flash.first[0]
when :errors then "alert-error"
when :success then "alert-success"
when :notifications then "alert-block"
end
css_class
end
end
So as you can see, I'm not redirecting from my create method, after saving I'm just passing the message of the status. So your page will not refresh and only update the messages.

Related

Blog App not saving attributes to database upon form submission

I am following a guide to build a blog with rails, simple Post model with title and body.
I am using simple form and upon form submission to create a new post, the post saves created_at and updated_at values, but not the actual content submitted in the form.
I have attempted removing the code for simple form and using Rails native form_for. This DOES save all values to the database. I am new to simple form, not certain whether or not I am using it correctly.
Here is the console record:
Started POST "/posts" for ::1 at 2019-08-17 13:51:01 -0500
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"qY8kYZxVIMBL8lzHYuQ4qOu6nXsTGLWCRhLPJ2eiAU8EyzR61fZppAFBYmgcm3rx02FYAHcCgFBVlUyDTLtDGA==", "post"=>{"title"=>"Simple Form Test", "body"=>"<p>Test Test Test</p>\r\n"}, "commit"=>"Create Post"}
(0.0ms) begin transaction
SQL (3.3ms) INSERT INTO "posts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2019-08-17 18:51:01.325736"], ["updated_at", "2019- 08-17 18:51:01.325736"]]
(7.7ms) commit transaction
Redirected to http://localhost:3000/posts/3
Completed 302 Found in 28ms (ActiveRecord: 11.1ms)
Here is the form:
<%= simple_form_for #post do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2>
<%= "#{pluralize(#post.errors.count, "error")} prohibited this post from being saved:" %>
</h2>
<ul>
<% #post.errors.full_messages.each do |msg| %>
<li>
<%= msg %>
</li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.input :title, class: "form-control" %>
</div>
<div class="form-group">
<%= f.input :body, :as => :ckeditor, input_html: {:ckeditor => {:toolbar => 'FULL'}}, class: "form-control" %>
</div>
<div class="form-group">
<%= f.button :submit %>
</div>
<% end %>
Here is the controller:
class PostsController < ApplicationController
before_action :find_post, only: [:edit, :update, :show, :delete]
# Index action to render all posts
def index
#posts = Post.all
end
# New action for creating post
def new
#post = Post.new
end
# Create action saves the post into database
def create
#post = Post.new
if #post.save(post_params)
flash[:notice] = "Successfully created post!"
redirect_to post_path(#post)
else
flash[:alert] = "Error creating new post!"
render :new
end
end
# Edit action retrives the post and renders the edit page
def edit
end
# Update action updates the post with the new information
def update
if #post.update_attributes(post_params)
flash[:notice] = "Successfully updated post!"
redirect_to post_path(#post)
else
flash[:alert] = "Error updating post!"
render :edit
end
end
# The show action renders the individual post after retrieving the the id
def show
end
# The destroy action removes the post permanently from the database
def destroy
if #post.destroy
flash[:notice] = "Successfully deleted post!"
redirect_to posts_path
else
flash[:alert] = "Error updating post!"
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end
def find_post
#post = Post.find(params[:id])
end
end
Hopin
g to be able to create posts with body and title, and learn more about simple form.
Thanks in advance!
You wrote #post = Post.new without pass your parameters to your object, so when you save you object you save an empty object.
It should be either :
#post = Post.new(post_params)
Or directly
#post = Post.create(post_params)

Rails 4 - partial rendered with update.js.erb not showing updated values

On the account settings page for my Rails app I am trying to use Ajax to have the displayed users settings info updated after the update form is submitted. Right now when I submit the form the database gets updated and the _account_settings.html.erb partial appears to get re-rendered, but the partial doesn't show the updated information. For example, say the users name is "John Doe" and he clicks the '#edit_name' link. This renders the _name_form.html.erb which he can use to change his name. When he changes his name and submits the form, let's say he changes it to "Joe Blow", the form disappears and the 'Name: <%= current_user.name %> - click to edit' shows up again but the name is still "John Doe" even though the name in the DB is now "Joe Blow". If I refresh the page the name now appears as "Joe Blow". I am using devise and made a custom registrations controller to allow the user to update certain attributes without entering a password (name still requires the current password). I used this code provided by the devise and simply added
respond_to do |format|
format.html { redirect_to edit_user_registration_path }
format.js
end
to the end of the 'if #user.update_attributes(account_update_params)' block in the above link. Any ideas as to why the re-rendered partial isn't showing the updated user information?
edit.html.erb
<h1>Account Settings</h1>
<div id="account_settings_container">
<%= render 'account_settings' %>
</div>
_account_settings.html.erb
<div class="user-attribute-container">
<%= link_to "#", class: "edit-attribute", id: "edit_name", remote: true do %>
<p>Name: <%= current_user.name %> - click to edit</p>
<% end %>
</div>
<div class="user-attribute-container">
<%= link_to "#", class: "edit-attribute", id: "edit_email", remote: true do %>
<p>Email: <%= current_user.email %> - click to edit</p>
<% end %>
</div>
<div class="user-attribute-container">
<%= link_to "#", class: "edit-attribute", id: "edit_password", remote: true do %>
<p>Password: click to edit your password</p>
<% end %>
</div>
<%= javascript_tag do %>
$("#edit_name").click(function() {
$(this).hide().after("<%= escape_javascript(render('name_form')) %>");
});
$("#edit_email").click(function() {
$(this).hide().after("<%= escape_javascript(render('email_form')) %>");
});
$("#edit_password").click(function() {
$(this).hide().after("<%= escape_javascript(render('password_form')) %>");
});
<% end %>
_name_form.html.erb (the email and password form partials have :email, :password & :password_confirmation instead of :name, otherwise they're the same)
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :method => :put, :html => { id: "edit_user_name" }, remote: true) do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name %>
<%= f.label :password_field, "Password" %>
<%= f.password_field :current_password %>
<%= f.submit "Update" %>
<% end %>
update.js.erb
$("#account_settings_container").html("<%= escape_javascript(render('account_settings')) %>");
From the log file:
Started PUT "/users" for 127.0.0.1 at 2014-06-09 15:01:21 -0700<br>
Processing by RegistrationsController#update as JS<br>
Parameters: {"utf8"=>"✓", "user"=>{"name"=>"Joe Blow", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}<br>
[1m[36mUser Load (0.0ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = 14 ORDER BY "users"."id" ASC LIMIT 1[0m<br>
[1m[35mUser Load (0.0ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 14]]<br>
[1m[36m (0.0ms)[0m [1mBEGIN[0m<br>
[1m[35mSQL (0.0ms)[0m UPDATE "users" SET "name" = $1, "updated_at" = $2 WHERE "users"."id" = 14 [["name", "Joe Blow"], ["updated_at", Mon, 09 Jun 2014 15:01:21 PDT -07:00]]<br>
[1m[36m (0.0ms)[0m [1mCOMMIT[0m<br>
Rendered registrations/_name_form.html.erb (15.6ms)<br>
Rendered registrations/_email_form.html.erb (0.0ms)<br>
Rendered registrations/_password_form.html.erb (15.6ms)<br>
Rendered registrations/_account_settings.html.erb (46.9ms)<br>
Rendered registrations/update.js.erb (46.9ms)<br>
Completed 200 OK in 219ms (Views: 78.1ms | ActiveRecord: 0.0ms)
Custom devise registrations controller:
class RegistrationsController < Devise::RegistrationsController
def update
#user = User.find(current_user.id)
successfully_updated = if needs_password?(#user, params)
#user.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
else
# remove the virtual current_password attribute
# update_without_password doesn't know how to ignore it
params[:user].delete(:current_password)
#user.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
end
if successfully_updated
# sign_in #user, :bypass => true
respond_to do |format|
format.html { redirect_to edit_user_registration_path }
format.js
end
else
respond_to do |format|
format.html { render "edit" }
format.js
end
end
end
private
def needs_password?(user, params)
user.email != params[:user][:email] || params[:user][:password].present? || user.name != params[:user][:name]
end
end
current_user is generated by Devise using a before_filter. So the object returned, will be the user as it was before that action method was called. You need to use the #user object which is the user object that is modified by the action method.
So for example:
<p>Name: <%= #user.name %> - click to edit</p>

Rails Paperclip inserting instead of updating

I created a simple application that has a Product and an Image model. Product has_many Images and Images has an attached file attribute (paperclip).
I created a simple_form for creating/editing Products and it works fine on creation. However, when editing a Product that has N images, rails inserts more N files - empty files.
I have set up a Simple Form custom input that tests if the image attachment exists in which case instead of rendering the builders input, it only renders an image_tag().
I see the html generated and it show something strange, a hidden tag:
<input id="product_images_attributes_0_id" name="product[images_attributes][0][id]" type="hidden" value="14">
And in the rails server console I see:
Processing by ProductsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"asdfasdfaasdf=", "product"=>{"reference"=>"Y1112CYL.E2", "images_attributes"=>{"0"=>{"id"=>"14"}}}, "commit"=>"Update Product", "id"=>"20"}
Product Load (0.6ms) SELECT "products".* FROM "products" WHERE "products"."id" = $1 LIMIT 1 [["id", "20"]]
Unpermitted parameters: id
(0.2ms) BEGIN
SQL (1.0ms) INSERT INTO "images" ("created_at", "imageable_id", "imageable_type", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["created_at", Tue, 18 Feb 2014 05:05:13 UTC +00:00], ["imageable_id", 20], ["imageable_type", "Product"], ["updated_at", Tue, 18 Feb 2014 05:05:13 UTC +00:00]]
(0.6ms) COMMIT
Here is the code to my implementation. If someone could help I would be very happy! Please pardon me if I left out any import part of the code, I will gladly edit the question to include it.
_form.html.erb
<%= simple_form_for(#product) do |f| %>
<%= f.error_notification %>
<div class="inputs">
<%= f.input :reference %>
<h3>Images</h3>
<div id='images'>
<%= f.simple_fields_for :images do |image| %>
<%= render 'image_fields', :f => image %>
<% end %>
<div class='links'>
<%= link_to_add_association 'New image', f, :images %>
</div>
</div>
</div>
<div class="actions">
<%= f.button :submit %>
</div>
<%end%>
_image_fields.html.erb
<%= content_tag :div, class: "nested-fields images-fields" do %>
<%= content_tag :div, id: "new-image" do %>
<% if f.object.photo.exists? %>
<% f.template.image_tag(f.object.photo.url(:thumb)) %>
<% else %>
<% f.input :photo, :as => :photo %>
<% end %>
<% end %>
<% end %>
app/inputs/photo_input.erb
class PhotoInput < SimpleForm::Inputs::FileInput
def input
out = '' # the output string we're going to build
# check if there's an uploaded file (eg: edit mode or form not saved)
if object.send("#{attribute_name}?")
# append preview image to output
# <%= image_tag #user.avatar.url(:thumb), :class => 'thumbnail', id: 'avatar' %>
out << template.image_tag(object.send(attribute_name).url(:thumb), :class => 'thumbnail', id: 'photo')
else
# append file input. it will work accordingly with your simple_form wrappers
(out << #builder.file_field(attribute_name, input_html_options)).html_safe
end
end
end
ProductsController#update
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
For posterity, #omarvelous' comment seems to have solved it:
I added the reject if all blank to my accepts_nested_attributes_for
accepts_nested_attributes_for :images, :allow_destroy => true, :reject_if => :all_blank
Edit:
It turns out there is an issue with this solution. When reject_if => :all_blank is it stops the destroy from working properly. See this post that shows a workaround -- that I did not manage to get to work.

Ruby on rails redirect_to won't redirect after save, just stays on page (but does save)

Here is my code:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to :success }
else
format.html { render :new }
format.js { render :form_errors }
end
end
end
end
View:
<div id="joinFormContainer">
<%= form_for #user, :remote => true do |f| %>
<div id="firstNameField">
<%= f.text_field :first_name, :placeholder => "First Name" %>
</div>
<div id="lastNameField">
<%= f.text_field :last_name, :placeholder => "Last Name" %>
</div>
<div id="emailFieldJoin">
<%= f.text_field :email, :placeholder => "Email" %>
</div>
<div id="passwordFieldJoin">
<%= f.password_field :password, :placeholder => "Password" %>
</div>
<div id="usernameField">
<%= f.text_field :username, :placeholder => "Username" %>
</div>
<div id="joinButton"> <%= f.submit 'Join Us', :id =>"join_submit" %> </div>
</div><% end %>
<div id="error_explanation">
<%= #user.errors.full_messages.first if #user.errors.any? %>
</div>
</div>
<p> </p>
</div>
</div>
log:
Binary data inserted for `string` type on column `encrypted_password`
Binary data inserted for `string` type on column `password_salt`
SQL (0.9ms) INSERT INTO "users" ("created_at", "email", "encrypted_password", "first_name", "last_name", "password_salt", "updated_at", "username") VALUES (?, ?, ?, ?, ?, ?, ?, ?) [["created_at", Wed, 26 Oct 2011 23:40:03 UTC +00:00], ["email", "fdfdfdfdfdffdf#sdsd.sdd"], ["encrypted_password", "$2a$10$vFOoxHfvc3N2jNPMgx3iN.cNrxENvO5qAaSTaUa5itmzb0uADV9ZS"], ["first_name", "fddffdf"], ["last_name", "dffdffddff"], ["password_salt", "$2a$10$vFOoxHfvc3N2jNPMgx3iN."], ["updated_at", Wed, 26 Oct 2011 23:40:03 UTC +00:00], ["username", "fdgdgddgfdfd"]]
Redirected to http://localhost:3000/success
Completed 302 Found in 87ms
Started GET "/success" for 127.0.0.1 at 2011-10-27 00:40:03 +0100
Processing by UsersController#success as JS
Rendered users/success.html.erb within layouts/application (0.0ms)
Completed 200 OK in 10ms (Views: 10.1ms | ActiveRecord: 0.0ms)
After save the user isn't redirected to temporary success page. Am I missing something?
I also tried redirect_to 'success'
This simple change to the controller solved my issue:
I replaced:
format.html { redirect_to :success }
with:
format.js { render :js => "window.location = '#{success_path}'" }
all is working fine now.
Decided to not bother with recaptcha for now
EDIT:
From reading your logs, your form is being processed as JS. If you want the redirect, then remove the remote=>true from your form for now
The rest is my original answer, it may be an idea to implement some of it anyway:
I think you need redirect_to success_path
UPDATE:
ok, this will work, (hopefully):
1- in routes.rb do the following:
resources :users do
member do
get 'success'
end
end
In User controller, create a new action called success
def success
#user = User.find(params[:id])
end
In Create action
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to success_user_path(#user) }
else
format.html { render :new }
format.js { render :form_errors }
end
end
Then create /views/users/success.html.erb (or haml) and put whatever you want in it

Why do I get this error?

I'm getting this error:
ActiveRecord::RecordNotFound (Couldn't find Video without an ID):
app/controllers/videos_controller.rb:52:in `topic_update'
It's referring to this action in my videos controller:
def topic_update
#video = Video.find(params[:id])
respond_to do |format|
if #video.update_attributes(params[:video])
format.html { redirect_to(#video) }
format.js
else
format.html { render :action => "edit" }
end
end
end
The error is thrown after this form sends a PUT request:
<%= form_for #video, :url => {:action => "topic_update"}, :remote => true do |f| %>
<div class="field">
<%= f.text_field :topic_names, :class => "topic_field" %>
</div>
<%= f.submit "Add Topic", :id => 'topic_submit' %>
<% end %>
This is what happens according to my logs:
Started PUT "/topic/update.js" for 127.0.0.1 at Mon Apr 11 00:12:19 -0700 2011
Processing by VideosController#topic_update as JS
Parameters: {"video"=>{"topic_names"=>"eedefva"}}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 57 LIMIT 1
I have this in my routes.rb file:
resources :videos
match '/topic/update' => "videos#topic_update"
This is because your 'topic_update' method will treat as a 'GET' method where as you want it as a post method,
try this in your routes.rb
resources :videos do
member do
put 'topic_update'
end
end
I haven't tested this but :D
read here for more info (http://guides.rubyonrails.org/routing.html)
HTH
cheers
sameera
Basically, you are trying to update a non-existent (not saved before) object.
This method form_for #video would add id parameter if #video is referring to an existent record that was saved before.
Please make sure you're calling update procedure (showing "edit" form) only if #video corresponds to a stored record.

Resources