How to append items to an array - ruby-on-rails

I have the following:
myObject = {
id: user.id,
email: user.email,
}
I need to add values like so:
if current_user && current_user.id == user.id
myObject << {
notification_email: user.notification_email,
notification_email2: user.notification_email2
}
end
The code above raises an error.
What's the right way to optionally append values to the object?
ERROR
undefined method `<<' for # Did you mean? <

Perhaps you want Hash#merge.
myObject.merge(
notification_email: user.notification_email,
notification_email2: user.notification_email2
)
If you want side effects, use the banged version.
myObject.merge!(
notification_email: user.notification_email,
notification_email2: user.notification_email2
)

myObject is a hash, so to add new items you can do this:
if current_user && current_user.id == user.id
myObject[:notification_email] = user.notification_email
myObject[:notification_email2] = user.notification_email2
end

Related

updating the database after create action doesn't work

set_bonus(member_id, cookie) method does not work. I'm trying to update the same model that that the self.set_signup_attribution(member_id, cookie, origin) returns.
The new_has_value variable returns {"currency"=>"usd", "type"=>"flat", "amount"=>1000}
Model.rb
# THIS METHOD WORKS
def self.set_signup_attribution(member_id, cookie, origin)
return unless cookie.present?
tracking_code = cookie
attribution_channel = AttributionChannel.find_by tracking_code: tracking_code
associated_member_record = Member.find member_id
if attribution_channel.present?
Attribution.create!({
event: Attribution::SIGN_UP,
attribution_channel: attribution_channel,
associated: associated_member_record,
extra: origin
})
set_bonus(member_id, cookie)
else
Rails.logger.info "Unknown Attribution Channel for tracking code: '#{ tracking_code }'"
end
end
# THIS METHOD DOES NOT WORK. UPDATES THE DATABASE.
def self.set_bonus(member_id, cookie)
epoch = Member.find_by(id: member_id).attribution_epoch
attribution_code = AttributionChannel.find_by(tracking_code: cookie)
duration_value = attribution_code.attribution_duration.downcase.split(' ')
duration = duration_value.first.to_i.send(duration_value.last)
return if cookie.present? && epoch.present?
current_time = Time.now
if attribution_code.bonus_config.present?
if (current_time - epoch).to_i < duration
hash_value = attribution_code.bonus_config
new_hash_value = hash_value.assoc("sign_up")[1]
value = Attribution.where(attribution_channel_id: attribution_code)
if new_hash_value["type"] == "flat"
value.update_all(
bonus_amount: new_hash_value["amount"],
bonus_currency: new_hash_value["currency"]
)
elsif new_hash_value["type"] == "percentage"
value.update_all(
bonus_amount: new_hash_value["amount"],
bonus_currency: new_hash_value["currency"]
)
else
{
bonus_amount: "Doesn't exist",
bonus_currency: "Doesn't exist"
}
end
else
"Do nothing"
end
else
"Do nothing"
end
#cookie = nil
binding.pry
end
Controller.rb
def index
unless session[:just_signed_up]
redirect_back_or_settings_page
end
Attribution.set_signup_attribution(current_user, cookies[:visit_attr], request.referer)
Attribution.set_bonus(current_user, cookies[:visit_attr])
session[:just_signed_up] = false
#email = current_user.email
end
How do I go about this? That is what I have tried and doesn't work. Can I merge set_bonus method to set_signup_attribution method or something?
Any help will be appreciated.
So drilling this further:
I merged set_bonus with set_signup_attribution and the two fields (bonus_amount and bonus_currency) which set_bonus method is supposed to update returns nil:
Attribution.create!(
{
event: Attribution::SIGN_UP,
attribution_channel: attribution_channel,
associated: associated_member_record,
extra: origin
}.merge(self.set_bonus(member_id, cookie).to_h)
)
With this drill after using binding.pry on that set_bonus method, I figured out it worked but it's returning nil and I don't know why. Could it be because member_id is not available in the model or something?
in your if statement you should call set_bonus method on appropriate object.
attribution = Attribution.create!({
event: Attribution::SIGN_UP,
attribution_channel: attribution_channel,
associated: associated_member_record,
extra: origin
})
attribution.set_bonus(member_id, cookie) if attribution.persisted?
Just be careful as .create! will raise an error in case there is something wrong, so maybe would be better to use
attribution = Attribution.new(.....)
if attribution.save
attribution.set_bonus(.....)
else
Rails.logger.info attribution.errors
end
I hope this would help.
Cheers

Setting multiple model attributes at once via loop

Im using virtual attributes to concat and form a address before i save the user. So when they click edit user i would like to populate the fields in the form again. Every time i try to assign them they come back nil?
This is what i call from devise registrations controller before_action edit:
def test
resource.populate_address_attributes
end
and here is the method im trying to work with:
def populate_address_attributes
if address == nil || address == ""
return false
else
attributes = address.split(",")
[self.number, self.street_name, self.area, self.postcode, self.state].each { |x| x = attributes.delete_at[0]}
end
end
all i'm getting is this:
=> [nil, nil, nil, nil, nil]
maybe i'm trying to make it to complicated?
When you are passing [self.number, self.street_name] etc you are passing the value of those attributes (which are nil and hence immutable).
Try this
def populate_address_attributes
if address == nil || address == ""
return false
else
attributes = address.split(",")
[:number, :street_name, :area, :postcode, :state].each_with_index do |field, index|
self.public_send("#{field}=", attributes[index])
end
end
end

Remove white space from params

I have a piece of code which collects params from a form and reads them into invite as I can see. The problem is one of these parameters is an email which I want to ensure has no trailing whitespace. How could I apply strip to invite and all of the params fed into it?
def invite_partner
return unless invite = params[:partner]
return flash.now[:error] = 'Please select a role' unless role = Role.where(klass: invite[:klass], name: 'Admin').first
return flash.now[:alert] = 'Email address already in use' if User.where(email: invite[:email]).first
raise 'bugger' unless current_user.is_a?(User)
partner_invite = PartnerInviteMailer.invite(current_user.operator, invite[:email], invite[:klass], Portal.portal_for_hostname(host_from_request))
partner_invite.deliver
flash.now[:success] = "#{invite[:klass]} invited, email sent to #{invite[:email]}"
end
Does this help?
params[:partner].each { |key, value| value.strip! }
Skip array's like related ids.
params[:partner].each { |key, value| value.strip! unless value.kind_of?(Array) }
You can use the try method, which will handle Arrays, nil values, etc without having to check kind_of?.
params[:partner].each { |key, value| value.try(:strip!) }

undefined method `is_current' for #<ActiveRecord::Relation:0x38622a8> in ruby on rails update data

I'm trying to update some data in database but I'm getting this error:
undefined method `is_current' for #<ActiveRecord::Relation:0x38622a8>
My controller:
#user = User.where("user_id = #{user_id} and is_current = 1")
if #user.nil?
puts"xxxxxxxxxxxxxxxxxxxxxxxxxxx"
else
#user.is_current = 0
#user.to = Time.now
#user.save
end
User.where returns an array. You need to say .first afterwards. Additionally do not use a string in where with out escaping your arguments. Your query is not secure and is open to SQL injection.
#user = User.where(user_id: user_id, is_current: 1).first
try to write query in model, it's good practice, so you can do
#user = User.where("user_id = #{user_id} and is_current = 1")
replace with
#user = User.user_is_current(user_id,1) # two argument 1) user_id and 2) is_current value
in your model
def user_is_current(user_id,is_current)
where(user_id: user_id, is_current: is_current)
end
it will give data in array so you can write
#user = User.user_is_current(user_id,1).first

strange nil object result

I have a module:
module Voteable
def has_up_vote_of user
return ! self.votes.select{|v| v.user.id == user.id && v.value == 1}.empty?
end
def has_down_vote_of user
return ! self.votes.select{|v| v.user.id == user.id && v.value == -1}.empty?
end
end
Which is mixed into a model:
class Comment < ActiveRecord::Base
include Voteable
end
In a controller code, there is a check:
has_up_vote = #voteable.has_up_vote_of #user
has_down_vote = #voteable.has_down_vote_of #user
#voteable and #user are existing model items, found in a DB.
Suppose, voteable item has up-vote of user. After executing the code, has_up_vote will be equal to true, and has_down_vote will be nil.
Why nil, instead of false ?
I have used several variations of methods, but the problem is the same. Even this gives me the same effect:
def has_up_vote_of user
has = self.votes.select{|v| v.user.id == user.id && v.value == 1}.empty?
return !has.nil? && has
end
Posssible, i'm misunderstanding something, but this behavior is strange
Update
I've noticed very strange behaviour.
When i change methods to trivial:
def has_up_vote_of user
return false
end
def has_down_vote_of user
return false
end
They both returns nil, when i debug the app.
But, from console, they returns false.
It's more stange, because i cannot do anything with these results. These code is not working:
has_up_vote = false if has_up_vote.nil?
has_down_vote = false if has_down_vote.nil?
I think that the debugging environment you're running in is interfering with the actual value of has_down_votes. The select method should never return nil as defined.
Instead of !{}.empty? you could use {}.present?
Its more readable and the output will always be true/false only
I know this doesn't get to the root cause of your strange problem, but it should give you the results you want. Instead of
return ! self.votes.select{|v| v.user.id == user.id && v.value == -1}.empty?
try
return !!self.votes.select{|v| v.user.id == user.id && v.value == -1}.any?
The double exclamation point is intentional -- it will cause nil to become false. (!arr.empty? is equivalent to arr.any? which is equivalent to !!arr.any? -- except the last one converts the nil to false)

Resources