Why is my rails controller rolling back my ajax commit? - ruby-on-rails

I am having a mysterious problem with the controller receiving my ajax request but not saving it in the database. In my server log I see:
Started POST "/collection_maps" for 127.0.0.1 at 2014-07-07 07:14:04 -0600
Processing by CollectionMapsController#create as */*
Parameters: {"collection_id"=>"2", "manufacturer_id"=>"1", "package_id"=>"14"}
(0.1ms) begin transaction
(0.1ms) rollback transaction
Rendered collection_maps/create.js.erb (1.9ms)
Completed 200 OK in 19.2ms (Views: 4.8ms | ActiveRecord: 0.2ms)
127.0.0.1 - - [07/Jul/2014 07:14:04] "POST /collection_maps HTTP/1.1" 200 - 0.0627
The response I receive in the browser from my create.js.erb file indicates the parameters are null -- but as you can see above, they're clearly there.
(The response comes only as text, the browser doesn't execute the code, but that's another problem. I think.)
// Create a list of errors
var errors = $('<ul />');
errors.append('<li>Package can\'t be blank</li>');
errors.append('<li>Manufacturer can\'t be blank</li>');
errors.append('<li>Collection can\'t be blank</li>');
// Display errors on form
$("#collection-response").html(errors).show();
When I try to create the record in the console, using the same parameters, it works:
irb(main):006:0> c = CollectionMap.new("collection_id"=>"2", "manufacturer_id"=>"1", "package_id"=>"12")
=> #<CollectionMap id: nil, package_id: 12, manufacturer_id: 1, collection_id: 2, created_at: nil, updated_at: nil>
irb(main):007:0> c.save
(0.1ms) begin transaction
SQL (5.7ms) INSERT INTO "collection_maps" ("collection_id", "created_at", "package_id", "manufacturer_id", "updated_at") VALUES (?, ?, ?, ?, ?) [["collection_id", 2], ["created_at", Mon, 07 Jul 2014 06:38:47 UTC +00:00], ["package_id", 12], ["manufacturer_id", 1], ["updated_at", Mon, 07 Jul 2014 06:38:47 UTC +00:00]]
(1.2ms) commit transaction
=> true
irb(main):008:0> c
=> #<CollectionMap id: 6, package_id: 12, manufacturer_id: 1, collection_id: 2, created_at: "2014-07-07 06:38:47", updated_at: "2014-07-07 06:38:47">
I thought maybe it had something to do with CRSF protection (though I don't have user sessions) so I added a skip_filter. Here's my controller code:
class CollectionMapsController < ApplicationController
respond_to :js, :html
skip_before_filter :verify_authenticity_token
# POST /collection_maps
# POST /collection_maps.xml
def create
#collection_map = CollectionMap.new(params[:collection_map])
flash[:notice] = "Collection map successfully added" if #collection_map.save
respond_with( #collection_map, :layout => !request.xhr?)
end
Here's my ajax code:
$.ajax({ url: '<%="#{collection_maps_path}"%>',
type: 'POST',
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token',
'<%="#{form_authenticity_token}"%>')},
dataType: "js",
data: {'collection_id' : this.value,
'manufacturer_id' : $("#remedy_manufacturer_id option:selected").val(),
'package_id' : $("#remedy_package_id option:selected").val()},
});
And finally, my model:
class CollectionMap < ActiveRecord::Base
belongs_to :manufacturer
belongs_to :package
belongs_to :collection
validates_presence_of :package_id, :manufacturer_id, :collection_id
attr_protected :created_at
attr_protected :updated_at
attr_accessible :package_id, :manufacturer_id, :collection_id
end
I am totally baffled, so help would be much appreciated.
UPDATE: The reason my browser was not executing the javascript returned by the controller was because I had dataType: "js" in the ajax request. Should be dataType: "script". Be careful where you cut and paste from!

Your AJAX request is sending back the three parameters you need, but your controller action is looking for them nested below a :collection_map key. You can change your controller to this:
def create
#collection_map = CollectionMap.new(params)
flash[:notice] = "Collection map successfully added" if #collection_map.save
respond_with( #collection_map, :layout => !request.xhr?)
end
Or change your AJAX request to this:
$.ajax({ url: '<%="#{collection_maps_path}"%>',
type: 'POST',
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token',
'<%="#{form_authenticity_token}"%>')},
dataType: "js",
data: {'collection_map': {'collection_id' : this.value,
'manufacturer_id' : $("#remedy_manufacturer_id option:selected").val(),
'package_id' : $("#remedy_package_id option:selected").val()}},
});
Changing the AJAX request is probably preferable; nesting the parameters below a single key is more "Rails-like"/idiomatic.

you are also mixing attr_accessible and attr_protected. Choose One. Or if this is a newer Rails (4.0 + ) project, use the the new params methodology by creating a method like 'collection_map_params' for 'protection' in your CollectioMapsController.

Related

Why does my record have all nil fields after being saved?

I am making an ember and rails app.
I am trying to do a post request to http://localhost:3000/candidates
My request is getting a 200 and is creating a record but everything is nil:
Why is this?
#<Candidate id: 15, name: nil, email: nil, created_at: "2018-08-23 22:28:07", updated_at: "2018-08-23 22:28:07">
here is my controller code:
class CandidatesController < ApplicationController
# POST /candidates
# def create
# #candidate = Candidate.create!(candidate_params)
# json_response(#candidate, :created)
# end
def create
puts "create"
puts params
puts candidate_params
candidate = Candidate.create!(candidate_params)
if candidate.save
render jsonapi: candidate
else
render jsonapi_errors: candidate.errors
end
end
private
def candidate_params
# whitelist params
params.permit(:name, :email)
end
end
and here is my ember code:
import Ember from "ember";
export default Ember.Route.extend({
model() {
// return this.get("store").findAll("candidate");
},
actions: {
createCandidate() {
console.log("create candidate");
let candidate = this.get("store").createRecord("candidate", {
id: 1,
name: "Katie",
email: "katie#gmail.com"
});
candidate.save();
}
}
});
I am also getting this error in my js console:
SyntaxError: Unexpected end of JSON input
I am using the 'jsonapi-rails' gem
Here are the server logs and screen shot of network tab:
NetworkScreenshot
Started POST "/candidates" for 127.0.0.1 at 2018-08-29 14:07:12 +0100
Processing by CandidatesController#create as application/vnd.api+json
create
{"controller"=>"candidates", "action"=>"create"}
{}
(2.7ms) begin transaction
↳ app/controllers/candidates_controller.rb:12
Candidate Create (0.4ms) INSERT INTO "candidates" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2018-08-29 13:07:12.984174"], ["updated_at", "2018-08-29 13:07:12.984174"]]
↳ app/controllers/candidates_controller.rb:12
(1.3ms) commit transaction
↳ app/controllers/candidates_controller.rb:12
(0.1ms) begin transaction
↳ app/controllers/candidates_controller.rb:14
(0.0ms) commit transaction
↳ app/controllers/candidates_controller.rb:14
Completed 200 OK in 9ms (Views: 0.1ms | ActiveRecord: 4.5ms)
This is my adapter:
import DS from "ember-data";
export default DS.JSONAPIAdapter.extend({
host: "http://localhost:3000",
dataType: "json"
});
I am not using any serializer in the frontend. should I be?
Yes I am expecting jsonapi data.
You have to define a model into your ember app :
https://guides.emberjs.com/release/models/#toc_models
Moreover, if you are using jsonapi specs, you should set related adapter
// app/adapters/application.js
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({});
and serializer
// app/serializers/application.js
import DS from 'ember-data';
export default DS.JSONAPISerializer.extend({});

Bad response from server after tinymce image upload

I'm trying to upload images using paperclip and tinymce-rails-image-upload following this demo. I'm uploading images in a question model (that belongs to comments). When I upload, I get a 'got a bad response from the server' message and the image isn't shown in the editor, however it does create a new question.
Here is my the log after upload:
Processing by TinymceAssetsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"auth token", "hint"=>"", "file"=>#<ActionDispatch::Http::UploadedFile:0x000001025a2780 #tempfile=# <File:/var/folders/t4/86vsrmds42j84r36kwpng7k00000gn/T/RackMultipart20150207- 12522-9rj6xq>, #original_filename="applecash.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"file\"; filename=\"applecash.jpg\"\r\nContent-Type: image/jpeg\r\n">, "alt"=>""}
Command :: identify -format '%wx%h,%[exif:orientation]' '/var/folders/t4/86vsrmds42j84r36kwpng7k00000gn/T/RackMultipart20150207-12522-9rj6xq[0]' 2>/dev/null
Unpermitted parameters: utf8, authenticity_token
(0.1ms) begin transaction
Question Load (0.5ms) SELECT "questions".* FROM "questions" WHERE (questions.position IS NOT NULL) AND (1 = 1) ORDER BY questions.position DESC LIMIT 1
Binary data inserted for `string` type on column `file_content_type`
SQL (0.8ms) INSERT INTO "questions" ("created_at", "file_content_type", "file_file_name", "file_file_size", "file_updated_at", "position", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?) [["created_at", Sun, 08 Feb 2015 18:35:07 UTC +00:00], ["file_content_type", "image/jpeg"], ["file_file_name", "timcook.jpg"], ["file_file_size", 120040], ["file_updated_at", Sun, 08 Feb 2015 18:35:07 UTC +00:00], ["position", 9], ["updated_at", Sun, 08 Feb 2015 18:35:07 UTC +00:00]]
(7.3ms) commit transaction
Completed 200 OK in 68ms (Views: 0.6ms | ActiveRecord: 8.7ms)
Here is the tinymce controller:
class TinymceAssetsController < ApplicationController
respond_to :json
def create
geometry = Paperclip::Geometry.from_file params[:file]
question = Question.create params.permit(:file, :alt, :hint)
render json: {
question: {
url: question.file.url,
height: geometry.height.to_i,
width: geometry.width.to_i
}
}, layout: false, content_type: "text/html"
end
end
The questions controller create action looks like this (do I add #comment and the additional parameters to the tinymce controller?):
def create
#comment = Comment.find(params[:comment_id])
#question = #comment.questions.new(question_params)
end
...
def question_params
params.require(:question).permit(:body, :comment_id, :user_id, :file, :position)
end
The question model:
class Question < ActiveRecord::Base
has_attached_file :file
end
and the editor view:
<%= simple_form_for [#comment, Question.new] do |f| %>
<%= f.text_area :body, :class => "tinymce", :rows => 10, :cols => 60 %>
<% end %>
<%= tinymce plugins: ["uploadimage"] %>
I'm confused as to why its creating a new question for every uploaded image and what's still causing the 'bad response' error.
it seems tinymce-rails-imageupload expects "image" in response to uploaded file
render json: {
image: {
url: question.file.url,
height: geometry.height.to_i,
width: geometry.width.to_i
}
}, layout: false, content_type: "text/html"

rails-4 validation says field cant be blank even though the field is not blank

I have a activerecord model with a validates :body, presence: true. When a form is filled and submited, I get {:body=>["can't be blank"]} even though the body is not actually blank. If I remove the validation from the model, and re-submit, the record is successfully created. Why is the validation saying the body field is blank when it is not blank.
The controller.
class SqlTemplatesController < ApplicationController
def create
#sql_template = SqlTemplate.new(sql_template_params)
respond_to do |format|
if #sql_template.save
format.html { redirect_to #sql_template, notice: 'Sql template was successfully created.' }
end
end
private
def sql_template_params
params.require(:sql_template).permit(:body, :path, :format, :locale, :handler, :partial)
end
end
The Model
class SqlTemplate < ActiveRecord::Base
validates :body, :path, presence: true
validates :format, inclusion: Mime::SET.symbols.map(&:to_s)
validates :locale, inclusion: I18n.available_locales.map(&:to_s)
validates :handler, inclusion: ActionView::Template::Handlers.extensions.map(&:to_s)
def to_liquid
SqlTemplateDrop.new(self)
end
def body=(text)
if self[:handler] == 'liquid'
#template = Liquid::Template.parse(text)
self[:body] = Marshal.dump(#template)
end
end
def render(options = {})
template.render options
end
private
def template
return #body unless #body.nil?
#body = Marshal.load(self[:body])
end
end
In the rails console If create a new record and set the body field to either a string body => "message body" or a liquid markup eg body => "{{body}}, it will raise the error {:body=>["can't be blank"]} but if remove the validation they work.
irb(main):016:0> a = SqlTemplate.create(:body => "{{body}", path => "mail/liquid_database_template", :format => "html", :locale => "en", :handler => "liquid", :partial => false)
(0.1ms) begin transaction
(0.1ms) rollback transaction
irb(main):016:0> a.errors.messages
=> {:body=>["can't be blank"]}
If I remove the validation and submit a form, it all works, as shown below:
Started POST "/sql_templates" for 127.0.0.1 at 2014-03-11 15:28:14 +0000
Processing by SqlTemplatesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"GVsRbsCKSlcEMiL1AzXE0tT8LBCNhhoK6wSGzvnB80A=", "sql_template"=>{"body"=>"{{body}}", "path"=>"customer_mail/liquid_database_template", "format"=>"html", "locale"=>"en", "handler"=>"liquid", "partial"=>"0"}, "commit"=>"Create Sql template"}
#<SqlTemplate id: nil, body: nil, path: "customer_mail/liquid_database_template", format: "html", locale: "en", handler: "liquid", partial: false, created_at: nil, updated_at: nil>
(0.1ms) begin transaction
SQL (9.4ms) INSERT INTO "sql_templates" ("created_at", "format", "handler", "locale", "path", "updated_at") VALUES (?, ?, ?, ?, ?, ?) [["created_at", "2014-03-11 15:28:14.869619"], ["format", "html"], ["handler", "liquid"], ["locale", "en"], ["path", "customer_mail/liquid_database_template"], ["updated_at", "2014-03-11 15:28:14.869619"]]
(621.4ms) commit transaction
Redirected to http://localhost:3000/sql_templates/7
Completed 302 Found in 662ms (ActiveRecord: 630.9ms)
Started GET "/sql_templates/7" for 127.0.0.1 at 2014-03-11 15:28:15 +0000
Processing by SqlTemplatesController#show as HTML
Parameters: {"id"=>"7"}
SqlTemplate Load (3.1ms) SELECT "sql_templates".* FROM "sql_templates" WHERE "sql_templates"."id" = ? LIMIT 1 [["id", 7]]
Rendered sql_templates/show.html.erb within layouts/application (11.4ms)
Completed 200 OK in 52ms (Views: 46.0ms | ActiveRecord: 3.1ms)
If I add the validation back and submit it fails as shown below:
Started POST "/sql_templates" for 127.0.0.1 at 2014-03-11 14:34:22 +0000
ActiveRecord::SchemaMigration Load (0.3ms) SELECT "schema_migrations".* FROM "schema_migrations"
Processing by SqlTemplatesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"GVsRbsCKSlcEMiL1AzXE0tT8LBCNhhoK6wSGzvnB80A=", "sql_template"=> {"body"=>"{{body}}", "path"=>"customer_mail/liquid_database_template", "format"=>"html", "locale"=>"en", "handler"=>"liquid", "partial"=>"0"}, "commit"=>"Create Sql template"}
#<SqlTemplate id: nil, body: nil, path: "customer_mail/liquid_database_template", format: "html", locale: "en", handler: "liquid", partial: false, created_at: nil, updated_at: nil>
(0.2ms) begin transaction
(0.2ms) rollback transaction
Rendered sql_templates/_form.html.erb (32.6ms)
Rendered sql_templates/new.html.erb within layouts/application (57.1ms)
Completed 200 OK in 208ms (Views: 143.0ms | ActiveRecord: 1.4ms)
Your body setter is getting called before the setter for handler. So self[:handler] will be nil when it goes into the body= method
You can try one of these
i) Change the order of your hash
a = SqlTemplate.create(:handler => "liquid", :body => "{{body}", path => "mail/liquid_database_template", :format => "html", :locale => "en", :partial => false)
ii) Set the body later after setting the handler
a = SqlTemplate.new(:handler => "liquid", path => "mail/liquid_database_template", :format => "html", :locale => "en", :partial => false)
a.body = "{{body}}"
a.save
I resolved it myself. The problem was with the setter method for the body field. Normally rails automatically defines this but if it is being overridden to do some extra things which is the case here, I still needed to set self[:body] = text at the top before everything else. Note that text is the value passed in to the field through the form. Without that validates presence will fail.
def body=(text)
self[:body] = text
end

undefined method 'title'

I'm getting an error on the show action when new guidelines are being added to my app. This is since I changed the show action to allow for custom routes...The new guideline is added to the database correctly...
My show action in guidelines_controller.rb is
def show
#guideline = Guideline.where(title: params[:title]).first
respond_to do |format|
format.html # show.html.erb
format.json { render json: #guideline }
end
end
model guidelines.rb is
attr_accessible :content, :hospital, :title, :user_id, :guideline_id, :specialty
show view is
<p>Title: <%= link_to #guideline.title, seeguideline_path(#guideline.title) %> </p
Error message is
console says...
Started POST "/guidelines" for 127.0.0.1 at 2013-02-22 17:07:29 +1100
Processing by GuidelinesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"bQKIkSb4Wzr46FERMbU82Q1qMzd3GrGNq6Nqmr0KNhY=", "guideline"=>{"title"=>"Stackoverflo", "specialty"=>"Dermatology", "hospital"=>"Stack Hospital", "content"=>"www.stackoverflow.com"}, "commit"=>"Create Guideline"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 11 LIMIT 1
(0.1ms) begin transaction
Guideline Exists (0.4ms) SELECT 1 AS one FROM "guidelines" WHERE (LOWER("guidelines"."hospital") = LOWER('Stack Hospital') AND "guidelines"."title" = 'Stackoverflo') LIMIT 1
SQL (65.0ms) INSERT INTO "guidelines" ("content", "created_at", "hospital", "specialty", "subtitle", "title", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?) [["content", "www.stackoverflow.com"], ["created_at", Fri, 22 Feb 2013 06:07:29 UTC +00:00], ["hospital", "Stack Hospital"], ["specialty", "Dermatology"], ["subtitle", nil], ["title", "Stackoverflo"], ["updated_at", Fri, 22 Feb 2013 06:07:29 UTC +00:00], ["user_id", 11]]
SOLR Request (152.5ms) [ path=#<RSolr::Client:0x007f9c79f2fc48> parameters={data: <?xml version="1.0" encoding="UTF-8"?><add><doc><field name="id">Guideline 35</field><field name="type">Guideline</field><field name="type">ActiveRecord::Base</field><field name="class_name">Guideline</field><field name="title_text">Stackoverflo</field></doc></add>, headers: {"Content-Type"=>"text/xml"}, method: post, params: {:wt=>:ruby}, query: wt=ruby, path: update, uri: http://localhost:8982/solr/update?wt=ruby, open_timeout: , read_timeout: } ]
(3.7ms) commit transaction
Redirected to http://localhost:3000/guidelines/35
SOLR Request (100.3ms) [ path=#<RSolr::Client:0x007f9c79f2fc48> parameters={data: <?xml version="1.0" encoding="UTF-8"?><commit/>, headers: {"Content-Type"=>"text/xml"}, method: post, params: {:wt=>:ruby}, query: wt=ruby, path: update, uri: http://localhost:8982/solr/update?wt=ruby, open_timeout: , read_timeout: } ]
Completed 302 Found in 485ms (ActiveRecord: 69.8ms)
Started GET "/guidelines/35" for 127.0.0.1 at 2013-02-22 17:07:30 +1100
Processing by GuidelinesController#show as HTML
Parameters: {"id"=>"35"}
Guideline Load (0.2ms) SELECT "guidelines".* FROM "guidelines" WHERE "guidelines"."id" = ? LIMIT 1 [["id", "35"]]
Guideline Load (0.2ms) SELECT "guidelines".* FROM "guidelines" WHERE "guidelines"."title" IS NULL LIMIT 1
Rendered guidelines/show.html.erb within layouts/application (18.3ms)
Completed 500 Internal Server Error in 83ms
ActionView::Template::Error (undefined method `title' for nil:NilClass):
6:
7: <div class="guideline span10">
8:
9: <p>Title: <%= link_to #guideline.title, seeguideline_path(#guideline.title) %> </p>
10: <strong> <a href="<%= #guideline.content %>", target = '_blank'>Link to guideline</a> </strong>
11: <p>Hospital Name: <%= #guideline.hospital %></p>
12:
app/views/guidelines/show.html.erb:9:in `_app_views_guidelines_show_html_erb__4234346501713687788_70155056040280'
app/controllers/guidelines_controller.rb:132:in `show'
route is
get '/:title', to: 'guidelines#show', as: :seeguideline
Are you sure your route is passing the :title param? What does your console log show for the SQL request for the query? I have a feeling your route isn't passing what you think it's passing...
Also, you're going to want to handle the case that the query comes back empty anyway. Having the app blow up probably isn't what you want.

Rails new form -> nil

The task model has just one field : title.
I've made a form to add a new task with one single field : title
But in the create method, we can see that title is filled by "test"
but in the query, we can see "nil" ... any ideas ?
thanks
Started POST "/tasks" for 127.0.0.1 at 2013-01-03 13:16:44 -0500
Processing by TasksController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"iWaK1QX6VCyeUCueLrRNErJEtdm/ZNxg4d3LU0vKjnY=", "task"=>{"title"
=>"test"}, "commit"=>"Add a new task "}
(0.1ms) begin transaction
SQL (0.9ms) INSERT INTO "tasks" ("created_at", "title", "updated_at") VALUES (?, ?, ?) [["created_at", Thu, 03 Jan 2013 18:16:44 UTC +00:00], ["title", nil], ["updated_at", Thu, 03 Jan 2013 18:16:44 UTC +00:00]]
(0.8ms) commit transaction
Redirected to http://0.0.0.0:3000/tasks
Completed 302 Found in 8ms (ActiveRecord: 1.8ms)
here is the create method
def create
#task = Task.new(params[:post])
if #task.save
redirect_to tasks_path, :notice => "Task successfully saved"
else
render "new"
end
end
The problem is that you are fetching post instead of task
#task = Task.new(params[:task])
Make sure your attribute is accessible or you won't be able to mass-assign changes to it:
class Task < ActiveRecord::Base
attr_accessible :title
end
You should have unit tests that properly exercise your models to be sure that they can be updated as you do in the controller. Those will quickly uncover any attributes which have not been correctly flagged.
Rails 2.3 and prior were not strict about this, you could mass-assign anything, but Rails 3 will not assign these attributes unless they are specifically allowed.
Make sure
attr_accessible :title
is in your Task model (task.rb)
UPDATE:
change params[:post] to params[:task]:
#task = Task.new(params[:task])
In your tasks_controller.rb , you must have create method which will handle POST request and accept parameters which are passed though request .
def create
task = Task.new(params[:task])
task.save
end

Resources