Ruby on Rails add specific attribute to newly created object in view - ruby-on-rails

I am using a form_for helper to create a new comment on a page. Whenever the submit button is clicked, I also want to give the new comment an attribute, like :this_id => 4. Is this somehow possible in the view?

Use hidden_field :
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-hidden_field
hidden_field(:signup, :pass_confirm)
# => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{#signup.pass_confirm}" />
hidden_field(:post, :tag_list)
# => <input type="hidden" id="post_tag_list" name="post[tag_list]" value="#{#post.tag_list}" />
hidden_field(:user, :token)
# => <input type="hidden" id="user_token" name="user[token]" value="#{#user.token}" />

Related

undefined method `map' for "1,2":String

I need to pass an array in a params, possible? Values can be, for example, ["1","2","3","4","5"] and these are strings but needs to eb converted to integers later.
I use a react_component in between a rails form_for. The html is like this:
<input type="hidden" name="people_id" id="people_id" value={this.state.people} />
The people array looks like this:
How can I pass the array in the value of the hidden field? The server error I got was
Im trying to do something like this in a model:
ids = params[:people_id]
ids.map do |b|
Foo.create!(people_id: b.to_i)
end
If I ids.split(",").map I get symbol to int error.
Edit:
––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
Still not sure what the issue is as nothing works. Here is a minimal reproduction of my code:
This answer is my react component and that's how I add to the array. Still in the component, I have the hidden field:
<input type="hidden" name="[people_id][]" id="people_id" value={this.state.people} />
_form.html.erb:
<%= form_for resource, as: resource_name, url: registration_path(resource_name), :html => { :data => {:abide => ''}, :multipart => true } do |f| %>
<!-- react component goes here -->
<%= f.submit "Go", class: "large button" %>
<% end %>
The story is, guest can select few people during registration in one go. Those people will be notified when registration is complete. Think of it as "I am inviting these people to bid on my tender". Those numbers, in the array, are user_ids.
users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
# POST /resource
def create
super do |resource|
ids = params[:people_id].pop # logs now as "people_id"=>["1,2"]
resource.save!(ids.split(",").map |b| Foo.create!(people_id: b.to_i) end)
end
end
end
New error on line resource.save:
no implicit conversion of Symbol into Integer
Edit #2
If I only have, in the create method:
ids.split(",").map do |b|
resource.save!(Foo.create!(people_id: b.to_i))
end
It works! Foo is created two times each with the correct people_id.
Because I am creating more objects: Bar, I do not know how to do that in:
resource.save!(<the loop for Foo> && Bar.create!())
The flow must be:
Device creates the User
Foo is created with the loop
Bar is created
etc
It has to be done that way as an User object is created on the fly.
In Rails you use parameter keys with brackets on the end to pass arrays.
However you should not concatenate the values as a comma seperated list but rather send each value as a seperate param:
GET /foo?people_ids[]=1&people_ids[]=2&people_ids[]=3
That way Rails will unpack the parameters into an array:
Parameters: {"people_ids"=>["1", "2", "3"]}
The same principle applies to POST except that the params are sent as formdata.
If you want a good example of how this works then look at the rails collection_check_boxes helper and the inputs it generates.
<input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" />
<label for="post_author_ids_1">D. Heinemeier Hansson</label>
<input id="post_author_ids_2" name="post[author_ids][]" type="checkbox" value="2" />
<label for="post_author_ids_2">D. Thomas</label>
<input id="post_author_ids_3" name="post[author_ids][]" type="checkbox" value="3" />
<label for="post_author_ids_3">M. Clark</label>
<input name="post[author_ids][]" type="hidden" value="" />
Updated:
If you intend to implement you own array parameters by splitting a string you should not end the input with brackets:
<input type="hidden" name="[people_id][]" value="1,2,3">
{"people_id"=>["1,2,3"]}
Notice how people_id is treated as an array and the input value is the first element.
While you could do params[:people_id].first.split(",") it makes more sense to use the correct key from the get go:
<input type="hidden" name="people_id" value="1,2,3">
Also you don't really want to wrap the "root" key in brackets. Thats used in rails to nest a param key in a hash eg. user[name].

What URL should I use to PUT an update?

I have a Rails app that I just picked up that has the following command in "rake routes":
PUT /testclass/:id(.:format) testclass#update
I want to send a PUT update to this testclass with the id 18445 and change finished to false:
/18445&finished=false
for example.
My understanding is this should be able to be done by a HTTP request in the browser, for example, can it? Or do I need to use a Ruby command?
Any guidance?
You do not need to use a ruby command to access that route to make an update.
Basic HTML will look something like this (you can edit the action to be relevant to your route):
<form action='testclass/18445' method="post">
<input type="hidden" name="_method" value="put">
<input name="authenticity_token" value="<%= form_authenticity_token %>" type="hidden">
<input type="hidden" name="testclass[id]" value="18445" >
<input type="hidden" name="testclass[finished]" value="false" >
<input type="submit" value="update" >
</form>
Notice it is a 'post' but there is a hidden input with the name '_method' and value 'put'. Hopefully this is what you're looking for. You can send your id through a hidden input, same with the false value.

Nested attributes and interacting with form hash and setting the user_id to current_user.id

I have rewritten this question as the other one seemed too verbose. I have the following model structure and am interested in having a set of files uploaded (2 at a time via a builder). I am not sure if the polymorphic relat
class Item < ActiveRecord::Base
has_many :assets, :as => :assetable, :dependent => :destroy
accepts_nested_attributes_for :assets, :allow_destroy => true, :reject_if => lambda { |a| a[:asset].blank? }
attr_accessible :assets_attributes, :asset
...
end
class Asset < ActiveRecord::Base
belongs_to :assetable, :polymorphic => true
attr_accessible :name, :user_id, :description ...
...
end
I have copied out the entirety of the form:
<form accept-charset="UTF-8" action="/arc/items/70" class="edit_item" enctype="multipart/form-data" id="edit_item_70" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="_method" type="hidden" value="put" /><input name="authenticity_token" type="hidden" value="NnaCxwmfy2zT8MnN7oNQnOx0xYXkgKUs+NbIh8+8cL4=" /></div>
<div class='files'>
<input id="item_assets_attributes_70_asset" name="item[assets_attributes][70][asset]" type="file" />
<input id="item_assets_attributes_70_description" name="item[assets_attributes][70][description]" size="30" type="text" />
<input id="item_assets_attributes_71_asset" name="item[assets_attributes][71][asset]" type="file" />
<input id="item_assets_attributes_71_description" name="item[assets_attributes][71][description]" size="30" type="text" />
</div>
<input name="commit" type="submit" value="Update Menu item" />
</form>
and here is the controller for interacting with it:
class ItemsController < ApplicationController
...
def update
item=params[:item]
item[:assets_attributes].values do |v|
v[:asset][:user_id]=3 # just hard-code it to see if workig
end
if #item.update_attributes(item)
flash[:notice]="Menu Item has been updated #{undo_link}"
else
flash[:notice]="Menu Item has not been updated"
end
end
In my asset class, the user_id NEVER gets set. How would I make this work? I obviously want to get the current_user.id.
thx
edit #1
Using Rails 3.1
edit 2
One thing that I've noticed is that if I set an instance variable in the loop and then debug it into the view, it wasn't set meaning that this loop isn't even running.
item[:assets_attributes].values do |v|
v[:user_id]=3
#a="here is a string"
end
I have also updated the Item model with the appropriate attr_accessible for the item class.
In this block you're not doing anything.
item[:assets_attributes].values do |v|
v[:user_id]=3 # just hard-code it to see if working
end
values is just returning the values, so you need to have an iterator like each if you want to interact with those values. Try this
item[:assets_attributes].values.each do |v|
v[:user_id]=3 # just hard-code it to see if working
end
It seems likely that you cannot mass assign user_id. Either:
You have attr_accessible defined, and it does not include user_id
You have attr_protected defined, and it does include user_id
You are using Rails 3.2, which does this automatically to prevent reassigning an object to a different user via mass assignment (which is a security hole).
If that is the case, then your best bet is to set the user directly via asset.user= instead (or to allow user_id to be mass assigned, I suppose).

How to assign a value to a accepts_nested_attributes_for model

This is a follow-up to this question where's the appropriate place to handle writing the current_user.id to an object I have the following model. An item which has_many assets. I'm am using accepts_nested_attributes_for :assets in the item.
I'd like to assign the current_user.id value to each asset. Normally I just do #item.update_attributes(params[:item]) to save it. Is there a simple one line way of setting the user_id for each asset in this scenario?
Looking in dev log, I see the value here:
item[assets_attributes][10][asset]
Should I just iterate through all of these and set a user_id value?
thx
here's some more of the html (items -> menu_item; had left out above to simplify). The proposed controller sol'n below does not seem to work. I'm fine with doing at the level of controller. Any help appreciated.
<div class='image-row'>
<input id="menu_item_assets_attributes_18_asset" name="menu_item[assets_attributes][18][asset]" type="file" />
<input id="menu_item_assets_attributes_18_description" name="menu_item[assets_attributes][18][description]" size="30" type="text" />
</div>
<div class='image-row'>
<input id="menu_item_assets_attributes_19_asset" name="menu_item[assets_attributes][19][asset]" type="file" />
<input id="menu_item_assets_attributes_19_description" name="menu_item[assets_attributes][19][description]" size="30" type="text" />
</div>
<div class='image-row'>
<img alt="D5cc413a1748fb43b0baa2e32e29b10ac2efda10_huntbch_thumb" src="/images/371/d5cc413a1748fb43b0baa2e32e29b10ac2efda10_huntbch_thumb.jpg?1329917713" />
<div class='img-row-description'>
<label for="menu_item_assets_attributes_20_description">Description</label>
<input id="menu_item_assets_attributes_20_description" name="menu_item[assets_attributes][20][description]" size="60" type="text" value="here is my comment" />
<label for="menu_item_assets_attributes_20_destroy">Destroy</label>
<input name="menu_item[assets_attributes][20][_destroy]" type="hidden" value="0" /><input id="menu_item_assets_attributes_20__destroy" name="menu_item[assets_attributes][20][_destroy]" type="checkbox" value="1" />
</div>
This answer is probably a little bit muddier than your previous one.
If each asset must have an item, then it might be more sensible to remove the idea of an owning user from an asset entirely: you can always find the owning user by querying the attached item, something like #asset.item.user. However, if users can own assets independently of items, I don't think this will work for you.
If assets are always created in a nested manner for items, a before_create for the asset could assign the value you want. Something like this in asset.rb:
before_create :assign_user
def assign_user
self.user = self.item.user if self.item && self.item.user
end
Finally, if you just want to do it in the controller, Wolfgang's answer is really good and will add the user_id to each asset_attributes.
How about iterating over the params array and setting the value like so:
params[:item][:assets_attributes].map! do |asset_params|
asset_params[:user_id] = current_user.id
end
Now you can use update_attributes( params[:item] ) as before.

radiobutton with ruby

i m doing a project on "student attendance management system".i using rail of version 1.9.1
and rail of version 2.5. i wanted to use radiobutton in my project to mark present and absent so how can i use?please send me the code and what should i do? if you want to give any suggetion so i will very happy.
Taken from the rails api docs:
radio_button(object_name, method,
tag_value, options = {})
Returns a radio button tag for
accessing a specified attribute
(identified by method) on an object
assigned to the template (identified
by object). If the current value of
method is tag_value the radio button
will be checked.
To force the radio button to be
checked pass :checked => true in the
options hash. You may pass HTML
options there as well. Examples
# Let's say that #student.attendance returns "rails":
radio_button("student", "attendance", "present")
radio_button("student", "attendance", "absent")
# => <input type="radio" id="student_attendance_present" name="student[attendance]" value="present" checked="checked" />
# <input type="radio" id="student_attendance_absent" name="student[attendance]" value="absent" />
radio_button("user", "receive_newsletter", "yes")
radio_button("user", "receive_newsletter", "no")
# => <input type="radio" id="user_receive_newsletter_yes" name="user[receive_newsletter]" value="yes" />
# <input type="radio" id="user_receive_newsletter_no" name="user[receive_newsletter]" value="no" checked="checked" />

Resources