How to parse a Mash from LinkedIn to create a Ruby object - ruby-on-rails

I used LinkedIn gem by pengwynn to get authentication from LinkedIn. Everything works fine, and I get a Mash in a callback that looks like this:
#<LinkedIn::Mash all=[#<LinkedIn::Mash company=#<LinkedIn::Mash id=1422 industry="Banking"
name="Company" size="10,001+ employees" ticker="ABC" type="Public Company"> id=2851554
is_current=true start_date=#<LinkedIn::Mash month=12 year=2008> summary="" title="Boss">] total=1>
How can I parse it to something similar to Rails params in order to create a new object from it?
Thank you.

When you receive list of connections of any sort from LinkedIn, you need to get to the list from all. On the object you received from LinkedIn, you have {all, total}. total will give you the number of objects in the array, all will give you all of the objects. So if you wanted to turn the first company into a hash, you would call object.all.first.to_hash. You can iterate through all of them by doing object.all.each {|c| # your block}.
If your own Rails models match the objects being returned from the linkedin gem, you can do:
companies.all.each do |company|
Company.create(company.to_hash)
end
If they don't map 1:1, you can just choose the fields you want:
companies.all.each do |company|
c = Company.new
c.name = company.name
c.year_founded = company.start_date.year
c.ticker = company.ticker
# etc. etc. etc.
c.save
end

You can just call .to_hash to turn a Mash into a Hash (like params).
Source:
https://github.com/intridea/hashie/blob/master/lib/hashie/hash.rb

Related

Fetch ActiveRecord query result as an array of hashes with chosen attributes

The model User has first, last and login as attributes. It also has a method called name that joins first and last.
What I want is to iterate through the Users records and create an array of hashes with the attributes I want. Like so:
results = []
User.all.map do |user|
record = {}
record["login"] = user.login
record["name"] = user.name
results << record
end
Is there a cleaner way in Ruby to do this?
Trying to map over User.all is going to cause performance issues (later, if not now). To avoid instantiating all User objects, you can use pluck to get the data directly out of the DB and then map it.
results = User.all.pluck(:login, :first, :last).map do |login, first, last|
{ 'login' => login, 'name' => first << last }
end
Instantiating all the users is going to be problematic. Even the as_json relation method is going to do that. It may even be a problem using this method, depending on how many users there are.
Also, this assumes that User#name really just does first + last. If it's different, you can change the logic in the block.
You can use ActiveRecord::QueryMethods#select and ActiveRecord::Relation#as_json:
User.select(:login, '(first || last) as name').as_json(except: :id)
I would write:
results = User.all.map { |u| { login: u.login, name: u.name } }
The poorly named and poorly documented method ActiveRecord::Result#to_hash does what you want, I think.
User.select(:login, :name).to_hash
Poorly named because it does in fact return an array of Hash, which seems pretty poor form for a method named to_hash.

How to check if text contains an #username? - Rails

In my create action in the comments controller I want to check if the comment text contains a "# + username" so I can add it to my public activities.
if #comment.body.include?(' [HERE] ')
maybe User.all.username.any? ?
You better use ruby regex to first find the user name from comment body matching pattern #abc and then user that username query database to find user
#comment.body.scan(/#(\w+)/).flatten.to_a.each do|username|
if User.where(:username => username).any?
# your code here
end
end
or search the users with single database query by passing the array
usernames = #comment.body.scan(/#(\w+)/).flatten.to_a
if User.where(:username => usernames).any?
# your code here
end
This will optimize the db query and will not load all users to memory.
A quick answer:
if User.pluck(:username).any? {|u| #comment.body.include?("##{u}")}
# ...
end
A better answer:
Why not use a javascript library to auto-complete the username? This is more user friendly, and scales better as the User table grows.

Ruby - how to create dynamic model attributes?

I have an array with model attributes (these model attributes are columns in DB table). I am trying to iterate through this array and automatically create a record which I would like to save to DB table, something like this:
columns.each_with_index do |c, i|
user.c = data[i]
puts user.c
end
user is model.
But if I try the snippet above, I get
undefined method `c=' for #<User:0x007f8164d1bb80>
I've tried also
columns.each_with_index do |c, i|
user."#{c}" = data[i]
puts user."#{c}"
end
But this doesn't work as well.
Data in columns array are taken from form that sends user, so I want to save only data that he send me, but I still cannot figure it out...
I would like to ask you for help... thank you in advance!
user.send("#{c}=".to_sym, data[i])
Also, you can access the attributes as a hash.
user.attributes[c] = data[i]
The best thing would probably be to build a hash and to use update_attributes:
mydata = {}
columns.each_with_index{|c, i| mydata[c] = data[i]}
user.update_attributes(mydata)
this way you retain the protections provided by attr_accessible.
If this is actually in a controller, you can just make use of some basic rails conventions and build the User record like this:
#user = User.new(params[:user])
if #user.save
# do something
else
# render the form again
end
Although you can set the values using send, I agree with #DaveS that you probably want to protect yourself via attr_accessibles. If your planning to use Rails 4, here's a good overview.

Rails/Ruby. Searching for double emails

I am developing an API in Rails 3.
Lately I have seen some user accounts being double. I am not sure how many so I need a way to find out which accounts that are double.
Is there a way, in ruby, to search the entire database and fetch those user accounts that got the same email address (hence double)?
Thankful for all input!
Just open the Rails console (rails c) and type something like this:
Account.group(:email).having('count_all > 1').count
This will return a Hash with email addresses being the key and the number of times it occured as the value. The result will look something like this:
=> #<OrderedHash {"billyjoe#example.com"=>2, "johndoe#example.com"=>2}>
Then, I guess you could take those email addresses and actually get the accounts:
Account.where(:email => "billyjoe#example.com")
To output them all in the console, you could combine both of those like this:
email_hash = Account.group(:email).having('count_all > 1').count
email_hash.each do |email, count|
Account.where(:email => email).each do |account|
p account
end
end
I think if you try to use(for example):
UserAccount.all.group_by(&:email_address).each do |email, record|
#you will get a set of records grouped by email address
end
this will help you (You did not write detailed description of your models but if think you will get the clue)

How to column sort using will_paginate where the data is a record array, not a model

I have a service I query and I get data I filter through and create a an array of records.
Unless I missed something, ActiveResource::Base does not qualify since the access to the service is not via rest and I can't use the raw data as delivered.
I am displaying the data in a table and use will_paginate to page the data. But I am not currently married to will_paginate.
I do need to sort the columns as well as paginate.
I have found two version of ujs_sort_helper.
https://github.com/pengwynn/ujs_sort_helper
https://github.com/sikachu/ujs_sort_helper
I am trying to understand:
- http://javathehutt.blogspot.com/2009/06/mo-simple-sortable-tables-in-rails.html
What have other done in rails 3? Or is one of the ujs_sort_helper packages just he correct way to go.
In term of data refresh, this is a dashbaord. Multiple data source will address the various DIVs.
Also, I am a Rails noob. But not a programming noob.
You could use meta_search's sort_link if you wish.
I like it because it also does filtering incredibly easy with meta_where.
You can also make the behavior through ajax by adding the data-remote attribute to 'a.sort_link' (i have done that through javascript).
I would welcome the maintainer of ujs_sort_helper to comment. Just a bug here and there in the rails 3 version of the code. Now ujs_sort_helper works, for me.
What I have not done is create ANOTHER branch on this package. I emailed the file to the author.
sort order now compares symbols, instead of symbol to string.
def sort_order(column, initial_order='asc')
#safe since to_sm on a sym is a nil operation. At least for now.
if session[#sort_name][:key].to_sym == column.to_sym
session[#sort_name][:order].downcase == 'asc' ? 'desc' : 'asc'
else
initial_order
end
end
The icon us set via the current order value. The sort clause should be the opposite. So show down arrow for the list being displayed in ascending order, but the 'url' is set to redisplay the table in descending order.
I have no clue what the :q symbol is supposed to be used for.
def sort_header_tag(column, options = {})
options[:initial_order].nil? ? initial_order = "asc" : initial_order = options[:initial_order]
key = session[#sort_name][:key].to_sym
order = sort_order(column, initial_order)
caption = options.delete(:caption) || column.to_s.titleize
url = { :sort_key => column, :sort_order => order, :filter => params[:filter]}
url.merge!({:q => params[:q]}) unless params[:q].nil?
content_tag('th', link_to(caption, url, :class=>session[#sort_name][:order] ), :class => "sort_link #{order if key == column}")
end

Resources