serialize a column and save - ruby-on-rails

I'm using rails 4.2 with ruby 2.2.
I'm trying to save some data inside a column in a hash format.
I'm trying to save license details in the license column which is of text datatype, and in the respective model i've given:
serialize :license, JSON
I have this in the controller:
params.require(:company_detail).permit(:company_name, :trading_name, :contact_name, :acn, :address, :suburb, :state, :post_code, :phone_number, :fax_number, :nrma_approved, :start_date, :release_date , :website_url ,:email, license: {date1: :date1, license1: :license1, date2: :date2, license2: :license2, date3: :date3, license3: :license3, date4: :date4, license4: :license4})
and in form
= form_for #company_detail, remote: true, html: {class: 'form-horizontal form-label-left', data: {"parsley-validate" => ""}} do |f|
= f.fields_for :license do |l|
.row
.col-lg-6
.form-group
%label.control-label.col-md-4.col-xs-12 Date 1
.col-md-8.col-xs-12
= l.text_field :date1, value: #company_detail.license.present? ? #company_detail.license["date1"] : '', class: 'date-picker form-control has-feedback-left datePicker'
.col-lg-6
.form-group
%label.control-label.col-md-4.col-xs-12 Licence Number 1
.col-md-8.col-xs-12
= l.text_field :license1, value: #company_detail.license.present? ? #company_detail.license["license1"] : '', class: 'form-control'
I tried entering a few fields in the form and submit, but even though the params are going in correctly, the value saved is null. This is the log:
Parameters: {"utf8"=>"✓", "company_detail"=>{"license"=>{"date1"=>"121212", "license1"=>"12313", "date2"=>"122131123", "license2"=>"123123", "date3"=>"", "license3"=>"", "date4"=>"", "license4"=>""}}, "commit"=>"Save", "id"=>"1"}
CompanyDetail Load (0.3ms) SELECT "company_details".* FROM "company_details" WHERE "company_details"."id" = $1 LIMIT 1 [["id", 1]]
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
(1.0ms) BEGIN
SQL (0.4ms) UPDATE "company_details" SET "license" = $1, "updated_at" = $2 WHERE "company_details"."id" = $3 [["license", "{\"date1\":null,\"license1\":null,\"date2\":null,\"license2\":null,\"date3\":null,\"license3\":null,\"date4\":null,\"license4\":null}"], ["updated_at", "2016-05-01 12:15:44.918547"], ["id", 1]]

Try this for your strong parameters for licence:
license: [:date1, :license1, :date2, :license2, :date3, :license3, :date4, :license4]

If you are using postgres as your db, then you can use json as the datatype for your column.
See here - ActiveRecord JSON
If you are looking into querying your json fields, you should use the jsonb field. Reference
But please note jsonb datatype was only introduced in postgresql v9.4

Related

Confirm Rails Devise user with checkbox

While administering users, I'd like the administrator to be able to confirm a user's account using a checkbox to trigger the user's devise user.confirm method.
I initially thought I'd be able to use attr_accessor to setup a variable called confirm_now to be used as a boolean on the user form, then in the controller update action (or by before/after action callback) evaluate the boolean and confirm the user accordingly.
I'm still not quite sure if I need methods in the model to set and read the attr_accessor variable, I'm still getting my head around that...or perhaps I'm over-complicating this and should call the user.confirm method when clicking save (is this bad practice? - I'm hesitant to add this field into the user_params).
Model:
class User < ApplicationRecord
attr_accessor :confirm_now
...
Controller:
class UsersController < ApplicationController
...
def update
if params[:user][:password].blank?
params[:user].delete(:password)
params[:user].delete(:password_confirmation)
end
if !#user.confirmed? && #user.confirm_now
#user.confirm
end
...
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :account_active, :confirm_now)
end
Form snippet (this evaluates and works as expected):
<% if !#user.confirmed? %>
<%= f.input :confirm_now, label: 'Confirm User', as: :boolean, checked_value: true, unchecked_value: false %>
<% end %>
Rails Log (the attr_accessor is set when checked on the form):
Processing by UsersController#update as HTML
Parameters: {"authenticity_token"=>"...", "user"=>{"first_name"=>"gg", "last_name"=>"gg", "email"=>"gg#gg.com", "account_active"=>"1", "confirm_now"=>"true", "password"=>"[FILTERED]"}, "commit"=>"Save", "id"=>"45"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."first_name" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."first_name" ASC LIMIT $2 [["id", 45], ["LIMIT", 1]]
CACHE User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."first_name" ASC LIMIT $2 [["id", 45], ["LIMIT", 1]]
Redirected to http://localhost:3000/users
Completed 302 Found in 6ms (ActiveRecord: 0.6ms | Allocations: 2665)
Thanks in advance!
To simplify I would make it a button, and pass the confirmed_at field directly.
Parameter whitelisting:
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password, :account_active, :confirmed_at)
end
Form:
<%=
if #user.confirmed?
link_to 'Unconfirm user',
user_path(#user, { user: { confirmed_at: nil } }),
method: :patch
else
link_to 'Confirm user',
user_path(#user, { user: { confirmed_at: Time.current } }),
method: :patch
end
%>
Please adjust the paths/method types according to your routes.

Why i can't create object with params?

I’ve been suffering from a problem for several days.
I can not create an object using the parameters from the form.
My form:
<%= form_with(model: #battle, local: true) do |form| %>
<div class="field">
<%= form.collection_select(:team_id, #teams, :id, :name) %>
</div>
<%= form.submit 'Submit'%>
<% end %>
In this form i want to choose only 1 team.
controller:
def create
#battle = Battle.new
#battle.user_id = current_user.id
#battle.team_ids = params[:team_id]
if #battle.save
redirect_to root_path, notice: "Battle has been created"
else
render :new
end
end
def battle_params
params.require(:battle).permit(:team_id)
end
And when used, this form creates an object without reference to the team.
logs:
Processing by BattlesController#create as HTML
Parameters: {"authenticity_token"=>"0wWoFrQXYkEsXsMRgGyKi5Mde7WndhI6zYWY4KvhQlgdcCAaCZqH1z1z9dK0x91iqOPw/Jsb2T6Q+EVtGz4VsA==", "battle"=>{"team_id"=>"14"}, "commit"=>"Submit"}
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/battles_controller.rb:14:in `create'
Team Load (0.4ms) SELECT "teams".* FROM "teams" WHERE 1=0
↳ app/controllers/battles_controller.rb:15:in `create'
(0.4ms) BEGIN
↳ app/controllers/battles_controller.rb:16:in `create'
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
↳ app/controllers/battles_controller.rb:16:in `create'
Battle Create (3.8ms) INSERT INTO "battles" ("user_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["user_id", 1], ["created_at", "2020-06-19 10:28:28.036147"], ["updated_at", "2020-06-19 10:28:28.036147"]]
If I try to create a battle with two teams, but it will be created with only one (without using parameters):
#battle.team_ids = [params[:team_id], 14]
Although, a battle is created without problems in the console:
battle = Battle.new
battle.team_ids = [13, 14]
I don’t understand what the problem may be.
Instead of params[:team_id] try using battle_params[:team_id] instead:
#battle.team_ids = battle_params[:team_id]
otherwise you'd need to call params[:battle][:team_id] which is not the Rails way as it isn't as secure, but it would still work.

RoR - ActiveAdmin Impossible to create a new product with nested form

I am new to rails and I'm trying to customize ActiveAdmin.
My app has 3 models: User (which has many products), Product (which has many prices) and Price. I am trying to customize ActiveAdmin with a nested form to be able to create/update a product directly with its prices.
Although the update works perfectly (updating product and even adding a new price), the create action doesn't work. I get "rollback" in the console but no specific error message.
Can you tell me what I'm doing wrong?
# app/admin/products.rb
ActiveAdmin.register Product do
form do |f|
f.semantic_errors
f.inputs do
f.input :name
f.input :size
end
f.inputs "Prices" do
f.has_many :prices do |price|
price.input :value
price.input :currency, :collection => ["dollars", "euros", "pounds"]
end
end
f.actions
end
permit_params :name, :size, :user_id, prices_attributes: [:id, :currency, :value, :product_id, :_edit, :_update, :_new, :_create]
I have also put "accepts_nested_attributes_for :prices" in app/models/product.rb.
The logs form the console
Started POST "/admin/products" for 127.0.0.1 at 2018-03-28 14:46:05 +0200
Processing by Admin::ProductsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"W9OJHqyFzXREfi4/DuBN1xnf0KIhAjJDfGsZjQqvGJ7BZOb11fVAz78djOf1k3XZdmpJxuPYinYi6Knu2agvnQ==", "product"=>{"name"=>"Shorts", "size"=>"XL", "prices_attributes"=>{"0"=>{"value"=>"40", "currency"=>"euros"}}}, "commit"=>"Create Product"}
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
AdminUser Load (0.4ms) SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = $1 ORDER BY "admin_users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.2ms) BEGIN
(0.3ms) ROLLBACK
Rendering /Users/alex/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/activeadmin-1.2.1/app/views/active_admin/resource/new.html.arb
Rendered /Users/alex/.rbenv/versions/2.4.3/lib/ruby/gems/2.4.0/gems/activeadmin-1.2.1/app/views/active_admin/resource/new.html.arb (100.1ms)
Completed 200 OK in 248ms (Views: 132.6ms | ActiveRecord: 1.9ms)
Thank you very much for you help.

rails_5 select and options_from_collections_for_select

I am working in rails 5.
I am working with a database named "meals". Data base "meals" belongs to a database "events". I have the form_for with meals.
<%= form_for(meal) do |f| %>
I want to a create a drop down with information from database "Events" and then use that as an id for "meals". The dropdown is populated with "events" but i cannot get the event to be selected when I submit the form.
I am using the "select" combined with "options_from_collection_for_select".
</div>
<%= f.select :event_id, options_from_collection_for_select((events), "id", "name", "events.id" ), prompt: 'select' %>
</div>
Parameters: {"utf8"=>"✓", "authenticity_token"=>"9RIvNLt92mYqM5P8m6l3t+vFiNwt/ISzr06pD+0xYlPR+eQR9E9FdsehIn TVwl6U/3q0UHCUw3epaUNuwMvfOw==", "meal"=>{"meal_name"=>"meal", "desc"=>"", "meal_type"=>"", "event_id"=>""}, "commit"=>"Create Meal"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 3], ["LIMIT", 1]]
(0.1ms) begin transaction
(0.1ms) rollback transaction
Thank you!

Rails nested attributes not being updated

I'm building my first Rails app and one of the important features in it is having users who speak and/or want to learn languages. In the user edit profile page, I allow him/her to choose what languages he/she speaks and/or wants to learn from a list (I'm using ryanb's nested_form gem):
There are 3 models involved in this: User, Speaks, Language
The languages table is just a table with languages of the world, it doesn't change. It consists basically of ISO codes for languages and their names. I populate it by running a script that reads from the official file I downloaded. Still I was simply using Rails defaults, so the table had an id column, and it was all working fine.
Then I decided to make a change and remove the id column, because it didn't make any sense anyway. I want my app to be up to date with the ISO list. I want the ISO code to identify the languages, not a meaningless id. I want to use
user.speaks.create!(language_id: "pt", level: 6)
instead of
user.speaks.create!(language_id: 129, level: 6)
I know it's unlikely that the ISO list will change but, if it does, I want to simply run my script again with the new file and not worry if the id column will still match the same ISO code as before. So I made the change. Now I can use user.speaks.create the way I want and the association works perfectly in the console. The problem is my form simply isn't working anymore. The data is sent but I don't understand the logs. They show a bunch of SELECTS but no INSERTS or UPDATES, I don't get why. Does anybody have any idea?
Here are my models:
class User < ActiveRecord::Base
attr_accessible ..., :speaks, :speaks_attributes, :wants_to_learn_attributes
has_many :speaks, :class_name => "Speaks", :dependent => :destroy
has_many :speaks_languages, :through => :speaks, :source => :language #, :primary_key => "iso_639_1_code"
has_many :wants_to_learn, :class_name => "WantsToLearn", :dependent => :destroy
has_many :wants_to_learn_languages, :through => :wants_to_learn, :source => :language #, :primary_key => "iso_639_1_code"
...
accepts_nested_attributes_for :speaks #, :reject_if => :speaks_duplicate, :allow_destroy => true
accepts_nested_attributes_for :wants_to_learn #, :reject_if => :wants_to_learn_duplicate, :allow_destroy => true
# EDIT 1: I remembered these pieces of code silenced errors, so I commented them out
...
end
class Speaks < ActiveRecord::Base
self.table_name = "speak"
attr_accessible :language, :language_id, :level
belongs_to :user
belongs_to :language
validates :user, :language, :level, presence: true
...
end
#EDIT 4:
class WantsToLearn < ActiveRecord::Base
self.table_name = "want_to_learn"
attr_accessible :language, :language_id
belongs_to :user
belongs_to :language
validates :user, :language, presence: true
...
end
class Language < ActiveRecord::Base
attr_accessible :iso_639_1_code, :name_en, :name_fr, :name_pt
has_many :speak, :class_name => "Speaks"
has_many :users_who_speak, :through => :speak, :source => :user
has_many :want_to_learn, :class_name => "WantsToLearn"
has_many :users_who_want_to_learn, :through => :want_to_learn, :source => :user
end
Controller:
def update
logger.debug params
if #user.update_attributes(params[:user])
#user.save
flash[:success] = "Profile updated"
sign_in #user
redirect_to :action => :edit
else
render :action => :edit
end
end
View:
<%= nested_form_for(#user, :html => { :class => "edit-profile-form"} ) do |f| %>
<%= render 'shared/error_messages' %>
<table border="0">
<tr><td colspan="2"><h2 id="languages" class="bblabla">Languages</h2></td></tr>
<tr>
<td><span>Languages you speak</span></td>
<td class="languages-cell">
<div id="speaks">
<%= f.fields_for :speaks, :wrapper => false do |speaks| %>
<div class="fields">
<%= speaks.select(:language_id,
Language.all.collect {|lang| [lang.name_en, lang.id]},
{ :selected => speaks.object.language_id, :include_blank => false },
:class => 'language') %>
<%= speaks.label :level, "Level: " %>
<%= speaks.select(:level, Speaks.level_options, { :selected => speaks.object.level }, :class => 'level') %>
<%= speaks.link_to_remove raw("<i class='icon-remove icon-2x'></i>"), :class => "remove-language" %>
</div>
<% end %>
</div>
<p class="add-language"><%= f.link_to_add "Add language", :speaks, :data => { :target => "#speaks" } %></p>
</td>
</tr>
...
Log:
Started PUT "/users/1" for 127.0.0.1 at 2013-07-19 08:41:16 -0300
Processing by UsersController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"ZmaU9...", "user"=>{"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374234067848"=>{"language_id"=>"en", "level"=>"5", "_destroy"=>"false"}}, "wants_to_learn_attributes"=>{"0"=>{"language_id"=>"ro", "_destroy"=>"false", "id"=>"1"}}, "home_location_attributes"=>{"google_id"=>"7789d9...", "latitude"=>"-22.9035393", "longitude"=>"-43.20958689999998", "city"=>"Rio de Janeiro", "neighborhood"=>"", "administrative_area_level_1"=>"Rio de Janeiro", "administrative_area_level_2"=>"", "country_id"=>"BR", "id"=>"1"}, "gender"=>"2", "relationship_status"=>"2", "about_me"=>""}, "commit"=>"Save changes", "id"=>"1"}
[1m[35mUser Load (0.3ms)[0m SELECT "users".* FROM "users" WHERE "users"."remember_token" = 'bjdvI...' LIMIT 1
[1m[36mUser Load (0.2ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1[0m [["id", "1"]]
{"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"ZmaU9W...", "user"=>{"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374234067848"=>{"language_id"=>"en", "level"=>"5", "_destroy"=>"false"}}, "wants_to_learn_attributes"=>{"0"=>{"language_id"=>"ro", "_destroy"=>"false", "id"=>"1"}}, "home_location_attributes"=>{"google_id"=>"7789d9...", "latitude"=>"-22.9035393", "longitude"=>"-43.20958689999998", "city"=>"Rio de Janeiro", "neighborhood"=>"", "administrative_area_level_1"=>"Rio de Janeiro", "administrative_area_level_2"=>"", "country_id"=>"BR", "id"=>"1"}, "gender"=>"2", "relationship_status"=>"2", "about_me"=>""}, "commit"=>"Save changes", "action"=>"update", "controller"=>"users", "id"=>"1"}
[1m[35m (0.1ms)[0m BEGIN
[1m[36mWantsToLearn Load (0.2ms)[0m [1mSELECT "want_to_learn".* FROM "want_to_learn" WHERE "want_to_learn"."user_id" = 1 AND "want_to_learn"."id" IN (1)[0m
[1m[35mLocation Load (0.3ms)[0m SELECT "locations".* FROM "locations" WHERE "locations"."google_id" = '7789d...' AND "locations"."latitude" = '-22.9035393' AND "locations"."longitude" = '-43.20958689999998' AND "locations"."city" = 'Rio de Janeiro' AND "locations"."neighborhood" = '' AND "locations"."administrative_area_level_1" = 'Rio de Janeiro' AND "locations"."administrative_area_level_2" = '' AND "locations"."country_id" = 'BR' LIMIT 1
[1m[36mUser Exists (40.0ms)[0m [1mSELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('ariel#pontes.com') AND "users"."id" != 1) LIMIT 1[0m
[1m[35m (96.7ms)[0m UPDATE "users" SET "remember_token" = 'd0pb...', "updated_at" = '2013-07-19 11:41:16.808422' WHERE "users"."id" = 1
[1m[36m (28.7ms)[0m [1mCOMMIT[0m
[1m[35m (0.1ms)[0m BEGIN
[1m[36mUser Exists (0.3ms)[0m [1mSELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('ariel#pontes.com') AND "users"."id" != 1) LIMIT 1[0m
[1m[35m (0.3ms)[0m UPDATE "users" SET "remember_token" = 'gKlW...', "updated_at" = '2013-07-19 11:41:17.072654' WHERE "users"."id" = 1
[1m[36m (0.4ms)[0m [1mCOMMIT[0m
Rendered shared/_error_messages.html.erb (0.0ms)
[1m[35mSpeaks Load (0.3ms)[0m SELECT "speak".* FROM "speak" WHERE "speak"."user_id" = 1
[1m[36mWantsToLearn Load (0.2ms)[0m [1mSELECT "want_to_learn".* FROM "want_to_learn" WHERE "want_to_learn"."user_id" = 1[0m
[1m[35mLanguage Load (0.3ms)[0m SELECT "languages".* FROM "languages"
[1m[36mCountry Load (0.3ms)[0m [1mSELECT "countries".* FROM "countries" WHERE "countries"."iso_3166_code" = 'BR' LIMIT 1[0m
[1m[35mCACHE (0.0ms)[0m SELECT "languages".* FROM "languages"
[1m[36mCACHE (0.0ms)[0m [1mSELECT "languages".* FROM "languages" [0m
Rendered users/edit.html.erb within layouts/application (39.8ms)
Rendered layouts/_shim.html.erb (0.0ms)
Rendered layouts/_header.html.erb (1.1ms)
Rendered layouts/_footer.html.erb (0.2ms)
Completed 200 OK in 576ms (Views: 160.7ms | ActiveRecord: 168.7ms)
Hope someone has an insight cause I've been looking all over the internet for the past 2 days with no luck. Thanks in advance!
EDIT 1
I placed the accepts_nested_attributes_for lines after the associations were made, as suggested by ovatsug25, but it didn't seem to make any change. I remembered, however, that there were some options in the User model that silenced errors, which of course hinders the debugging, so I commented these options out. Now I have the following error:
PG::Error: ERROR: operator does not exist: character varying = integer
LINE 1: ...M "languages" WHERE "languages"."iso_639_1_code" = 0 LIMIT ...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT "languages".* FROM "languages" WHERE "languages"."iso_639_1_code" = 0 LIMIT 1
I have NO IDEA why Rails is trying to select a language with pk = 0. Even if the pk WAS an integer this wouldn't make sense (would it???) since the default id starts from 1. And even if it started from zero, why would it be trying to select it anyway? Where is this zero comming from?? And I can't "add explicit type casts". The pk is a string and will never be 0 or '0' for that matter. This query doesn't make sense and simply isn't supposed to happen!
EDIT 2
I tried to update the attributes in the console and got the following:
irb(main):006:0> ariel = User.find(1)
User Load (101.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 1]]
=> #<User id: 1, first_name: "Ariel", last_name: "Pontes", ...>
irb(main):007:0> params = {"user"=>{"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374444891951"=>{"language_id"=>"en", "l
evel"=>"5", "_destroy"=>"false"}}, "wants_to_learn_attributes"=>{"0"=>{"language_id"=>"ro", "_destroy"=>"false"}}, "home_location_attributes"=>{"google_id"=>"778...c5a", "latitude"=>"-22.9035393", "longitude"=>"-43.20958689999998", "city"=>"Rio de Janeiro", "neighborhood"=>"", "administrative
_area_level_1"=>"Rio de Janeiro", "administrative_area_level_2"=>"", "country_id"=>"BR", "id"=>"1"}, "gender"=>"2", "relationship_status"=>"2", "about_me"=>""}}
=> {"user"=>{"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374444891951"=>{"language_id"=>"en", "level"=>"5", "_destroy"=
>"false"}}, "wants_to_learn_attributes"=>{"0"=>{"language_id"=>"ro", "_destroy"=>"false"}}, "home_location_attributes"=>{"google_id"=>"778...c5a", "latitude"=>"-22.9035393", "longitude"=>"-43.20958689999998", "city"=>"Rio de Janeiro", "neighborhood"=>"", "administrative_area_level_1"=>"Rio de
Janeiro", "administrative_area_level_2"=>"", "country_id"=>"BR", "id"=>"1"}, "gender"=>"2", "relationship_status"=>"2", "about_me"=>""}}
irb(main):008:0> ariel.update_attributes(params[:user])
(0.1ms) BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('ariel#pontes.com') AND "users"."id" != 1) LIMIT 1
(24.9ms) UPDATE "users" SET "remember_token" = '0tv...Cw', "updated_at" = '2013-07-22 15:45:30.705217' WHERE "users"."id" = 1
(54.3ms) COMMIT
=> true
irb(main):009:0>
Basically, it only updates the remember_token and updated_at for some reason.
EDIT 3
I tried to update only the spoken languages and it worked:
irb(main):012:0> ariel.update_attributes({"speaks_attributes"=>{"0"=>{"language_id"=>"pt", "level"=>"6", "_destroy"=>"false"}, "1374444891951"=>{"language_id"=>"e
n", "level"=>"5", "_destroy"=>"false"}}})
(0.2ms) BEGIN
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Language Load (0.8ms) SELECT "languages".* FROM "languages" WHERE "languages"."iso_639_1_code" = 'pt' LIMIT 1
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Language Load (0.2ms) SELECT "languages".* FROM "languages" WHERE "languages"."iso_639_1_code" = 'en' LIMIT 1
User Exists (0.2ms) SELECT 1 AS one FROM "users" WHERE (LOWER("users"."email") = LOWER('ariel#pontes.com') AND "users"."id" != 1) LIMIT 1
(0.2ms) UPDATE "users" SET "remember_token" = 'MYh5X1XoF6OsVIo3rhDNzQ', "updated_at" = '2013-07-22 22:05:08.198025' WHERE "users"."id" = 1
SQL (42.9ms) INSERT INTO "speak" ("created_at", "language_id", "level", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Mo
n, 22 Jul 2013 22:05:08 UTC +00:00], ["language_id", "pt"], ["level", 6], ["updated_at", Mon, 22 Jul 2013 22:05:08 UTC +00:00], ["user_id", 1]]
SQL (0.4ms) INSERT INTO "speak" ("created_at", "language_id", "level", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Mon
, 22 Jul 2013 22:05:08 UTC +00:00], ["language_id", "en"], ["level", 5], ["updated_at", Mon, 22 Jul 2013 22:05:08 UTC +00:00], ["user_id", 1]]
(14.7ms) COMMIT
=> true
I'm starting to fear it may be a case of witchcraft.
PS: Does anybody know why it loads the User 3 times? Seems rather pointless and wasteful.
The biggest clue is this error that caught your eye:
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT "languages".* FROM "languages" WHERE "languages"."iso_639_1_code" = 0 LIMIT 1
If you're providing a string value for a model attribute, but the underlying database column is a numeric column, Rails will try to convert the string value to the appropriate numeric type. So, if the underlying column is of type integer, the string input will be interpreted as an integer, using String#to_i. If the string doesn't start with a number, it will be converted to 0.
The Rails console (rails c) can be a useful tool for debugging issues like this. In this case, on the console, you can run WantsToLearn.columns_hash['language_id'].type to see what type Rails thinks it should be using for that attribute. Of course, you can also just as easily check the migrations.
I used to have a problem like this and solved it by segreating the accepts_attributes_for calls to the very bottom after all associations and accessible attributes have been declared. (I also merged attr_accesible into one call. I think ryanb says something in this video about the order of the calls. http://railscasts.com/episodes/196-nested-model-form-revised?view=asciicast.
Makes sense? No. But it worked for me.

Resources