rails passing null values when creating using AR create method - ruby-on-rails

In my rails application, I have a button which when clicked, copies data from one database and insert it in another.
I am using octopus gem to link my application to 2 databases.
To copy a record from db_A to db_B, I am using the code below:
Octopus.using(:shard_B) do
#book_new_live = Book.create(
:BK_SUB_FK => #book.BK_SUB_FK,
:BK_TITLE => #book.BK_TITLE,
:BK_SOURCE => "",
:BK_PUB => "",
:BK_COVER => "",
:BK_LABEL_PRODUCT => #book.BK_LABEL_PRODUCT,
:BK_FINAL_LABEL => "",
:BK_VISUAL_METHOD => #book.PRB_VISUAL_METHOD,
:BK_DB => "",
:BK_COVERED_REGION => "",
:BK_VERSION_NO => #book.BK_VERSION_NO,
:BK_SEQ_FILE => "",
)do |primary|
primary.BK_ID = #book.BK_ID
end
end
Database 'db_b', to which data in copied, does not accept null values and the columns cannot be null and the default value is 'NONE'.
Also, I am not allowed to modify the structure of the database so that it can accept null values.
If I use the simplified code below, I get an error message which informs me that the columns 'BK_SOURCE', 'BK_PUB', 'BK_COVER'...cannot be null. By default rails is passing null to those columns.
So I have to pass empty strings to the columns which cannot be null.
Octopus.using(:shard_B) do
#book_new_live = Book.create(
:BK_SUB_FK => #book.BK_SUB_FK,
:BK_TITLE => #book.BK_TITLE,
:BK_LABEL_PRODUCT => #book.BK_LABEL_PRODUCT,
:BK_VISUAL_METHOD => #book.PRB_VISUAL_METHOD,
:BK_VERSION_NO => #book.BK_VERSION_NO,
)do |primary|
primary.BK_ID = #book.BK_ID
end
end
Is there a way of preventing rails from passing null values to the columns not mentioned in the above code?

If i understand you correctly, you can just use the or operator to send your values like this:
Octopus.using(:shard_B) do
#book_new_live = Book.create(
:BK_SUB_FK => #book.BK_SUB_FK,
:BK_TITLE => #book.BK_TITLE,
:BK_SOURCE => #book.BK_SOURCE || "NONE",
:BK_PUB => #book.BK_PUB || "NONE",
:BK_COVER => #book.BK_COVER || "NONE",
:BK_LABEL_PRODUCT => #book.BK_LABEL_PRODUCT,
:BK_FINAL_LABEL => "",
:BK_VISUAL_METHOD => #book.PRB_VISUAL_METHOD,
:BK_DB => "",
:BK_COVERED_REGION => "",
:BK_VERSION_NO => #book.BK_VERSION_NO,
:BK_SEQ_FILE => "",
)do |primary|
primary.BK_ID = #book.BK_ID
end
end
By saying that the value to be passed is #book.BK_SOURCE || "NONE", if the attribute is nil, then the string NONE is passed instead.
EDIT
hash = {
:BK_SUB_FK => #book.BK_SUB_FK,
:BK_TITLE => #book.BK_TITLE,
:BK_SOURCE => #book.BK_SOURCE,
:BK_PUB => #book.BK_PUB,
:BK_COVER => #book.BK_COVER,
:BK_LABEL_PRODUCT => #book.BK_LABEL_PRODUCT,
:BK_FINAL_LABEL => #book.BK_FINAL_LABEL,
:BK_VISUAL_METHOD => #book.PRB_VISUAL_METHOD,
:BK_DB => #book.BK_DB,
:BK_VERSION_NO => #book.BK_VERSION_NO
}
hash = hash.delete_if { |k, v| v.nil? }
Octopus.using(:shard_B) do
#book_new_live = Book.create(hash)do |primary|
primary.BK_ID = #book.BK_ID
end
end
Give it a try.

Related

Add trailing comma and bracket to Ruby JSON

I need to add commas between my hashes and encapsulate them inside square brackets. Can anyone tell me how?
Here is my code:
namespace :fieldfacts do
desc "Export Topics"
task :export_topics => :environment do
out = []
File.open("public/topics.json","w") do |f|
Topic.all.each do |topic|
api = TopicsService.new()
topic_api = api.get(topic.topic_api_id)
out = {
'id' => topic.id,
'name' => topic.name,
'keywords_list' => topic_api.keywords_list,
'organizations_list' => topic_api.organizations_list,
'social_groups_list' => topic_api.social_groups_list,
'feeds_list' => topic_api.feeds_list,
'articles_list' => topic_api.articles_list,
'people' => topic_api.people
}
f.write(JSON.pretty_generate(out))
end
end
end
end
Here is the output:
{
"id": 3,
"name": "Precision Agriculture",
"keywords_list": null,
"organizations_list": null,
"social_groups_list": null,
"feeds_list": null,
"articles_list": null,
"people": null
}{
"id": 4,
"name": "Backcountry Skiing",
"keywords_list": null,
"organizations_list": null,
"social_groups_list": null,
"feeds_list": null,
"articles_list": null,
"people": null
}
Any help would be appreciated. Thanks!
Your issue here is that you are generating JSON multiple times and then appending it together, rather than generating it once.
Something like this should solve your problem (note the change in location of f.write):
namespace :fieldfacts do
desc "Export Topics"
task :export_topics => :environment do
out = []
File.open("public/topics.json","w") do |f|
Topic.all.each do |topic|
api = TopicsService.new()
topic_api = api.get(topic.topic_api_id)
out << {
'id' => topic.id,
'name' => topic.name,
'keywords_list' => topic_api.keywords_list,
'organizations_list' => topic_api.organizations_list,
'social_groups_list' => topic_api.social_groups_list,
'feeds_list' => topic_api.feeds_list,
'articles_list' => topic_api.articles_list,
'people' => topic_api.people
}
end
f.write(JSON.pretty_generate(out))
end
end
end

add two parameters in Soulmate::Loader

i have two fields in my model and i want add them in Soulmate::Loader:
for example, my "person" model has name and email field. and i want load then in Soulmate:
loader = Soulmate::Loader.new("people")
loader.add("term" => name, "id" => self.id, "data" => {
"link" => Rails.application.routes.url_helpers.person_path(self)
})
i want add name and email in loader.add. but i can't.
def load_into_soulmate
loader = Soulmate::Loader.new("people")
loader.add("term" =>{ name , email }, "id" => self.id, "data" => {
"link" => Rails.application.routes.url_helpers.person_path(self)
})
end
and
def load_into_soulmate
loader = Soulmate::Loader.new("people")
loader.add("term" =>{ "name" => name ,"email" => email }, "id" => self.id, "data" => {
"link" => Rails.application.routes.url_helpers.person_path(self)
})
end
error show when i use Person.find_each(&:save) for add datas to redis:
ArgumentError: ArgumentError
from /var/lib/gems/2.2.0/gems/soulmate-1.1.0/lib/soulmate/loader.rb:31:in `add'
but all is wrong.
I think you have to use aliases.
def load_into_soulmate
loader = Soulmate::Loader.new("people")
loader.add("term" =>"name", "id" => self.id, "aliases" => [email], "data" => {
"link" => Rails.application.routes.url_helpers.person_path(self)
})
end

What is an elegant way of modifying hashes inside an array within a nested hash in Ruby

I would like to transform this
def some_process(k,v)
return "#{v}_#{k}"
end
a_hash = {
"i_love_hashes" => {
"thing" => 20,
"other_thing" => "0",
"yet_another_thing" => "i disagree",
"_peculiar_thing" => [
{"count" => 30,
"name" => "freddie"},
{"count" => 15,
"name" => "johhno"},
{"count" => 12,
"name" => "mohammed"},
]
},
"as_do_i" => {
"thing" => 10,
"other_thing" => "2",
"yet_another_thing" => "i strongly agree",
"_peculiar_thing" => [
{"count" => 10,
"name" => "frodo"},
{"count" => 4,
"name" => "bilbo"},
{"count" => 2,
"name" => "elizabeth"},
]
}
}
into this
{
"i_love_hashes"=>{
"thing"=>20,
"other_thing"=>"0",
"yet_another_thing"=>"i disagree",
"_peculiar_thing"=> [
{"count"=>30, "name"=>"freddie", :sinister_name=>"freddie_i_love_hashes"},
{"count"=>15, "name"=>"johhno", :sinister_name=>"johhno_i_love_hashes"},
{"count"=>12, "name"=>"mohammed", :sinister_name=>"mohammed_i_love_hashes"}
]},
"as_do_i"=>{
"thing"=>10,
"other_thing"=>"2",
"yet_another_thing"=>"i strongly agree",
"_peculiar_thing"=>[
{"count"=>10, "name"=>"frodo", :sinister_name=>"frodo_as_do_i"},
{"count"=>4, "name"=>"bilbo", :sinister_name=>"bilbo_as_do_i"},
{"count"=>2, "name"=>"elizabeth", :sinister_name=>"elizabeth_as_do_i"}
]
}
}
this is the code I am currently using to achieve this
a_hash.each_with_object({}) do |(k,v),o|
o.merge!({k =>
v.each_with_object({}) do |(a,b),g|
g.merge!({ a =>
(b.is_a?(Array) ? b.collect {|x| x.merge({sinister_name: (some_process k, x["name"])})} : b)
})
end
})
end
Ignoring the specific details of what is being returned by "some_process" (what is important is that it depends on the outer most key and the inner name values, in this example), are there any alternatives that would be considered more elegant?
Why not do a recursive function?
def add_siniter(hash)
hash[:siniter_name] = "#{hash['name']}_i_love_hashes"
hash
end
def format_hash(item)
case item
when Hash then item.keys.each{|key| format_hash(item[key])}
when Array then item.map!{|h| add_siniter(h)}
end
end
format_hash(a_hash)

How to send custom parameter from jqgrid to rails controller?

I use jqgrid in my rails to show data in my web
and I want to decide which data to show depends on which page the user is surfing
here's the code
show.html.erb
<%=raw jqgrid("people_list", "people", "/people",
[ { :field => "pid", :label => "pid" ,:editable => true},
{ :field => "name", :label => "name" ,:editable => true},
{ :field => "gender", :label => "gender" ,:editable => true},
{ :field => "birthday", :label => "birthday" ,:editable => true}
] ,
{:autowidth=>true,:add => true,:edit => true,:delete => true,:view => true,:edit_url => post_data_people_url,:sortable_rows => 'true'
}
)%>
people_controller.rb
def index
index_columns ||= [:pid,:name,:gender,:birthday,:school]
current_page = params[:page] ? params[:page].to_i : 1
rows_per_page = params[:rows] ? params[:rows].to_i : 10
conditions={:page => current_page, :per_page => rows_per_page}
conditions[:order] = params["sidx"] + " " + params["sord"] unless (params[:sidx].blank? || params[:sord].blank?)
if params[:_search] == "true"
conditions[:conditions]=filter_by_conditions(index_columns)
end
#temp = Person.limit(0).all
KlassesPeople.where(:klass_id => 1).each do |stu|########
#temp.concat( Person.where(:id => stu.person_id) )
end
#people = #temp.paginate(conditions)
total_entries=#people.total_entries
respond_with(#people) do |format|
format.html
format.json { render :json => #people.to_jqgrid_json(index_columns, current_page, rows_per_page, total_entries)}
end
end
I want to pass the value of klass id from the jqgrid to the controller to determine the value of klass_id in the line with "########"
any idea?
I don't know how to format the code for you but you can use the postData parameter to pass a value to your controler every time the jqGrid would get data.
postData: { KeyName: KeyValue },
If you need to set this value dynamically you can set it via something like:
$('#gridName').jqGrid('setGridParam', { postData: { KeyName: KeyValue });

Why is the order of execution of attribute assignments failing?

I am passing these parameters to a controller:
{
"utf8" => "✓",
"authenticity_token" => "ersjaJ4/ieZelVifP/YpBHTJtiQ53HgO5KYjEdW0BlQ=",
"transaction" => {
"use_balance" => "1",
"traces_attributes" => {
"trace_ids" => ["6"],
"6" => {
"amount" => "12.0",
"charge_id" => "6"
}
},
"positive_balance" => "12",
"property_id" => "2",
"community_id" => "1"
},
"commit" => "Save Payment",
"community_id" => "1",
"property_id" => "2"
}
The controller#create then:
#payment = Transaction.new(params[:transaction])
Then the Transaction model:
belongs_to :property
belongs_to :community
attr_accessible :positive_balance
def traces_attributes=(params)
#INSIDE HERE THE VALUES OF
#params[:trace_ids] => ['6'] OK
#BUT
#self.possitive_balance => "" **NOT OK**
#self.property_id => nil **NOT OK**
end
My hypothesis is that traces_attribute= is executed before positive_balance= and property_id
Can I change this?
Why is this failing?
The order of the assignments should be the same as the order of the params in the form, but I don't think this is guaranteed.
A safer solution would be to only store the data in the traces_attributes= method, and access the other attributes later, for example in a before_save callback.
it looks based on the transaction hash that the property_id is outside of that hash so if you are building based on transactions it won't have a property_id
"transaction"=>{"use_balance"=>"1",
"traces_attributes"=>{"trace_ids"=>["6"],
"6"=>{"amount"=>"12.0",
"charge_id"=>"6"
}
},
"positive_balance"=>"12",
"property_id"=>"2",
"community_id"=>"1"
},
"commit"=>"Save Payment",
"community_id"=>"1",
"property_id"=>"2"}
do you see what i mean, the number of curly braces is messed up and prop. id isn't ending up in transactions ( i just copy and pasted your code pasted above )

Resources