Create a model attribute from checkbox input - ruby-on-rails

This creates and saves a new row to my database. The problem is that I have a checkbox in my view file for a boolean value, but no matter whether the box is checked or not, the new row is always false. I also can't get any of the other attributes to show up as anything other than nil. Any ideas?
This is my view is:
<%= form_for(#setting) do |s| %>
<div class="field" >
<%= s.label :my_setting_attribute %>
<%= s.check_box(:my_setting_attribute) %>
</div>
<div class="actions">
<%= s.submit "Submit" %>
</div>
<% end %>
And my controller:
def new
#setting = Setting.new
end
def create
#setting = Setting.new(params[:setting])
if #setting.save
redirect_to :action => 'index', :id => #setting.id
else
redirect_to :action => 'error'
end
end
I think I have my route file set correctly:
resources :settings do
collection do
get :index
post 'settings/new'
get 'settings/show'
end
end
Here's the development log excerpt:
Started POST "/settings" for 10.7.94.191 at 2011-07-25 20:30:11 -0400
Processing by SettingsController#create as HTML
Parameters: {"utf8"=>"â", "authenticity_token"=>"xxxxxxxxxxx=", "setting"=>{"my_setting_attribute"=>"1", "other_setting_attribute"=>"hello"}, "commit"=>"Submit"}
ESC[1mESC[36mUser Load (0.1ms)ESC[0m ESC[1mSELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1ESC[0m
ESC[1mESC[35mSQL (0.1ms)ESC[0m BEGIN
ESC[1mESC[36mSQL (1.0ms)ESC[0m ESC[1mdescribe `settings`ESC[0m
ESC[1mESC[35mAREL (0.3ms)ESC[0m INSERT INTO `settings` (`facebook_token`, `twitter`, `user_id`, `created_at`, `updated_at`, `image_id`) VALUES (NULL, NULL, NULL, '2011-07-26 00:30:12', '2011-07-26 00:30:12', NULL)
ESC[1mESC[36mSQL (57.1ms)ESC[0m ESC[1mCOMMITESC[0m
Redirected to http://3000/settings?id=12

May not be the "correct" way of doing it but you could probably do this:
In your controller for the update and create method, check what the value of params[:my_setting_attribute] is. You may need to conditionally set the attribute to either "true" or "false".
e.g. perhaps it is returning "1" instead of true (which your log seems to indicuate), then you can set it yourself with something like #my_object.my_setting_attribute = true if params[:my_setting_attribute] == "1". Then probably add an else clause to set everything else to false, just to be safe.

Related

rails form with validation always failing

I'm stuck on this... Asked a few questions already, but can't get my head around this.
I have a form for adding bibliography (model Biblio) that has a simple validation field on title of the bibliography.
Validation always fails, even when valid data is added.
MODEL
class Biblio < ApplicationRecord
# validates_presence_of :auteurs => there's a nested form too but
# I commented it out in order to isolate the problem
accepts_nested_attributes_for :auteurs
validates :titre, presence: true
CONTROLLER
(full text and I didn't translate in order to avoid typos)
def new
#biblio = Biblio.new(params_biblio)
#biblio.auteurs.build
end
def nouveau
# this method renders 'nouveau.html.erb',
# that contains the form allowing the addition of bibliography
#biblio = Biblio.new
if params[:id] # id is an optional parameter
#auteur = Auteur.find(params[:id])
#idauteur = #auteur.id
end
end
def ajouter
# is the method that treats the post form that was sent
#biblio = Biblio.new
if #biblio.save
# the 4 following lines are irrelevant here as they only add the
# second and subsequent authors to the join table.
# No validation and works fine.
b = auteurs_devises(params[:biblio][:auteurs])
aut = b.map do |var|
lett = Auteur.find(var)
lett.biblios << #biblio
end
redirect_to voir_biblio_url(Biblio.last)
else
if params[:id]
#auteur = Auteur.find(params[:id])
#idauteur = #auteur.id
end
render 'nouveau'
end
end
THE VIEW:
<%= form_for :biblio, url: administration_ajoute_biblio_url do |f| %>
<%= f.fields_for :auteurs do |aut| %>
<%= aut.label t('auteur') %>
<%= aut.text_field :nom , :name =>"biblio[auteurs][nom]", data: {autocomplete_source: auteurs_enum_path} %>
<% end %>
<%= f.label t('titre').capitalize %>
<%= f.text_field :titre %>
These are the params that are sent to the method nouveau:
Started POST "/administration/biblios/nouveau" for ::1 at 2017-02-07 21:28:28 +0100
Processing by Administration::BibliosController#ajouter as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"+354h4M0Tg+BX21XAuQ6YMKS0BGQ8UjET8paKjkGCBsS1up1lB131KsoaCy563X4juDz0EJy46WgXbHcu51Kgw==", "biblio"=>{"auteurs"=>{"nom"=>"Godding"}, "titre"=>"Test Tuesday Evening", "soustitre"=>"", "recueil"=>"", "editeur"=>"", "annee"=>"", "isbn"=>"", "genre"=>"source", "revue_id"=>"", "revue_no"=>"", "revue_page"=>"", "lieu"=>"", "commentaire"=>""}, "commit"=>"Enregistrer"}
(0.2ms) BEGIN
(0.1ms) ROLLBACK
Rendering administration/biblios/nouveau.html.erb within layouts/messources
CONTROLLER AGAIN
def params_biblio
params.require(:biblio).permit(
:titre,
:soustitre,
:editeur,
:isbn,
:recueil,
:genre,
:revue_id,
:revue_no,
:revue_page,
:annee,
:lieu,
:commentaire,
auteurs: [:nom] )
end
For the sake of completeness, here's my routes.rb:
# ADMINISTRATION => BIBLIOGRAPHIE
get 'biblios/nouveau(/:id)' => 'biblios#nouveau', as: 'nouvelle_biblio'
post 'biblios/nouveau(/:id)' => 'biblios#ajouter', as: 'ajoute_biblio'
delete 'biblios/supprime/:id' => 'biblios#supprime', as: 'supprime_biblio'
get 'biblios/maj/:id' => 'biblios#cherche_maj', as: 'maj_biblio'
patch 'biblios/maj/:id' => 'biblios#maj', as: 'patch_maj_biblio'
I must be blind. I'm doing something wrong... I put a title to this bibliography ('Test Tuesday Evening'), this is the only field on which I left a validation, and despite this, validation always fails.

Pundit raising AuthorizationNotPerformedError on a loop where authorize object is called

I have two rails app :
one is a "front-end app" responsible for displaying data, taking input from the user and sending data to the API (the second app). The second is an API dealing with database operations and sending JSON to the front end app.
I have an action where my user decides how many roomshe wants to create in his hotel and how many bedsshould he create in each room. The form on the front end app looks like that :
<h1>Add Rooms</h1>
<form action="http://localhost:3000/hotels/<%=params[:hotel_id]%>/rooms/multiple_create" method="post">
<input name="authenticity_token" value="<%= form_authenticity_token %>" type="hidden">
<div class="form-group">
<%= label_tag 'room[room_number]', "Number of rooms" %>
<input type="number" name="room[room_number]" required>
</div>
<div class="form-group">
<%= label_tag "room[bed_number]", "Number of beds by room" %>
<input type="number" name= "room[bed_number]" required>
</div>
<div class="form-group">
<%= label_tag "room[content]", "Room Type" %>
<input type="text" name= "room[content]" required>
</div>
<input type="submit">
<% if #errors %>
<ul class="list-unstyled">
<%#errors.each do |error|%>
<li class="has-error"><%=error%></li>
<% end -%>
</ul>
<% end -%>
</form>
This form is linked to my RoomsController#multiple_create action on the front-end app that is responsible for sending the form data to the API :
class RoomsController < ApplicationController
def multiple_new
end
def multiple_create
#response = HTTParty.post(ENV['API_ADDRESS']+'api/v1/hotels/'+ params[:hotel_id]+'/rooms/multiple_create',
:body => { :room =>{
:room_number => params[:room][:room_number],
:bed_number => params[:room][:bed_number],
}
}.to_json,
:headers => { 'X-User-Email' => session[:user_email], 'X-User-Token'=> session[:user_token], 'Content-Type' => 'application/json' } )
# Erreur Mauvais Auth Token
if #response["error"] == "You need to sign in or sign up before continuing."
redirect_to unauthorized_path
# erreur de validation
elsif #response["error"]
raise
#errors = #response["errors"]
render :multiple_new
else
raise
redirect_to account_path(account_id)
end
end
end
I have a corresponding method in my room_controller.rb that is responsible for creating rooms, beds for each rooms and slots for each beds. On the API I am using Pundit for authorization.
def multiple_create
i = 0
start_date = Date.today
ActiveRecord::Base.transaction do
while i < params[:room_number].to_i
#room = #hotel.rooms.build(room_params)
authorize #room
if #room.save
(0...params[:bed_number].to_i).each do
#bed = #room.beds.create!
for a in 0...60
#bed.slots.create!(available: true, date: start_date + a.days )
end
end
i+=1
else
break
end
end
end
if i == params[:room_number]
render json: {success: "All rooms and beds where successfully created"}
else
render json: {error: "There was a problem during room creation process. Please try again later"}
end
end
Everytime I try to post on this method I get :
Pundit::AuthorizationNotPerformedError - Pundit::AuthorizationNotPerformedError:
pundit (1.0.1) lib/pundit.rb:103:in `verify_authorized
It seems to me I am actually calling authorize #room before saving the new room during the loop. I have a method multiple_create in my room_policy.rb:
def multiple_create?
(user && record.hotel.account.admin == user) || (user && user.manager && (user.account == record.hotel.account))
end
And in my API base_controller I have :
after_action :verify_authorized, except: :index
Why am I getting this pundit error here ?
Thats a very creative solution - however there is a much way simpler and better way to deal with inserting / updating multiple records.
class Hotel
has_many :rooms
accepts_nested_attributes_for :rooms
end
accepts_nested_attributes_for means that you can create rooms with:
#hotel = Hotel.new(
rooms_attributes: [
{ foo: 'bar' },
{ foo: 'baz' }
]
)
#hotel.save # will insert both the hotel and rooms
You would create a form like so:
<%= form_for(#hotel) |f| %>
<%= f.fields_for :rooms do |rf| %>
<%= f.foo %>
<% end %>
<% end %>
And handle it in your controller like so:
class HotelsController
def update
#hotel.update(hotel_params)
respond_with(#hotel)
end
private
def hotel_params
params.require(:hotel).permit(rooms_attributes: [ :foo ])
end
end
You can nest it deeper with multiple accepts_nested_attributes_for and fields for. But in general when you go more than one level down thats a serious code smell. Split it into multiple controllers instead.
Note that you don't really need a create_multiple or update_multiple action.
So back to the core of the question, how do I authenticate it? Keep it simple stupid.
def update
authorize #hotel
# ...
end
and handle it in your HotelPolicy.
def update?
return false unless user
record.account.admin == user || (user.manager && (user.account == record.account))
end
Edit
Based on your description of what you want to do you could simply add a custom getter / setter on your Hotel model.
class Hotel < ActiveRecord::Base
has_many :rooms
# custom getter for binding form inputs
def number_of_rooms
rooms.count
end
# custom setter which actually creates the associated records
# this subtracts the existing number of rooms so that setting
# hotel.number_of_rooms = 50 on an existing record with 20 rooms
# will result in a total of 50 not 70.
def number_of_rooms=(number)
(number.to_i - number_of_rooms).times { rooms.new }
end
end
When you create or update a record like so:
[14] pry(main)> h = Hotel.new(number_of_rooms: 3)
=> #<Hotel:0x007feeb6ee2b20 id: nil, created_at: nil, updated_at: nil>
[15] pry(main)> h.save
(0.1ms) begin transaction
SQL (0.4ms) INSERT INTO "hotels" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2016-02-08 13:17:06.723803"], ["updated_at", "2016-02-08 13:17:06.723803"]]
SQL (0.2ms) INSERT INTO "rooms" ("hotel_id", "created_at", "updated_at") VALUES (?, ?, ?) [["hotel_id", 3], ["created_at", "2016-02-08 13:17:06.726157"], ["updated_at", "2016-02-08 13:17:06.726157"]]
SQL (0.4ms) INSERT INTO "rooms" ("hotel_id", "created_at", "updated_at") VALUES (?, ?, ?) [["hotel_id", 3], ["created_at", "2016-02-08 13:17:06.728636"], ["updated_at", "2016-02-08 13:17:06.728636"]]
SQL (0.1ms) INSERT INTO "rooms" ("hotel_id", "created_at", "updated_at") VALUES (?, ?, ?) [["hotel_id", 3], ["created_at", "2016-02-08 13:17:06.730291"], ["updated_at", "2016-02-08 13:17:06.730291"]]
(1.6ms) commit transaction
=> true
[16] pry(main)>
It will add build N number of associated rooms. You can then save the record normally.
You would add this to your normal hotel update / create action by simply adding a form input for number_of_rooms:
<%= form_for(#hotel) |f| %>
<% # ... %>
<%= f.label :number_of_rooms %>
<%= f.number_field :number_of_rooms %>
<% end %>
This input will be in params[:hotel][:number_of_rooms]. You should add it to your strong parameters whitelist.
Note that however you won't be able to set attributes per room. Follow the recommendation above for authorization.

Working with Rails arrays in Postgres

I have a postgres column called content which is an array.
But when trying to use it in a form I'm getting:
can't cast ActionController::Parameters to text
Despite the fact that the output looks pretty good:
{"utf8"=>"✓",
"_method"=>"patch",
"authenticity_token"=>"NkK4BggxknfEn0A8shTs06xmesERaZdYtZdl9oEEUTk=",
"notification_template"=>{"content"=>{"0"=>"Join us {{event_time}} {{{twitter_name}}} to win Big! hint: {{{question}}} #quiz {{location_tags}} {{url}} sdfsdfsdf"}},
"commit"=>"Update Notification template",
"id"=>"25"}
strong params
params.require(:notification_template).permit(:name, :content => {})
routes
resources :notification_templates do
get 'edit/:id', to: 'notification_templates#edit_content', as: 'edit_content'
end
controller
def edit_content
#notification_template = NotificationTemplate.find(params[:notification_template_id])
end
def update
if #notification_template.update(notification_template_params)
redirect_to admin_notification_template_path(#notification_template), notice: 'Social message was successfully updated.'
else
render action: 'edit'
end
end
my form
the url looks like: /notification_templates/25/edit_content/7 # custom action, but uses normal update
<%= simple_form_for([:admin, #notification_template]) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.simple_fields_for :content do |fields| %>
<%= fields.input params[:id], input_html: { value: #notification_template.content[params[:id].to_i] } %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
the DB column
add_column :notification_templates, :content, :text, array: true, default: []
Lastly, I was unsure about the conventions for adding it. The above worked fine, but I also noticed other possibilities such as
add_column :notification_templates, :content, :text, array: true, default: []
add_column :notification_templates, :content, :sting, array: true, default: []
add_column :notification_templates, :content, :text, array: true, default: {}
I choose the first one on the basis that a string wouldn't allow for as many characters as I might eventually need and text is more convenient. Also the default of [] vs {} or '{}'
But in postgres is see content text[] DEFAULT '{}'::text[]
log
Started PATCH "/admin/notification_templates/25" for 127.0.0.1 at 2014-11-28 14:25:43 +0100
Processing by Admin::NotificationTemplatesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"NkK4BggxknfEn0A8shTs06xmesERaZdYtZdl9oEEUTk=", "notification_template"=>{"content"=>{"4"=>"{{{question}}} Study up and stop by {{{twitter_name}}} {{event_time}} for a #quiz {{location_tags}} {{url}} sdfsdfsdf"}}, "commit"=>"Update Notification template", "id"=>"25"}
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
NotificationTemplate Load (0.5ms) SELECT "notification_templates".* FROM "notification_templates" WHERE "notification_templates"."id" = $1 LIMIT 1 [["id", 25]]
(0.3ms) BEGIN
(0.3ms) ROLLBACK
Completed 500 Internal Server Error in 54ms
Reporting exception: can't cast ActionController::Parameters to text
TypeError (can't cast ActionController::Parameters to text):
app/controllers/admin/notification_templates_controller.rb:40:in `update'
Rendered /Users/holden/.rvm/gems/ruby-2.0.0-p481#questionone-2.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_source.erb (1.1ms)
Rendered /Users/holden/.rvm/gems/ruby-2.0.0-p481#questionone-2.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.0ms)
Rendered /Users/holden/.rvm/gems/ruby-2.0.0-p481#questionone-2.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.4ms)
Rendered /Users/holden/.rvm/gems/ruby-2.0.0-p481#questionone-2.0/gems/actionpack-4.1.7/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (27.5ms)
UPDATE
I also observed that update array type field doesn't work as expected in the console.
eg. if I attempt to update a member of the array, something = record.content[2] = 'blah' it appears to work. But when I save the record it doesn't update it.
Yeah, Rails postgres Arrays are still a bit wonky. Hstore is a bit easier.
You may be better served going thru a virtual attribute and doing what you want expressly rather than relying on standard rails behavior through a form.
eg.
def content_member=(member)
unless member.blank?
self.content_will_change!
self.content[member.keys.first.to_i] = member.values.first
end
end
You also need to let rails know if you're going to update a member of an array, that's why it doesn't work in the console.
There's a full explanation here:
Rails 4 Postgresql array data-type: updating values

Rails form to create model with reference

I'm trying to create a model form that will allow me to add references by name via a <select> tag.
e.g.
In the database there are already RefModels with ref_name = "a", ref_name = "b", ref_name = "c".
Form:
<%= form_for #model %>
<%= f.label :ref_models, "Referenced Models:" %>
<%= f.select :ref_models, ["a","b","c"], {}, {:multiple => true} %>
Controller:
def create
#model = Model.new(model_params)
params[:model][:ref_models].each do |ref|
#ref = RefModel.where("ref_name = ?", ref)
#model.ref_models << #ref
end
respond_to do |format|
...
end
end
In my logs I'm getting this error:
Started POST "/models" for 127.0.0.1 at 2013-06-25 16:20:48 -0300
Processing by ModelssController#create as JS
Parameters: {"utf8"=>"✓", "models"=>{..., "ref_models"=>["a", "b", "c"], ...}, "commit"=>"Create"}
Completed 500 Internal Server Error in 2ms
ActiveRecord::AssociationTypeMismatch (RefModel(#70144007274440) expected, got String(#70144005442620)):
app/controllers/models_controller.rb:52:in `create'
What's the problem?
Note:
I changed the actual model names for "model" and "ref_model" to generalize.
EDIT:
The error occurs on this line:
#model = Model.new(model_params)
The error comes from this part:
#model = Model.new(model_params)
I'm pretty sure your model_params is actually params[:model]. If yes, it means it tries to create a record for Model with the attribute ref_models and the values contained in params[:model][:ref_models]
You should take off the params[:model][:ref_models] before passing it to the Model.new(params[:model]):
def create
ref_models = params[:model].delete(:ref_models)
#model = Model.new(params[:model])
ref_models.each do |ref|
#ref = RefModel.where("ref_name = ?", ref)
#model.ref_models << #ref
end
respond_to do |format|
...
end
end
Do these ref_models have IDs as well as names? If so, you can get Rails to do the heavy lifting for you.
In your view, do:
<%= f.select :ref_model_ids, RefModel.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>
Then, you can take out the custom code from your controller, Rails knows how to link those models up appropriately. That's assuming you have a table like model_ref_model with columns for model_id and ref_model_id.
Hope that helps...

'Unknown key(s)' ArgumentError

I'm working on a moderating feature for my application, which is based on a basic scaffold structure. What I need, is to edit several records with the boolean parameter publised on false. In moderate.html I'm getting the list of all unpublished entries with the ability to change their parameters which, what and published. The error appears, when I'm trying to save the changes through the complete action.
ArgumentError in NamesController#complete
Unknown key(s): 7, 1, 4
The "7, 1, 4" are id of my unpublished records.
Here are the parts of my code:
#names_controller.rb
def moderate
#names = Name.find(:all, params[:name_ids], :conditions => {:published => false})
respond_to do |format|
format.html { render :action => "moderate" }
format.xml
end
end
def complete
#names = Name.find(params[:name_ids])
#names.each do |name|
name.update_attributes!(params[:name].reject { |k,v| v.blank? })
end
flash[:notice] = "Updated records!"
redirect_to names_path
end
#moderate.html.erb
<% form_tag complete_names_path do %>
<% #names.each do |name| %>
<fieldset>
<% fields_for "name_ids[#{name.id}]", name do |name_fields| %>
<%= name_fields.text_field :which %>
<%= name_fields.text_field :what %>
<%= name_fields.check_box :published %>
<% end %>
</fieldset>
<% end %>
<%= submit_tag "Ok" %>
<% end %>/
#routes.rb
ActionController::Routing::Routes.draw do |map|
map.connect 'moderate', :controller => 'names', :action => 'moderate'
map.resources :names, :collection => { :complete => :put}
map.root :names
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
I understand, that there's something wrong with the name_ids, but don'nt understand, what should I do.
Thank you in advance.
ruby 1.8.7 (2009-06-12 patchlevel 174)
[universal-darwin10.0] Rails 2.3.5
Rails log for moderate and complete actions:
Processing NamesController#moderate (for 127.0.0.1 at 2010-10-16 21:36:42)
[GET] [4;35;1mName Load (0.6ms)[0m
[0mSELECT * FROM "names" WHERE
("names"."published" = 'f') [0m
Rendering template within
layouts/names Rendering names/moderate
Completed in 12ms (View: 7, DB: 1) |
200 OK [http://localhost/moderate]
Processing NamesController#complete
(for 127.0.0.1 at 2010-10-16 21:36:49)
[POST] Parameters: {"commit"=>"Ok",
"authenticity_token"=>"CtmsjIavksOMSIArrdovkkzuZzHVjkenFFMO5bHIvgg=",
"name_ids"=>{"7"=>{"published"=>"0",
"what"=>"Партия", "which"=>"Крутая"},
"1"=>{"published"=>"1",
"what"=>"Россия", "which"=>"Единая"},
"4"=>{"published"=>"0",
"what"=>"Организация",
"which"=>"Молдавская"}}}
[4;36;1mName Load (0.4ms)[0m
[0;1mSELECT * FROM "names" WHERE
("names"."id" IN (7,1,4)) [0m
NoMethodError (You have a nil object
when you didn't expect it! You might
have expected an instance of Array.
The error occurred while evaluating
nil.reject):
app/controllers/names_controller.rb:47:in
complete'
app/controllers/names_controller.rb:46:in
each'
app/controllers/names_controller.rb:46:in
`complete'
Rendered rescues/_trace (110.3ms)
Rendered rescues/_request_and_response
(0.5ms) Rendering rescues/layout
(internal_server_error)
Likely you need to get just the keys from the name_ids hash. Try:
#names = Name.find(params[:name_ids].keys)
A separate problem is your reference to params[:name], which is nil. Did you mean (EDIT: use to_s to match the params key, lol):
#names.each do |name|
name.update_attributes!(params[:name_ids][name.id.to_s].reject { |k,v| v.blank? })
end
EDIT (brief-ish explanation):
What was happening was that you had a nested hash in the params, params[:name_ids]. It looked like:
"name_ids"=>{"7"=>{"published"=>"0", "what"=>"Партия", "which"=>"Крутая"}, "1"=>{"published"=>"1", "what"=>"Россия", "which"=>"Единая"}, "4"=>{"published"=>"0", "what"=>"Организация", "which"=>"Молдавская"}}
An ActiveRecord 'find' method can take an array of ids, but not a hash of values. What you were originally submitting to 'find' in this line:
#names = Name.find(params[:name_ids])
...was the value for params[:name_ids]:
{"7"=>{"published"=>"0", "what"=>"Партия", "which"=>"Крутая"}, "1"=>{"published"=>"1",
"what"=>"Россия", "which"=>"Единая"}, "4"=>{"published"=>"0", "what"=>"Организация",
"which"=>"Молдавская"}
When what you wanted was:
#names = Name.find(['7','1','4'])
which is what calling params[:name_ids].keys gives you.
The second problem was this line:
name.update_attributes!(params[:name].reject { |k,v| v.blank? })
There was no value ':name' in params, so calling 'reject' on it cause the 'no method' error -- there is no 'reject' method on the nil object. What you wanted was to update the attributes for the 'name' that corresponded to the particular name in the loop. This meant you wanted to get the values out of params[:name_ids][:id] where :id was the id of 'name'.
It all goes back to the way fields_for created the params to begin with. This line:
<% fields_for "name_ids[#{name.id}]", name do |name_fields| %>
meant that params would contain a hash called 'name_ids', with keys corresponding to name.id, that themselves would contain hashes of attributes that ActiveRecord could use in the update_attributes method.
There's a good bit of the famous Rails magic to keep track of in there -- does that help?

Resources