Remove blank element from array - ruby-on-rails

When I'm saving multiple select from a ruby on rails form it appears to be adding a blank element at the front. How do I remove it? The field is selected_player.
{"utf8"=>"✓",
"authenticity_token"=>"H8W7qPBezubyeU0adnTGZ4oJqYErin1QNz5oK0QV6WY=",
"schedule"=>{"event"=>"1",
"result_id"=>"",
"time"=>"26/10/2012",
"duration"=>"15",
"arrival_time"=>"14",
"location_id"=>"25",
"selected_players"=>["", "38", "41"],
"team_id"=>"1",
"opponent_id"=>"7",
"home_or_away"=>"Home"},
"commit"=>"Save Event"}
controller
def update
#schedule = Schedule.find(params[:id])
#user = User.find(current_user)
#players = User.where(:team_id => current_user[:team_id]).all
respond_to do |format|
if #schedule.update_attributes(params[:schedule])
Notifier.event_added(#user,#schedule).deliver
format.html { redirect_to(#schedule,
:notice => "#{event_display_c(#schedule.event)} vs #{#schedule.opponent.name} was successfully updated.") }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => #schedule.errors, :status => :unprocessable_entity }
end
end
end

This works for empty strings:
array.delete_if(&:empty?)
To filter out empty strings and nil values use:
array.delete_if(&:blank?)
Example:
>> a = ["A", "B", "", nil]
=> ["A", "B", "", nil]
>> a.delete_if(&:blank?)
=> ["A", "B"]

Ref reject! of Array class
params["schedule"]["selected_players"] = ["", "38", "41"]
params["schedule"]["selected_players"].reject!{|a| a==""} #gives params["selected_players"] = ["38", "41"]

This should work as well.
params["schedule"]["selected_players"].reject!(&:blank?)

Something like:
params["selected_players"].select!{|val| !val.empty?}
should work

What is "selected_players"? Is it something like "collection_singular_ids" of the collection associations? If so, you can leave it as it is, because ActiveRecord will remove the blank elements from the array with following code:
ids = Array.wrap(ids).reject { |id| id.blank? }

If you want to handle this in the model rather than the controller you can add a setter method like this
def selected_players=(param_array)
write_attribute(:selected_players, param_array.reject(&:blank?))
end

I think params["selected_players"].compact is the most succinct.
Docs are here: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-compact

Related

String substitution within ruby array

I have the following code, within which I want to change certain values to csv friendly, e.g., 'nil' to ''. I need to know how to make these changes. Thank you.
def daily_door_schedule
#tickets = Ticket.where(active: true).
pluck(
:door_manufacturer,
:job_number,
:door_style,
:door_allocation_date,
:date_doors_received_in_aub,
:door_delivery_due_date,
:notes
)
respond_to do |format|
format.html
format.csv { render text: #tickets.to_csv }
end
end
This should do it:
#tickets = Ticket.where(active: true).
pluck(
:door_manufacturer,
:job_number,
:door_style,
:door_allocation_date,
:date_doors_received_in_aub,
:door_delivery_due_date,
:notes
).map { |ticket| ticket.map(&:to_s) }

param is missing or the value is empty: user_club - rails

I want to call create action of controller user_clubs and I did this way:
View Clubs
<button>
<%= link_to "Join Club", user_clubs_path(:user_id => current_user.id, :club_id => #club.id, :join_date => Date.current), :method => :post %>
</button>
Controller user_clubs
def create
#user_club = UserClub.new(user_club_params)
respond_to do |format|
if #user_club.save
format.html { redirect_to #user_club, notice: 'User club was successfully created.' }
format.json { render :show, status: :created, location: #user_club }
else
format.html { render :new }
format.json { render json: #user_club.errors, status: :unprocessable_entity }
end
end
end
def user_club_params
params.require(:user_club).permit(:user_id, :club_id, :join_date) --->**Error here**
end
Error information
app/controllers/user_clubs_controller.rb:75:in user_club_params'
app/controllers/user_clubs_controller.rb:28:increate'
Request
Parameters:
{"_method"=>"post",
"authenticity_token"=>"5Grhb+LIGt9B8XbnEcvg7BZQlDE935KO/aeikZoqxYs=",
"club_id"=>"1",
"join_date"=>"2014-11-17",
"user_id"=>"2"
}
Clubs and UserClubs are different. Club is a model that represents a team of people and user_clubs is the model that represents the many-to-many relationship between Users and Clubs.
First, can someone explain me how the call to user_clubs_path followed by the arguments know that has to go to the action create of user_clubs controller?
In second, the objective problem, why is this an error?
First question
Because of your routes definition, type into a terminal:
rake routes
And you'll see all generated routes and its associated helpers. First column (rake output) references the named helper: user_clubs => user_clubs_path):
Second question
You should add the parameters into user_club key, because you're requiring (by strong_parameters) this "scope" params.require(:user_club):
user_clubs_path(:user_club => {:user_id => current_user.id, :club_id => #club.id, :join_date => Date.current})
You'll receive in the controller:
{
"_method" => "post",
"authenticity_token" => "...",
"user_club" => {
"club_id" => "1",
"join_date"=> "2014-11-17",
"user_id"=> "2"
}
}
The parameters need to be nested under the user_club key. Try this instead:
user_clubs_path(:user_club => {:user_id => current_user.id, :club_id => #club.id, :join_date => Date.current})

How to get the whole array of name in one array object using json?

In my code,i am parsing a JSON object like
[{"name":"karthi"},{"name":"shreshtt"},{"name":"jitu"},{"name":null},{"name":null},{"name":null},{"name":null}]
In this, I want to collect all names in an single array object. This is how my controller looks as of now. I want to store the resultant name array in #hotels variable.
controller.erb
respond_to :json, :xml
def index
#hotels = Hotel.all
respond_to do |format|
format.html # show.html.erb
format.json { render json: #hotels.to_json(:only => [ :name ]) }
end
end
view/hoels/index.json.erb
[
hotel: <% #hotels.each do |hotel| %>
{ 'name': "<%= hotel.name.to_json.html_safe %>" }
<% unless index== #hotels.count - 1%>
<% end %>
<% end %>
]
You want to add just the names to an array?
How about:
a = [{name: "karthi"},{name: "shreshtt"},{name: "jitu"},{name: nil},{name: nil},{name: nil},{name: nil}]
#hotel = []
a.collect{|a_name| #hotel << a_name[:name]}
=> ["karthi", "shreshtt", "jitu", nil, nil, nil, nil]
#hotel.compact!
=> ["karthi", "shreshtt", "jitu"]
What´s about that?
a = {}
a["hotel"] = []
array = [{"name"=>"kathi"}, {"name"=>"kathi2"}, {"name"=>"kathi3"}, {"name"=>"kathi4"}, {"name" => nil}]
a["hotel"] = array
a["hotel"].each do |v|
if v["name"] == nil
a["hotel"].delete(v)
end
end
a => {"hotel"=>[{:name=>"kathi"}, {:name=>"kathi2"}, {:name=>"kathi3"}, {:name=>"kathi4"}]}
You can do like following
hotels = Hotel.select("name").where("name is not NULL")
json_obj = {hotels: hotels}.to_json
format.json { render json: json_obj }

JSON Rendering: How to include the opening bracket description?

I have some Ruby code that is putting out JSON like this:
def nearby
##bathrooms = Bathroom.geo_scope(:origin =>[params[:lat],[params[:lon]]], :within => 5)
lat = params[:lat]
lon = params[:lon]
##bathrooms = Bathroom.geo_scope(:within => 5, :origin => [45.580639,-122.677682], :order=>'distance')
#bathrooms = Bathroom.geo_scope(:within => 3, :origin => [lat,lon], :order=>'distance')
respond_to do |format|
format.json { render :json => #bathrooms }
format.js { render :nothing => true }
end
end
The result is something like this:
[{"ID":129,"access":"1","avail":"0","bathroomtype":"0","city":"PORTLAND","comment":"","country":"US","created":"0000-00-00 00:00:00","directions":"The two bathrooms are in the long hallway at the back of the restaurant, past the bar.","distance":"2.94986114636676","lat":"45.539217","lon":"-122.661795","modifed":"0000-00-00","name":"Echo","postal":"97212-3727","slug":"echo-portland170","source":"","state":"OR","street":"2225 NE Martin Luther King Jr. Blvd"},
What I don't know how to do is to name the set? For example, after the first enclosing bracket I would like to name the set bathrooms. How can I do this is Rails?
Try:
render json: { bathrooms: #bathrooms }
It looks like #bathrooms is a list, so you can't assign keys to elements in lists. You'll need to make a map first. For example, if you only want the first element:
format.json { render :json => {:bathrooms => #bathrooms[0]} }
To set all list elements:
format.json { render :json => {:bathrooms => #bathrooms} }

.save puts NULL in id field in Rails

Here's the model file:
class ProfileTag < ActiveRecord::Base
def self.create_or_update(options = {})
id = options.delete(:id)
record = find_by_id(id) || new
record.id = id
record.attributes = options
puts "record.profile_id is"
puts record.profile_id
record.save!
record
end
end
This gives me the correct print out in my log. But it also says that there's a call to UPDATE that sets profile_id to NULL. Here's some of the output in the log file:
Processing ProfilesController#update (for 127.0.0.1 at 2010-05-28 18:20:54) [PUT]
Parameters: {"commit"=>"Save", "profile"=>{"id"=>"2", "password_confirmation"=>"", "username"=>"user2", "first_name"=>"user2_first", "password"=>"", "last_name"=>"user2_last"}, "authenticity_token"=>"...", "tag"=>"1", "id"=>"2"}
?[4;36;1mProfileTag Create (0.0ms)?[0m ?[0;1mINSERT INTO `profile_tags`
(`reputation_value`, `updated_at`, `tag_id`, `id`, `profile_id`, `created_at`) VALUES(0, '2010-05-29 01:20:54', 1, NULL, 4, '2010-05-29 01:20:54')?[0m
?[4;35;1mSQL (2.0ms)?[0m ?[0mCOMMIT?[0m
?[4;36;1mSQL (0.0ms)?[0m ?[0;1mBEGIN?[0m
?[4;35;1mSQL (0.0ms)?[0m ?[0mCOMMIT?[0m
?[4;36;1mProfileTag Load (0.0ms)?[0m ?[0;1mSELECT * FROM `profile_tags` WHERE (`profile_tags`.profile_id = 4) ?[0m
?[4;35;1mSQL (1.0ms)?[0m ?[0mBEGIN?[0m
?[4;36;1mProfileTag Update (0.0ms)?[0m ?[0;1mUPDATE `profile_tags` SET profile_id = NULL WHERE (profile_id = 4 AND id IN (35)) ?[0m
I'm not sure I understand why the INSERT puts the value into profile_id properly, but then it sets it to NULL on an UPDATE.
[Edit]
In ProfileController:
def update
#...stuff. Set tags array.
save_tags(tags) #These tags are correct. Verified by printouts before and after this call.
respond_to do |format|
if #profile.update_attributes(params[:profile])
flash[:notice] = 'Profile was successfully updated.'
#format.html { redirect_to(#profile) }
format.html { redirect_to :action=>'show' }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #profile.errors, :status => :unprocessable_entity }
end
end
end
def save_tags(tags)
profile = find_profile #finds the correct profile. And I confirm that it exists with a printout
tags.each do |t|
ProfileTags.create_or_update(:profile_id => profile.profile_id, :tag_id => t.id)
end
end
If you need more specifics, please let me know. I'm thinking that the save functionality does many things other than INSERTs into the database, but I don't know what I need to specify so that it will properly set profile_id.
Look at the line:
ProfileTags.create_or_update(:profile_id => profile.profile_id, :tag_id => t.id)
I believe you want to pass profile.id, and not profile.profile_id (which is probably null).
save! itself should't do this.
Maybe your problem is the name of the method. ActiveRecord::Base already have a method named create_or_update (see http://github.com/rails/rails/blob/2-3-stable/activerecord/lib/active_record/base.rb#L2913) which is called by save! - maybe replacing it causes this weird problem.
Try changing the name of your method to something else, it might help.
You aren't passing the id attribute to the create_or_update method in the first place, so you don't need to call it, just call create instead, like so:
def save_tags(tags)
profile = find_profile #finds the correct profile. And I confirm that it exists with a printout
tags.each do |t|
ProfileTag.create(:profile_id => profile.profile_id, :tag_id => t.id)
end
end

Resources