How do I get unique elements in this array? - ruby-on-rails

Using Mongoid. Unfortunately, Mongoid does not allow for selecting unique / distinct!
Have gotten these results. As you can see, there are 7 results. If you look carefully (at user_id), there are only 2 users.
[
#<Activity _id: 4cea6c4572357e00fa00011a, created_at: 2010-11-22 13:12:37 UTC, updated_at: 2010-11-22 13:12:37 UTC, action: "Attend", user_id: BSON::ObjectId('4cea2fb872357e00fa000025'), artist_id: nil, media_id: BSON::ObjectId('4cea447472357e00fa00009a')>,
#<Activity _id: 4cea6c3072357e00fa000116, created_at: 2010-11-22 13:12:16 UTC, updated_at: 2010-11-22 13:12:16 UTC, action: "Attend", user_id: BSON::ObjectId('4cea2fb872357e00fa000025'), artist_id: nil, media_id: BSON::ObjectId('4cea447472357e00fa00009a')>,
#<Activity _id: 4cea6bdd72357e00fa00010d, created_at: 2010-11-22 13:10:53 UTC, updated_at: 2010-11-22 13:10:53 UTC, action: "Attend", user_id: BSON::ObjectId('4cea2fb872357e00fa000025'), artist_id: nil, media_id: BSON::ObjectId('4cea447472357e00fa00009a')>,
#<Activity _id: 4cea46df72357e00fa0000a4, created_at: 2010-11-22 10:33:03 UTC, updated_at: 2010-11-22 10:33:03 UTC, action: "Attend", user_id: BSON::ObjectId('4cea2fb872357e00fa000025'), artist_id: nil, media_id: BSON::ObjectId('4cea447472357e00fa00009a')>,
#<Activity _id: 4cea40c572357e00fa00006f, created_at: 2010-11-22 10:07:01 UTC, updated_at: 2010-11-22 10:07:01 UTC, action: "Attend", user_id: BSON::ObjectId('4cea2fb872357e00fa000025'), artist_id: nil, media_id: BSON::ObjectId('4cea3c8b72357e00fa00005e')>,
#<Activity _id: 4cea3ca172357e00fa000062, created_at: 2010-11-22 09:49:21 UTC, updated_at: 2010-11-22 09:49:21 UTC, action: "Attend", user_id: BSON::ObjectId('4cea39b772357e00fa000046'), artist_id: nil, media_id: BSON::ObjectId('4cea3c8b72357e00fa00005e')>,
#<Activity _id: 4cea344a72357e00fa00003f, created_at: 2010-11-22 09:13:46 UTC, updated_at: 2010-11-22 09:13:46 UTC, action: "Attend", user_id: BSON::ObjectId('4cea2fb872357e00fa000025'), artist_id: nil, media_id: BSON::ObjectId('4cea306c72357e00fa000031')>
]
I was looking at this, and was thinking I could do something similar so that my array would now look like this:
[
#<Activity _id: 4cea6c4572357e00fa00011a, created_at: 2010-11-22 13:12:37 UTC, updated_at: 2010-11-22 13:12:37 UTC, action: "Attend", user_id: BSON::ObjectId('4cea2fb872357e00fa000025'), artist_id: nil, media_id: BSON::ObjectId('4cea447472357e00fa00009a')>,
#<Activity _id: 4cea3ca172357e00fa000062, created_at: 2010-11-22 09:49:21 UTC, updated_at: 2010-11-22 09:49:21 UTC, action: "Attend", user_id: BSON::ObjectId('4cea39b772357e00fa000046'), artist_id: nil, media_id: BSON::ObjectId('4cea3c8b72357e00fa00005e')>
]
I'm not concerned which combination of results are extracted. As long as I have unique user_id's in the result set. Anyone know how this can be achieved?

You can just use the method uniq. Assuming your array is ary, call:
ary.uniq{|x| x.user_id}
and this will return a set with unique user_ids.

This should work for you:
Consider Table1 has a column by the name of activity which may have the same value in more than one record. This is how you will extract ONLY the unique entries of activity field within Table1.
#An array of multiple data entries
#table1 = Table1.find(:all)
#extracts **activity** for each entry in the array #table1, and returns only the ones which are unique
#unique_activities = #table1.map{|t| t.activity}.uniq

For those hitting this up in the future, you can now use the Mongoid::Criteria#distinct method from Origin to select only distinct values from the database:
# Requires a Mongoid::Criteria
Attendees.all.distinct(:user_id)
http://mongoid.org/en/mongoid/docs/querying.html (v3.1.0)

Have you looked at this page?
http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct
That might save you some time?
eg
db.addresses.distinct("zip-code");

Instead of using an Array, consider using either a Hash or a Set.
Sets behave similar to an Array, only they contain unique values only, and, under the covers, are built on Hashes. Sets don't retain the order that items are put into them unlike Arrays. Hashes don't retain the order either but can be accessed via a key so you don't have to traverse the hash to find a particular item.
I favor using Hashes. In your application the user_id could be the key and the value would be the entire object. That will automatically remove any duplicates from the hash.
Or, only extract unique values from the database, like John Ballinger suggested.

Errr, it's a bit messy in the view. But I think I've gotten it to work with group (http://mongoid.org/docs/querying/)
Controller
#event_attendees = Activity.only(:user_id).where(:action => 'Attend').order_by(:created_at.desc).group
View
<% #event_attendees.each do |event_attendee| %>
<%= event_attendee['group'].first.user.first_name %>
<% end %>

Related

Rails console output to recreate objects

I accidentally deleted 1000 objects from a database and now trying to recreate these objects. Thankfully I was able to scroll through my console output and find the records. I copy and pasted the console output which is in this (greatly shortened) format:
[#<Assignment id: 276503, school_id: 2091, listing_id: 251572, created_at: "2018-08-30 05:02:36", updated_at: "2018-08-30 05:02:36">, #<Assignment id: 279532, school_id: 1233, listing_id: 252702, created_at: "2018-08-30 06:19:12", updated_at: "2018-08-30 06:19:12">]
#...
I can't get the console to assign this output to a variable so I can figure out how to use this data to recreate the objects in the db:
irb(main):040:0> a = [#<Assignment id: 276503, school_id: 2091, listing_id: 251572, created_at: "2018-08-30 05:02:36", updated_at: "2018-08-30 05:02:36">, #<Assignment id: 279532, school_id: 1233, listing_id: 252702, created_at: "2018-08-30 06:19:12", updated_at: "2018-08-30 06:19:12">]
irb(main):041:1*
Does anyone have ideas how to turn this console output back into objects in my db?
If you have the problems with assigning a huge array to a variable in the console, you can try to use rake task.
array.each do |e|
options = e.split(',')
school_id = options.detect{|i| i.match?(/school_id/)}.split(':').last
listing_id = options.detect{|i| i.match?(/listing_id/)}.split(':').last
Assignment.create(school_id: school_id, listing_id: listing.id)
end
This should work. It is quite consuming, but from another perspective easy and fast.
I would paste that output on sublime or any other text editor and then format
to become something useful...
A bunch of inserts using SQL or just .create() that i would then paste it on the console

How to separate objects based on column value and retrieve and retrieve the first object of each group?

I'm fairly new programming and I can't manage to find the answer for a problem I have. I'm using active record, rails and sqlite3 and I have a model called Unit. The units have several columns category, sold, color, etc. and also a product_code that is unique for each unique combination of values from the previous columns mentioned. What I can't do is separate all the units based on the product_code they have and then retrieve and object(first or any) of each kind. The units also need to have false value in the column sold. I first tried:
Unit.where(sold:false).select(:product_code).distinct
but this only gives me the different codes:
#<ActiveRecord::Relation [#<Unit id: nil, product_code: "MONMJARD327">,
#<Unit id: nil, product_code: "LAPEJARD327">,
#<Unit id: nil, product_code: "ESTXJARD327">,
#<Unit id: nil, product_code: "COSGJARD327">,
#<Unit id: nil, product_code: "BOLAJARD327">,
#<Unit id: nil, product_code: "FUNIJARD327">,
#<Unit id: nil, product_code: "CARMJARD327">,
#<Unit id: nil, product_code: "MOCEJARD327">,
#<Unit id: nil, product_code: "COJGJARD327">,
#<Unit id: nil, product_code: "RELG">, ...]>
The problem is that I need to retrieve the values of the columns for each different group so I can form a table. Then I tried this:
Unit.where(sold:false).group(:product_code)
This worked fine in development:
[#<Unit id: 104, product_code: "BOLAJARD327", sold: false, category_id: 16, remission_id: nil, created_at: "2016-08-23 20:30:13", updated_at: "2016-08-23 20:30:13", fabric_id: 2, color_id: 1, pattern_id: 13, batch_id: nil, profit: nil, date_sold: nil, store_id: nil>,
#<Unit id: 106, product_code: "CARMJARD327", sold: false, category_id: 11, remission_id: nil, created_at: "2016-08-23 20:30:13", updated_at: "2016-08-23 20:30:13", fabric_id: 2, color_id: 1, pattern_id: 13, batch_id: nil, profit: nil, date_sold: nil, store_id: nil>, etc.]
but in development I use PosgresSQL and this generates the ERROR:
PG::GroupingError: ERROR: column "units.id" must appear in the GROUP BY clause or be used in an aggregate function
Is there a better way to do this selection and retrieve the objects as intended?
Thanks in advance!
Not entirely sure I understand what you're trying to do here, but if you want the ActiveRecord relation of unsold Units containing a product code, you can do:
Unit.where(sold: false).select(:product_code)
# which returns
=> #<ActiveRecord::Relation [#<Unit id: nil, product_code: "ESTXJARD327">, #<Unit id: nil, product_code: "BOLAJARD327">]>
To then select the first one you could do something like:
Unit.where(sold: false).select(:product_code).first
If you have multiple Units that have the same product_code you can group them together with:
Unit.where(sold: false).select(:product_code).group(:product_code)
Again, you can select the first entry here by appending .first

Why can't I save two or more siblings with mongoid-tree?

I'm using this engine: https://github.com/opennorth/popolo-engine
As you can see in the model, organization includes Mongoid::Tree.
For whatever reason, I cannot seem to create/save more than one record on a level.
I can have two organisations, one a parent and one a child, but I can't then add a second child. I also cannot have two 'top level' nodes that sit without parents.
Popolo::Organization.create(name:"Org1")
=> #<Popolo::Organization _id: 5405dd09360e2e5421000002, created_at: 2014-09-02 15:06:49 UTC, updated_at: 2014-09-02 15:06:49 UTC, parent_id: nil, parent_ids: [], name: "Org1", classification: nil, founding_date: nil, dissolution_date: nil, image: nil>
Popolo::Organization.create(name:"Org2")
=> #<Popolo::Organization _id: 5405dd0c360e2e5421000003, created_at: 2014-09-02 15:06:52 UTC, updated_at: 2014-09-02 15:06:52 UTC, parent_id: nil, parent_ids: [], name: "Org2", classification: nil, founding_date: nil, dissolution_date: nil, image: nil>
Popolo::Organization.all.size
=> 1
EDIT: This works okay in the test environment.
I restarted my mongodb service and it worked!
sudo rm /var/lib/mongodb/mongod.lock
service mongodb start
Very odd indeed.

Why does ActiveRecord association return two copies of every associated object

I have...
class Report < ActiveRecord::Base
has_and_belongs_to_many :elements
end
class Element < ActiveRecord::Base
has_and_belongs_to_many :reports
end
I'm seeing some very weird behaviour at the command line:
$Element.all
[#<Element id: 1, name: "fdafda", created_at: "2013-03-12 02:10:56", updated_at: "2013-03-12 02:10:56">,
#<Element id: 2, name: "Foo", created_at: "2013-03-14 10:46:56", updated_at: "2013-03-14 10:46:56">,
#<Element id: 3, name: "Bar", created_at: "2013-03-14 10:47:03", updated_at: "2013-03-14 10:47:03">]
$ Report.first.elements
[#<Element id: 2, name: "Foo", created_at: "2013-03-14 10:46:56", updated_at: "2013-03-14 10:46:56">,
#<Element id: 2, name: "Foo", created_at: "2013-03-14 10:46:56", updated_at: "2013-03-14 10:46:56">,
#<Element id: 3, name: "Bar", created_at: "2013-03-14 10:47:03", updated_at: "2013-03-14 10:47:03">,
#<Element id: 3, name: "Bar", created_at: "2013-03-14 10:47:03", updated_at: "2013-03-14 10:47:03">]
(rdb:2) Report.first.elements.uniq
[#<Element id: 2, name: "Foo", created_at: "2013-03-14 10:46:56", updated_at: "2013-03-14 10:46:56">,
#<Element id: 3, name: "Bar", created_at: "2013-03-14 10:47:03", updated_at: "2013-03-14 10:47:03">]
How is the duplication of elements in Report.first.elements even possible? And how can I stop it?
rails -v
Rails 3.2.11
$ ruby -v
ruby 1.9.2p320 (2012-04-20 revision 35421) [x86_64-darwin12.2.1]
Found the answer. Had a report selector in the form at reports/id/elements/new. If the user selected the current report in the report selector, two links between the element and the report would be created in the join table.

Rspec new expectation syntax

I've the following rspec unit test:
require 'spec_helper'
describe Article do
describe ".recents" do
it "includes articles created less than one week ago" do
article = Article.create(created_at: Date.today - 1.week + 1.second)
expect(Article.recents).to eql([article])
end
it "excludes articles published at midnight one week ago" do
article = Article.create!(:created_at => Date.today - 1.week)
expect(Article.recents).to be_empty
end
end
end
and the Articlemodel:
class Article < ActiveRecord::Base
attr_accessible :description, :name, :price, :created_at
scope :recents, where('created_at <= ?', 1.week.ago)
end
when I run my tests I get:
1) Article.recents includes articles created less than one week ago
Failure/Error: expect(Article.recents).to eql([article])
expected: [#<Article id: 60, name: nil, description: nil, price: nil, created_at: "2012-11-14 00:00:01", updated_at: "2012-11-21 10:12:33", section_id: nil>]
got: [#<Article id: 60, name: nil, description: nil, price: nil, created_at: "2012-11-14 00:00:01", updated_at: "2012-11-21 10:12:33", section_id: nil>]
(compared using eql?)
Diff:#<ActiveRecord::Relation:0x007ff692bce158>.==([#<Article id: 60, name: nil, description: nil, price: nil, created_at: "2012-11-14 00:00:01", updated_at: "2012-11-21 10:12:33", section_id: nil>]) returned false even though the diff between #<ActiveRecord::Relation:0x007ff692bce158> and [#<Article id: 60, name: nil, description: nil, price: nil, created_at: "2012-11-14 00:00:01", updated_at: "2012-11-21 10:12:33", section_id: nil>] is empty. Check the implementation of #<ActiveRecord::Relation:0x007ff692bce158>.==.
# ./spec/models/article_spec.rb:7:in `block (3 levels) in <top (required)>'
Could someone please help me to figure out what's the error in my test?
It seems good for me.
You are comparing an activerecord relation (Article.recents) to an array ([article]), which is why the expectation is failing. (It looks like they are the same in the spec results because inspect converts the relation into an array before printing it out.)
Change your first expectation to this:
expect(Article.recents.to_a).to eql([article])

Resources