Rails :: Why the attribute change doesn't persist? - ruby-on-rails

Controller:
#events = Event.all
#events.each { |e| e.user_subscribed = "someuser" }
#events.each { |e| puts "error" + e.user_subscribed }
I have attr_accessor :user_subscribed. but the error is can't convert nil into String as e.user_subscribed evaluates to nil.
I'm using mongoid on the backend.
edit: this works, but it just copies the whole array.
#events = #events.map do |e|
e.user_subscribed = "faaa"
e
end

If you're not saving the #events to the database, user_subscribed won't persist, unless you keep it in memory:
#events_with_subscription = #events.map { |e| e.user_subscribed = "someuser"; return e }

edited based on OP comments.
sounds like it might be better to just output Event.user_subscribed(current_user) directly in the view...but if you wanted to load up all that data before hand you could do:
#array_of_subscription_results = #Events.map{|e| e.user_subscribed(current_user,some,other,var,required) }
As long as user_subscribed returns the values you are interested in, thats what map will load into #array_of_subscription_results

Related

Emptying a PostgreSQL text array column in Ruby on Rails

data = {string1,string2}
The array data is fetched from PostgreSQL database that has a column of type text[] ie text array.
I need to empty this array.
OUTPUT:
data = {}
Can I use
tablename.update_attributes!(data: "")
OR
tablename.data.map!{ |e| e.destroy }
Context:
EMAILS.each do |email|
res = tablename.where('lower(email) = lower(?)',
"#{email}")
res.each do |u|
u.data.map! { |e| e.destroy } // this is where i want to empty the array
end
puts ""
end;
end;
I am very new in Rails. Can someone suggest something I can use?
Please, replace your line of code with this
u.data.map! { |e| e.update(data: []) }
The way to erase an array column is to set an empty array to it: data: []
You can use update_all to update all retrieved records at once:
EMAILS.each do |email|
tablename.where('lower(email) = lower(?)', email).update_all(data: [])
end

Rails does not write column

i have a totally strange problem:
Rails 6.0.0
ruby 2.5.7
mysql 8.0.15
it saves the most columns, but not all.
p.errors.full_messages delivers emtpy array and p.valid? delivers true.
but, p.to_geocode does not be set to true in the database, p.location_string is also not saved.
But, all the values, which are advised by the loop (hash.keys.each {..) are correctly stored.
what may there be?
thanks in advance!
Chris
Code:
def write_project(hash)
# MAKE RECORD
p = Project.new
hash.keys.each {|k| p[k.to_sym] = hash[k.to_sym]}
p.created_by = session[:login_name]
p.group = 'antenna_project'
#default_values.each do |k, v|
unless p[k.to_sym].present?
p[k.to_sym] = v
end
end
p.import_id = #import.id
# ERROR HANDLING SAVE
p[:to_geocode] = true
p.location_string = [hash[:street].to_s, hash[:zip].to_s, hash[:city].to_s, 'switzerland'].reject(&:empty?).join(', ')
unless p.save(validate: false)
e = "COULD NOT SAVE RECORD"
log_import_error(nil, e)
return e
end
#import.block_others_until = (DateTime.now + 1.seconds)
#import.save
return "SUCCESS"
end

Sorting by integers represented as strings

I would like sort array of ActiveRecord objects by related object's attribute value. Meaning something like this:
Item has one product which has an attribute SKU. The SKU is mostly integer stored as a string, but could be alphanumeric as well.
sorted = items.sort_by { |item| Integer(item.product.sku) } rescue items
For now in case of error the items with original order returns.
What would I like to do?
Extend the Array class to achieve something like:
items.numeric_sort { |item| item.product.sku }
What I did so far?
1. Building a lambda expression and passing it
class Array
def numeric_sort(&lambda)
if lambda.respond_to? :call
self.sort_by(&lambda) rescue self
else
self.sort_by { |el| Integer(el) } rescue self
end
end
end
product_bin = lambda { |task_item| Integer(item.product.bin) }
items.numeric_sort(&product_bin)
2. Building lambda expression from methods chain
class Object
def send_chain(keys)
keys.inject(self, :send)
end
end
class Array
def numeric_sort_by(*args)
(args.length == 1) ? lam = lambda {|el| Integer(el.send(args))} : lam = lambda {|el| Integer(el.send_chain(args))}
self.sort_by(&lam) rescue self
end
end
items.numeric_sort_by(:product, :sku)
Is it all makes any sense?
Can you please point me in the right direction to implement the syntax I mentioned above, if it is possible at all.
Thanks.
EDIT: the sku could be alphanumeric as well. Sorry for the confusion.
Try this solution.
There is no error handling.
It's just an idea to develop if you like it.
class Array
def numeric_sort_by(*args)
self.sort_by do |element|
object = element
args.size.times { |n| object = object.send(args[n]) }
object.to_f
end
end
end
items.numeric_sort_by 'product', 'sku'
So the straightforward implementation was:
sorted = items.sort_by { |item| Integer(item.product.sku) } rescue items
And the desired was:
items.numeric_sort_by { |item| item.product.sku }
I was manage to achieve it by yielding a block into the sort_by:
class Array
def numeric_sort_by(&block)
return to_enum :numeric_sort_by unless block_given?
self.sort_by { |element| Integer(yield(element)) } rescue self
end
end

Rails no implicit conversion of Symbol into Integer(rails)

I am trying to save a data inside bookmark variable but it's throwing an error which is described in the title.Please Tell me what am I doing wrong I can't understand the error.
bookmarks = Bookmark.where(request_id: bookmarked_against_Request[:_id])
if bookmarks
bookmarks[:corsponding_requests] << request_bookmarked[:id]
else
bookmarks_new = Hash.new
bookmarks["owner_req"] = session[:user]
bookmarks["request_id"] = data
bookmarks["corsponding_requests"] = Array.new
bookmarks["corsponding_requests"] << request_bookmarked[:_id]
Bookmark.createBookmark(bookmarks)
end
PS:- I HAVE CHANGED BOOKMARKS TO BOOKMARKS_NEW IN THE ELSE BLOCK BUT IT STILL THROWING THE SAME ERROR
Try this:
bookmarks = Bookmark.where(request_id: bookmarked_against_Request[:_id])
if bookmarks
bookmarks.each { |bookmark| bookmark.update_attributes(corsponding_requests: request_bookmarked[:id] }
else
bookmark = Hash.new
bookmark["owner_req"] = session[:user]
bookmark["request_id"] = data
bookmark["corsponding_requests"] = Array.new
bookmark["corsponding_requests"] << request_bookmarked[:_id]
Bookmark.createBookmark(bookmark)
end
You can imagine bookmarks like array, and when you try bookmarks[:corsponding_requests] ruby "think", that you want acces to array element through integer index (for example like bookmarks[1]) but it can't convert symbol to integer and throw an error. Maybe, it helps you...

Order model objects by an attr_accessor

I thought that attr_accessor has the same behavior as the other when I have to sort a list of objects, but it seems that is different:
dataRecords = MyData.where("day = ?", Time.now.yesterday.strftime("%Y%m%d").to_i)
dataRecords.each do |data|
data.accessor_var = func(data.x, data.y)
end
#sortedData = dataRecords.order('accessor_var DESC')
but #sortedData is not being sorted...
You need to keep in mind that when you apply a scope or order to an ActiveRecord::Relation the data is reloaded from the table. This means that when you loop through them and change an attribute, unless you save the result the changes will not be available to the next scope call.
You can use sort_by instead which will work on the objects in memory rather than the database.
Option 1: Save as you loop (probably not much use with an accessor!)
dataRecords = MyData.where("day = ?", Time.now.yesterday.strftime("%Y%m%d").to_i)
dataRecords.each do |data|
data.accessor_var = func(data.x, data.y)
data.save
end
#sortedData = dataRecords.order('accessor_var DESC') # Reload from table will include the saved values.
Option 2: sort_by
dataRecords = MyData.where("day = ?", Time.now.yesterday.strftime("%Y%m%d").to_i)
dataRecords.each do |data|
data.accessor_var = func(data.x, data.y)
end
#sortedData = dataRecords.sort_by{|data| data.accessor_var}
Also, toro2k has some nice optimisation for your sorting once you understand the situation.
It doesn't work because accessor_var is not a column in the database. You can use the method sort_by:
dataRecords.each { ... }
#sortedData = dataRecords.sort_by(&:accessor_var).reverse
Or, to save an interation over dataRecords:
#sortedData = dataRecords.sort_by { |data| data.accessor_var = func(data.x, data.y) }.reverse

Resources