How do I get only unique results from two dissimilar arrays? - ruby-on-rails

This might seem like a duplicate question, but I can't find any information on this. I want to show the results from a remotely acquired json array excluding certain results by comparing them to a local table. I have a gallery model with:
t.integer :smugmug_id
t.string :smugmug_key
t.integer :category_id
t.string :category_name
t.string :description
t.integer :highlight_id
t.string :highlight_key
t.string :highlight_type
t.string :keywords
t.string :nicename
t.integer :subcategory_id
t.string :subcategory_name
t.string :title
t.string :url
The data for this model gets populated by a rake task that connects to the smugmug api (json) and stores the data locally. I'm trying to create a view that shows all the smugmug galleries that are not stored locally.
Here's what I've tried so far, but it's not excluding the locally stored galleries like I thought it would.
def self.not_stored
smugmug_list = Smug::Client.new.albums(heavy = true)
gallery_list = Gallery.select(:smugmug_id)
smugmug_list.each do |smugmug|
smugmug unless gallery_list.include? smugmug.id
end
end
Hopefully this makes sense. I'm getting a json array of galleries, and I want to display that array excluding results where the album id matches the smugmug_id of any of my locally stored records.
Quick edit: I'm using an adaptation of this gem to connect to the smugmug api.

Just use the difference operator.
General Example:
ruby-1.9.2-p136 :001 > [3,2,1] - [2,1]
=> [3]
So you would have:
smugmug_list.collect{|e| e.id} - gallery_list
Enumerable#collect will turn the smugmug_list into a list of id's. From there, you can do the difference operator, which will return all the id's of all the smugmug galleries that are not stored locally.
Another option to maintain the list of galleries:
smugmug_list.select{|e|!gallery_list.include?(e.id)}

Related

Creating a filter for active record in rails

Just started coding in Ruby on Rails and have managed to create the basic CRUD functionality for my app.
I can also list them all.
Now I would like to create a filter for the user to interact with.
Database Schema
create_table "nades", force: :cascade do |t|
t.string "title"
t.integer "grenade"
t.text "description"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "map_id"
end
The "grenade" can have a value from 1-4, corresponding to a specific grenade:
[[1,"smoke"], [2,"flash"], [3,"molotov"], [4,"he-grande"]
Now I'm trying to create a filter with 4 buttons in the view. Where you can toggle each nade on/off to show or hide them in the results.
[x]Smoke [ ]Flash [ ]Moltov [x]HE
This should only return the nades where grenade = [1,4]
After some reading it looks like scoped would be nice to use to manage this.
However I'm not sure how to make it work as I want.
Was thinking of doing something like:
scope :by_nade, -> grenade { where(grenade: grenade) if status.grenade? }
However this only allows me to get 1 specific nade type from the database.
Is it posible to send multiple parameters like:
http://localhost:3000/nades/?by_nade=1,2 ??
Or is it a better solution to my problem?
Look into creating a form with an array of options (e.g., here). That will allow you to get multiple values for the specific type of grenade.
Your scope will work with either a single id or an array of ids and using the array of options approach should yield an array that will work. In your example above it would effectively be Nade.by_grenade([1,4]). You might want to guard against the array being empty (assuming that an empty list would be a bad thing).

Permutating an existing array to seed a Rails database

I would like to seed my Rails app database with the permutation of an existing array of objects, and am unsure about the best way to go about this.
I currently have a Country model, with the following attributes:
create_table :countries do |t|
t.string :name
t.float :latitude_dec
t.float :longitude_dec
t.timestamps null: false
end
I have seeded this model from a .yaml file (as these attributes are static), and now would like to use these records to seed a CountryPair model (where the attributes are also static). This model will have the following attributes:
create_table :country_pairs do |t|
t.string :country_a
t.string :country_b
t.string :pair_name
t.float :country_a_latitude_dec
t.float :country_b_latitude_dec
t.float :country_a_longitude_dec
t.float :country_b_longitude_dec
t.float :distance
t.timestamps null: false
end
The aim is to permutate the array of Country objects, and create a CountryPair object from each permutation (and seed the database with the output). I understand the Ruby array#permutation method, but am unsure about how to pull out the appropriate values into the new array of CountryPair objects. The order of countries in the pair is important here, so I'd like to use permutations rather than combinations.
Ultimately, I'd also like to calculate the distance between the country pairs, but I'm hoping to start figuring that out once I have the CountryPair model filled!!
This is my first foray back into Rails after a five year absence, so apologies if I've got some of the terminology/methodology wrong - please do ask for clarification if any further information is required! Thanks in advance!
You can add this snippet to your seeds.rb after the Countries are seeded.
Country.all.permutation(2) do |p|
CountryPair.create(
country_a: p[0].name,
country_b: p[1].name,
pair_name: p[0]name + p[1].name,
country_a_latitude_dec: p[0].latitude.dec,
country_b_latitude_dec: p[1].latitude.dec,
country_a_longitude_dec: p[0].longitude.dec,
country_b_longitude_dec: p[1].longitude.dec,
distance: # An algorithm to calculate distance
)
end
Then run it with: rake db:setup

How to select objects based on their enum value and then sum another field belonging to the object collection in Rails

So, I'm using Rails 4, and I have an enum column on my "Sales_Opportunity" object called pipeline_status - this enables me to move it through a sales pipeline (e.g. New Lead, Qualified Lead, Closed deal etc). This all works fine. I'm able to find the number of sales_opportunities that a company has by status through using the following:
<%= #company.sales_opportunities.where(pipeline_status: 3).count %>
This all works fine. What I want to do is to find all sales_opportunities that have the pipeline_status of "closed_won" (enum value of 4 in my app) and sum the value of each won deal (so I can represent the total value of the customer based on the deals that are won in the system). A Sales_Opportunity in my model has a sale_value field, so I tried:
<%= #company.sales_opportunities.where(pipeline_status: 4).each.sale_value.sum %>
which returns the following error:
undefined method `sale_value' for #<Enumerator:0x007f9b87a9d128>
This is probably a trivial error but I can't for the life of me figure out what's going on. Is there where statement returning the enumerator or the sales_opportunity objects with that enumerator? Any help would be gratefully appreciated.
If it helps here are the fields in my sales_opportunities table:
create_table "sales_opportunities", force: true do |t|
t.datetime "close_date"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "pipeline_status", default: 0
t.string "opportunity_name"
t.integer "company_id"
t.decimal "sale_value", precision: 15, scale: 2, default: 0.0
end
A Sales_opportunity belongs_to a Company Object and a User Object, if that makes any difference.
use aggregate function sum
<%= #company.sales_opportunities.where(pipeline_status: 4).sum(:sale_value) %>
Other possibility is to use
<%= #company.sales_opportunities.where(pipeline_status: 4).pluck(:sale_value).reduce(0, :+) %>

How to detect whether a delayed job is currently working?

I have a form through which I am uploading images. The workflow is, that I will upload and save an image and then I run a delayed job, that will take this image and will create from it 3 thumbs.
When I refresh the page, I usually see that the thumbs are not created yet, but after a while (10-15 seconds) are the thumbs ready.
But this is not very friendly - I would like to show to a user that his thumb is in progress of creating, but how to do that?
The structure of the delayed_jobs table is like this:
create_table "delayed_jobs", :force => true do |t|
t.integer "priority", :default => 0, :null => false
t.integer "attempts", :default => 0, :null => false
t.text "handler", :null => false
t.text "last_error"
t.datetime "run_at"
t.datetime "locked_at"
t.datetime "failed_at"
t.string "locked_by"
t.string "queue"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
I think the way to go could be to add to this table a column, like photo_id and simply if the respective row would be missing in this table, then I would know that the thumb is ready. Otherwise is in a queue/in progress of creating.
But how to save into this table this extra column? When I call the delay method, it's just like this:
#user.delay.activate!(#device)
How to pass there an ID of a photo?
Thanks
Rather than storing the photo_id in the delayed_jobs table, you can store the job id in the photos (or users) table. For this you'll need to write a Job class like so:
class PhotoThumbnailJob < Struct.new(:user_id)
def perform
# generate the thumbnail
end
end
Then get a reference to the job instance like this:
job = Delayed::Job.enqueue(PhotoThumbnailJob.new(#user.id))
#user.thumbnail_job_id = job.id
Now as long as you have the #user you can get the job. That way you can tell whether it failed or simply hasn't finished yet, and if it failed you can report on the reason, etc.
Note that if you do this, you might want to create a foreign key constraint on thumbnail_job_id and tell it to null that column when the job is deleted, because by default DJ will delete successful jobs from the delayed_jobs table.
I had a need for a similar capability in an application I built. The approach I took was to use WebSockets to send status updates to the user as my DelayedJob jobs progress. I used Pusher because the API is straightforward and it was free for us, but any implementation, including your own, would do.
Otherwise, I would stay very far way from altering the table and instead utilize the various hooks DelayedJob provides to enable a callback capability for you to take whatever action you prefer at various stages of the job.

globalize2 problem

I have strange globalize2 problem. I'm trying to use globalize 2 and acts_as_textiled and acts_as_commentable. For example - lets we have Post model, that acts_as_commentable. From console
p = Post.find 1
c = p.comments.find 1
works fine, but in browser - nothing displayed
Similar, when Post contains
acts_as_textiled :body
from console body is containing correct data, but in browser i see nothing :(
Any ideas how to correct it?
Upd: "nothing displayed" means,
that for code like
class Post < ActiveRecord::Base
translates :title, :body
acts_as_textiled :body
end
on access to Post.body i've got nil, but on disabled globalize2 or
acts_as_textiled body returns his value. I've tried with different
locales - the same result.
Have you performed the necessary migrations? For localised content you should remove the localised fields in the main table (posts) and create a table for the localisations, like this:
create_table "post_translations", :force => true do |t|
t.string "locale"
t.integer "product_id"
t.string "title"
t.text "body"
end
Just guessing here :)

Resources