RoR; Object expected got string - ruby-on-rails

I found several topics related , but couldn't figure out how to solve this problem,
This is my code
<%= f.label :projeto %><br>
<%= f.collection_select :projeto, Projeto.order(:id), :id, :name, include_blank: true %>
model => task belongs_to projeto and projeto has_many tasks
Full Error:
ActiveRecord::AssociationTypeMismatch at /tasks/1
Projeto(#69996814678740) expected, got String(#69996762580840)
Database is set to t.references.
Task_controller
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to #task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: #task }
else
format.html { render :edit }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
def task_params
params.require(:task).permit(:seq, :descr, :seqpai, :typo, :hour, :projeto)
end
Started PATCH "/tasks/1" for 127.0.0.1 at 2015-06-18 14:30:23 -0300
Processing by TasksController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Is7YTC0v5OONEEsIgOvmI+CEuVYG/WsoKWzskGippD2eOwthKVHb2dI+S19GkkI9aU0IwTrzwERlLq2ybWbGxw==", "task"=>{"seq"=>"0", "descr"=>"Projeto", "seqpai"=>"", "typo"=>"Analitica", "hour"=>"12", "projeto"=>"1"}, "commit"=>"Update Task", "id"=>"1"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]]
Task Load (0.2ms) SELECT "tasks".* FROM "tasks" WHERE "tasks"."id" = ? LIMIT 1 [["id", 1]]
(0.2ms) begin transaction
(0.1ms) rollback transaction
Completed 500 Internal Server Error in 25ms (ActiveRecord: 0.8ms)

Normally this is caused by assigning a string to something expecting a model association. For example:
# Not allowed, `project=` expects a Project model
#task.project = params[:project_id]
# Converts parameter into model, but may throw exception
#task.project = Project.find(params[:project_id])
# Direct assignment, requires validation on model level
#task.project_id = params[:project_id]

I changed the View for
<%= f.label :projeto_id %>
and permited in controller projeto_id
Then worked Fine,
Thanks everyone for the hint.

Related

redirect_to inside controller action doesn't work

I use Rails 5.1 and the "redirect_to #search" inside create action doesn't work.
My SearchesController:
class SearchesController < ApplicationController
def new
#search = Search.new
end
def create
#search = Search.create!(search_params)
redirect_to #search # search_path(#search) doesn't work either
end
def show
#search = Search.find(params[:id])
end
private
def search_params
params.require(:search).permit!
end
end
After creating a new search entry by clicking the submit button it doesn't redirect to show page.
My app/views/searches/new.html.erb:
<div>
<h1>Advanced Search Form</h1>
<%= form_with model: #search do |form| %>
<%= form.text_field :keywords %>
<%= form.select :ort, options_from_collection_for_select(Imagecapturing.cities, :ort, :city_name, prompt: false, include_blank: false) %>
<%= form.submit("Suchen", :id=>"button", :class=>"Test", :name=>"submit") %>
<% end %>
</div>
config/routes.rb:
Rails.application.routes.draw do
root 'imagecapturings#index'
resources :searches
end
Log:
Started POST "/searches" for ::1 at 2018-06-14 17:37:54 +0200
Processing by SearchesController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"B91lIUxZZvanOx1luhhfWBJ9mAO5Np/6Bx4xzPdv2Ygj29bprWk5+wIBP7kMVl5Eoxz0KcyJF5DK8UaVUhQaFQ==", "search"=>{"keywords"=>"", "ort"=>"A-St. Paul"}, "submit"=>"Suchen"}
(0.6ms) BEGIN
SQL (22.8ms) INSERT INTO `searches` (`keywords`, `ort`, `created_at`, `updated_at`) VALUES ('', 'A-St. Paul', '2018-06-14 15:37:58', '2018-06-14 15:37:58')
(11.1ms) COMMIT
Redirected to http://localhost:4000/searches/23
Completed 302 Found in 50ms (ActiveRecord: 34.5ms)
Started GET "/searches/23" for ::1 at 2018-06-14 17:37:58 +0200
Processing by SearchesController#show as JS
Parameters: {"id"=>"23"}
Search Load (0.7ms) SELECT `searches`.* FROM `searches` WHERE `searches`.`id` = 23 LIMIT 1
Rendering searches/show.html.erb within layouts/application
Imagecapturing Load (10.4ms) SELECT `imagecapturing`.* FROM `imagecapturing` WHERE (ort LIKE '%A-St. Paul%') ORDER BY `imagecapturing`.`id` DESC
Rendered searches/show.html.erb within layouts/application (62.5ms)
Rendered layouts/_top_nav.html.erb (6.0ms)
Imagecapturing Load (17.0ms) SELECT distinct(ort) FROM `imagecapturing` ORDER BY `imagecapturing`.`ort` ASC
Rendered searches/_links.html.erb (33.5ms)
Completed 200 OK in 409ms (Views: 340.1ms | ActiveRecord: 28.0ms)
Is in "Processing by SearchesController#show as JS" the "as JS" part the issue?
How can I get the redirect working so that after clicking the submit button it redirects to the show action?
--- UPDATE
With suggestion of user Rockwell I modified the create action to:
def create
#search= Search.create!(search_params)
respond_to do |format|
if #search
format.html {redirect_to #search}
format.json { render :show, status: :created, location: #step }
format.js { redirect_to #search }
else
format.html { render :new }
format.json { render json: #search.errors, status: :unprocessable_entity }
format.js { render :new }
end
end
end
But it still processes "as JS":
Started POST "/searches" for ::1 at 2018-06-14 18:09:18 +0200
Processing by SearchesController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"D7l5ibv8hu08Z18VKqa0Y+iqGHfT+SIZTIoM8vHdcpArv8pBWszZ4Jldfcmc6LV/Wct0XaZGqnOBZXurVKaxDQ==", "search"=>{"keywords"=>"", "ort"=>"Cologny"}, "submit"=>"Suchen"}
(0.2ms) BEGIN
SQL (11.8ms) INSERT INTO `searches` (`keywords`, `ort`, `created_at`, `updated_at`) VALUES ('', 'Cologny', '2018-06-14 16:09:18', '2018-06-14 16:09:18')
(17.0ms) COMMIT
Redirected to http://localhost:4000/searches/30
Completed 302 Found in 36ms (ActiveRecord: 29.0ms)
Started GET "/searches/30" for ::1 at 2018-06-14 18:09:19 +0200
Processing by SearchesController#show as JS
Parameters: {"id"=>"30"}
Search Load (0.8ms) SELECT `searches`.* FROM `searches` WHERE `searches`.`id` = 30 LIMIT 1
Rendering searches/show.html.erb within layouts/application
Imagecapturing Load (28.1ms) SELECT `imagecapturing`.* FROM `imagecapturing` WHERE (ort LIKE '%Cologny%') ORDER BY `imagecapturing`.`id` DESC
Rendered searches/show.html.erb within layouts/application (16157.3ms)
Rendered layouts/_top_nav.html.erb (3.6ms)
Imagecapturing Load (27.6ms) SELECT distinct(ort) FROM `imagecapturing` ORDER BY `imagecapturing`.`ort` ASC
Rendered searches/_links.html.erb (39.2ms)
Completed 200 OK in 16404ms (Views: 16314.1ms | ActiveRecord: 56.5ms)
I believe that you are correct, the Processing by SearchesController#show as JS is what is causing your error. If you respond to the format it should solve your issue. I added HTML and JSON here but you wouldn't need to if you know you will never need that, just the js should be fine.
def create
#search = Search.new(search_params)
respond_to do |format|
if #search.save
format.html {redirect_to #search}
format.json { render :show, status: :created, location: #step }
format.js { redirect_to #search }
else
format.html { render :new }
format.json { render json: #search.errors, status: :unprocessable_entity }
format.js { render :new }
end
end
end
If you are sending this as an AJAX you could specify the type that gets sent as well, but I would need to see the JS code for that to give a solution to fix that.
it is working as expected, you can see it on the log, the insert is done and then the redirect too.
but the problem is the format you are asking. it seems like the create is called as js Processing by SearchesController#create as JS (maybe you are doing an ajax request with that format or your form has remote:true). and then the redirect isn't done visually of course. you need to make the create request without js format or don't make the redirect on the controller and create a "create.js" view that does the redirect. but of course it's not the best solution.
if you want to do the redirect, the best way is to change the format of the create request.

Date failing to update, but returning true for Update (Rails ActiveRecord)

I have a Rails model called user that has a birthday field with type date in Postgres.
My first issue is that I'm not sure how to update the value of a user. If I pass in a string like "10/10/1980", it does not update.
The second issue is that even when the birthday is not updated, Rails returns true for the User.update(user_params) action
My two questions:
How can I update a date field?
How can I make sure that rails throws an error if an incorrect date is passed in?
How can I update a date field?
Update method from controller below. Fairly standard from scaffolding.
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
respond_to do |format|
puts(user_params)
if #user.update(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
Edit: Params:
def user_params
params.require(:user)
.permit(:points, :payment_option, :first_name, :last_name,
:payment_email, :phone_number, :facebook_id, :profile_pic_url,
:locale, :timezone, :gender, :email, :country, :city,
:age_group, :birthday, :employment_status, :occupation,
:education_level, :income_bracket)
end
Rails log (note that I added a puts(user_params) after the update statement.
Started PATCH "/api/v1/users/1" for 127.0.0.1 at 2017-12-07 19:16:37 +0800
Processing by UsersController#update as JSON
Parameters: {"user"=>{"birthday"=>"12dsafkljfsldk"}, "id"=>"1"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Can't verify CSRF token authenticity.
{"birthday"=>"10/10/1900"}
(0.2ms) BEGIN
(0.1ms) COMMIT
Rendering users/show.json.jbuilder
Rendered users/_user.json.jbuilder (0.6ms)
Rendered users/show.json.jbuilder (1.6ms)
Completed 200 OK in 31ms (Views: 5.9ms | ActiveRecord: 3.1ms)
I was hoping that I could use before_update to parse the date string into a Date object before saving, but it doesn't look like self.birthday is even showing up in the model.
Place this line in your ApplicationController
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
If it doesn't work then. Try to skip the action
skip_before_action :verify_authenticity_token

ActionController::UnknownFormat in MeetingsController#update

I have read countless SO questions about this issue, and can not find a solution.
I have a button that updates Meeting here:
<%= form_for(meeting) do |f| %>
<%= f.hidden_field :accepted, value: true %>
<%= button_tag(type: 'submit', class: "btn_primary") do %>
Accept <svg><use xlink:href="#checkmark"/></svg>
<% end %>
<% end %>
I get an unknown format error, BUT it still updates. What is causing this error?
I have tried removing respond_to do |format| from the update method. which solves the problem for this one button, but then breaks all the other buttons on the platform that calls meetings/update.
class MeetingsController < ApplicationController
respond_to :json, :html
def update
respond_to do |format| **error highlights this line**
if #meeting.update(meeting_params)
format.json { render :show, status: :ok, location: #meeting }
else
format.html { render :edit }
format.json { render json: #meeting.errors, status: :unprocessable_entity }
end
end
end
end
Console:
Started PATCH "/meetings/224" for 127.0.0.1 at 2016-11-11 16:05:27 -0500
Processing by MeetingsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hK6AoOZuw9DWyKUXw1dXWOSUolooWgBUPnkItUJX5Tm7XvimsHd9518pkqwVvNhUi3L3vlA4OZaJZiAgrbS0Ig==", "meeting"=>{"accepted"=>"true"}, "button"=>"", "id"=>"224"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Meeting Load (0.2ms) SELECT "meetings".* FROM "meetings" WHERE "meetings"."id" = ? LIMIT 1 [["id", 224]]
(0.3ms) begin transaction
SQL (0.5ms) UPDATE "meetings" SET "accepted" = ?, "updated_at" = ? WHERE "meetings"."id" = ? [["accepted", "t"], ["updated_at", "2016-11-11 21:05:27.882521"], ["id", 224]]
(1.3ms) commit transaction
Completed 406 Not Acceptable in 24ms (ActiveRecord: 2.7ms)
ActionController::UnknownFormat (ActionController::UnknownFormat):
app/controllers/meetings_controller.rb:65:in `update'
This was never an issue, and seemingly came out of no where. What is the cause of this error? Thanks!
I think I know what the issue is. I've added a line to your update method
class MeetingsController < ApplicationController
respond_to :json, :html
def update
respond_to do |format| **error highlights this line**
if #meeting.update(meeting_params)
format.html { redirect_to some_rails_path }
format.json { render :show, status: :ok, location: #meeting }
else
format.html { render :edit }
format.json { render json: #meeting.errors, status: :unprocessable_entity }
end
end
end
end
The reason you're getting an unknown format error but still successfully updating meeting is because your method has solid logic, so it's updating the meeting, but then once it does that, and you're only telling it what to do in terms of JSON but not in terms of HTML, you address both in your else statement, but not if the update succeeds.
Is this supposed to be an ajax request? It doesn't seem to be. But you're rendering json instead of html. If you're going to allow the page to reload you need to add an html option to if #meeting.update(meeting_params)
Something like: format.html { redirect_to #meeting, notice: 'Meeting was successfully updated.' }
If you're doing an ajax request this isn't the correct answer, but I don't see any indication in your question that you are. Lmk if you need further clarification.

How to allow devise users to edit their profil?

I have a namespace called "backend" which is protected by Devise.
I would like now to allow users to edit their profil.
So I created a users_controller in Backend.
Here's the users_controllercode :
class Backend::UsersController < ApplicationController
layout 'admin'
before_filter :authenticate_user!
def index
#users = Backend::User.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #users }
end
end
def show
#user = Backend::User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #user }
end
end
def edit
#user = Backend::User.find(params[:id])
end
def update
#user = Backend::User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'Article was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
end
When I go on backend_users_path there is a list of all the users. I would like to permit to edit only his own profil.
So I go on the Edit page : <%= link_to "Edit", edit_backend_user_path(backend_user.id) %> .
Here's the Edit page code :
<%= simple_form_for #user do |f| %>
<div><%= f.label :email %><br />
<%= f.input :email, :autofocus => true %></div>
<div><%= f.submit "Update" %></div>
<% end %>
And there is my problem : when I try to modify the email address, nothing happen. The update fails.
How can I do this ?
I'm quite lost.
Thanks by advance.
Here's the log file :
Started PUT "/backend/users/1" for 127.0.0.1 at 2012-11-13 12:13:51 +0100
Processing by Backend::UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"wWrUDh7LVWhP+P7OWO6laDWaCKInxk37AA2BPuQWAI4=", "backend_user"=>{"email"=>"grellazzi#laposte.net"}, "commit"=>"Update", "id"=>"1"}
[1m[35mBackend::User Load (0.0ms)[0m SELECT `backend_users`.* FROM `backend_users` WHERE `backend_users`.`id` = 1 LIMIT 1
[1m[36mBackend::User Load (0.0ms)[0m [1mSELECT `backend_users`.* FROM `backend_users` WHERE `backend_users`.`id` = ? LIMIT 1[0m [["id", "1"]]
[1m[35mSQL (1.0ms)[0m BEGIN
[1m[36m (0.0ms)[0m [1mCOMMIT[0m
Redirected to http://localhost:3000/backend/users/1
Completed 302 Found in 23ms (ActiveRecord: 1.0ms)
Started GET "/backend/users/1" for 127.0.0.1 at 2012-11-13 12:13:51 +0100
Processing by Backend::UsersController#show as HTML
Parameters: {"id"=>"1"}
[1m[35mBackend::User Load (0.0ms)[0m SELECT `backend_users`.* FROM `backend_users` WHERE `backend_users`.`id` = 1 LIMIT 1
[1m[36mBackend::User Load (0.0ms)[0m [1mSELECT `backend_users`.* FROM `backend_users` WHERE `backend_users`.`id` = ? LIMIT 1[0m [["id", "1"]]
Rendered backend/users/show.html.erb within layouts/admin (0.0ms)
Completed 200 OK in 7ms (Views: 5.0ms | ActiveRecord: 0.0ms)
Thanks for your links, I tried to modify my user_controller with
if params[:user][:password].blank?
params[:user].delete("password")
params[:user].delete("password_confirmation")
end
#user = User.find(current_user.id)
if #user.update_attributes(params[:user])
# Sign in the user bypassing validation in case his password changed
sign_in #user, :bypass => true
redirect_to root_path
else
render "edit"
end
But it fails...
If nothing happens, that usually indicates a validation error, in your case probably a missing password or other data that is not part of your form but is still being validated. To debug this, output #user.errors.inspect to your logfile or look at error_messages_on #user in your view.
In general, take a look at these guides on how to allow users to edit their (partial) profile:
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-account-without-providing-a-password
https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-password

Virtual attribute to set published_at for a Post

I have a post model with a datetime field called "published_at". On my form I have a checkbox for an attribute named "publish_now" (see below). I want "published_at" to be set to the Time.now() when the user checks the checkbox for my virtual attribute :publish_now.
<input class="boolean optional" id="post_publish_now" name="post[publish_now]" type="checkbox" value="1" />
Here is my create and update methods in the controller:
def create
#post = Post.new(params[:post])
if current_user
#post.author_id == current_user.id
end
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render json: #post, status: :created, location: #post }
else
format.html { render action: "new" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
def update
#post = Post.find(params[:id])
respond_to do |format|
if #post.update_attributes(params[:post])
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
And here is my model:
class Post < ActiveRecord::Base
belongs_to :author, class_name: "User", foreign_key: "author_id"
attr_accessible :author_id, :content, :published_at, :title, :publish_now
validates_presence_of :content, :title
def publish_now
!published_at.nil?
end
def publish_now=(value)
if value == "1" && published_at.nil?
published_at = Time.now()
end
end
end
This is my best guess of how it should work based on the railscast on virtual attributes, but it's not saving a value for published_at. Any suggestions where the problem might be?
UPDATE: (the form view)
<%= simple_form_for(#post) do |f| %>
<%= f.input :title %>
<%= f.input :content, input_html: { cols: 100, rows: 10, class: "
span5" } %>
<% if #post.published_now == false %>
<%= f.input :publish_now, as: :boolean %>
<% end %>
<%= f.submit %>
<% end %>
UPDATE Example Log:
Started POST "/posts" for 127.0.0.1 at 2012-10-31 14:14:49 -0500
Processing by PostsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"zlZ3s18VXwEvONIkk1CZAYESAEAxPP1OKcUtiyEuZgA=", "post"=>{"title"=>"big big love a doodle", "content"=>"aksdfj;skjf;kasjdf; lkj af;lk ;askdfj ;lk ;laf; ksd ;f", "publish_now"=>"1"}, "commit"=>"Create Post"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
(0.2ms) BEGIN
SQL (0.7ms) INSERT INTO "posts" ("author_id", "content", "created_at", "published_at", "title", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["author_id", nil], ["content", "aksdfj;skjf;kasjdf; lkj af;lk ;askdfj ;lk ;laf; ksd ;f"], ["created_at", Wed, 31 Oct 2012 14:14:49 CDT -05:00], ["published_at", nil], ["title", "big big love a doodle"], ["updated_at", Wed, 31 Oct 2012 14:14:49 CDT -05:00]]
(0.4ms) COMMIT
Redirected to http://localhost:3000/posts/5
Completed 302 Found in 18ms (ActiveRecord: 2.1ms)
The error is in this line
published_at = Time.now()
It should be
self.published_at = Time.now()
The parenthesis are also optional.
If you assign to something then Ruby will assume it's a local variable unless you explicitly provide the object, only then can Ruby know it's actually a method you want to call (published_at= method). This is a common gotcha moment in Ruby.
What happens in your code is that a new local variable published_at is created. See http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html at "Using Accessors Within a Class" for more information.
When reading attributes like that you don't need to prefix by self, however, because Ruby will not assume something is a local variable until you assign it. So before published_at=..., Ruby will treat published_at as a method call, after you do published_at=... (without self in front), it will treat published_at as a local variable. Only then you would have to use self.published_at to actually call the method instead of reading the local variable. For the attribute writter (ends with =), you always need to prefix with the object. You can alternatively use the attributes hash, that way you don't need to prefix by self:
attributes["published_at"] = whatever

Resources