Method to order list with dependancies - ruby-on-rails

Conditions: Have to use web based solution (HTML/CSS), Have to use Ruby on Rails, no use of database.
Imagine we have a list of jobs, each represented by a character. Because certain jobs must be done before others, a job may have a dependency on another job. For example, a may depend on b, meaning the final sequence of jobs should place b before a. If a has no dependency, the position of a in the final sequence does not matter. These jobs would be input with a simple text box (also how does one store multiple variables)
Given the following job structure:
a =>
b =>
c =>
The result should be a sequence containing all three jobs abc in no significant order.
Given the following job structure:
a =>
b => c
c => f
d => a
e => b
f =>
The result should be a sequence that positions f before c, c before b, b before e and a before d containing all six jobs abcdef.
Given the following job structure:
a =>
b => c
c => f
d => a
e =>
f => b
The result should be an error stating that jobs can’t have circular dependencies.

This should work:
module JobDependenciesResolver
def self.organize(dependencies)
unresolved_dependencies = dependencies.dup
sorted_jobs = []
until unresolved_dependencies.empty? do
doable_jobs = get_doable_jobs unresolved_dependencies, sorted_jobs
raise Exception.new("Not able to resolve dependencies") if doable_jobs.empty?
sorted_jobs += doable_jobs
unresolved_dependencies.delete_if {|key,value| sorted_jobs.include? key}
end
sorted_jobs
end
private
def self.get_doable_jobs(dependencies, job_array)
dependencies.select {|job, dependency| ([*dependency]-job_array).empty? }.keys
end
end

Related

How can I get the number of instances of a tag element with "id='foo'" using Watir?

How can I get the number of instances of a tag element with id='foo' using Watir?
I have this:
b = Watir::Browser.new
b.a(:id => 'foo')
How then do I get the number of instances and access via an index, like this:
b.a(:id => 'foo', :index => $i) #Here, $i is a variable in a loop
In pseudocode I'm essentially trying to do this:
num = "number of a tags with id foo"
while $i less than num do
put b.a(:id => 'foo', :index => $i).text into an array
end
I know how to do everything above EXCEPT finding num.
If you want to know how many matches there are, you need to get an element collection (not just an element). A collection is retrieved by pluralizing the element method - ie as.
b.as(:id => 'foo')
#=> <Watir::AnchorCollection>
From the collection, you can use length (or count) to find the number of instances:
b.as(:id => 'foo').length
Note that the element collection is Enumerable. This means you do not need to use a while loop and manual track the current index and total elements. For example, using each, you can simply write:
b.as(:id => 'foo').each do |a|
puts a.text
end
Below code should work for you:
arr = Array.new
b.as(:id => 'foo').each { |a| arr.push a}

Memory cleanup after active record destroy

Context:
Category has many Products and dependent destroy is set in Category model for products.
First Case:
c = Category.last
c.destroy
c => record persists as expected because it is already loaded in c variable
Second Case:
p = Category.last.products
Category.last.destory
p => records persisted as expected in p variable as already loaded in this.
Third Case:
c = Category.last
p = c.products
c.destroy
p => [] .. Why??
c => record persisted as expected in c variable
In third case, Why i am getting blank array for p variable ?
Refer SS.doubt_file

Match an element of an array to a different element in that array

I have an array containing several students. I want them to cross-grade one another randomly, i.e. each student will grade someone and will be graded by someone else (these two people may or may not be the same person).
Here is my close to working solution. One big problem with this code is that the last person may have to grade himself if everyone else has been matched.
I am very interested in a working and more elegant solution.
def randomize(student_array)
graders = student_array.dup
gradees = student_array.dup
result = {}
graders.each do |grader|
gradee = grader
while gradee == grader
gradee = gradees.sample
end
result[grader] = gradee
gradees.delete_at(gradees.index(gradee))
end
return result
end
If you don't have to pick up one from all possibilities but pick up a random case from limited cases, then it is easy. For example, the following will give a match:
student_array = %i[a b c d e]
a = student_array.shuffle
[a, a.rotate(1)].transpose.to_h
# => {:b => :e, :e => :d, :d => :a, :a => :c, :c => :b}

Use Proc as a key for caching

I am trying to cache rails request to an external service which takes a proc.
For me to be able to differentiate 2 requests, its important that the proc is part of the Rails cache key.
However multiple requests with the same proc and the values in the proc code, would still evaluate to a different proc object each time.
Eg:
#<Proc:0x007ff6f675dd08#/Users/app/development/work/runner.rb:10>
#<Proc:0x007ff6ffb50790#/Users/app/development/work/runner.rb:10>
Hence , I get cache miss even for same requests.
How do I use the block/proc in the cache key that evaluates to same if the procs are same in terms of code and variable values.
The service call is something like
def some_method
call_service do
a= 3;
b=6
end
end
def call_service(block)
Rails.cache.fetch(Date.today, block) {
external_service(&block)
}
end
I want to be able to compare blocks :
eg
{a=3, a*a} == {a=3, a*a} => True
{a=3, a*a} == {a=4, a*a} => false
{a=3, a*a} == {a=4, a*a*a} => False
I tried to use,
block.source
RubyVM::InstructionSequence.of(block).disasm
But none of them captures the state of the block, i.e the values of the variables (a=3 etc)
What the best way to achieve this type of caching in rails ?
P.S:
Using Rails4 and reddis as the cache
Each time you define an inline block with do ... end you will get a different Proc object. You will have to go out of your way to be absolutely certain you're sending through exactly the same Proc:
def some_method
#my_call ||= lambda {
a = 3
b = 6
}
call_service(&#my_call)
end
This is probably a bad idea from the outset. What you'd be better off doing is passing in a cache key:
call_service("3/6") do
# ...
end
Then you cache against this consistent key, not the arbitrary Proc.
You might get some mileage this way. This function returns a simple Proc object. The object will have a source location and a binding that contains the state of arguments a, b and c when the Proc was built.
def build_proc(a, b, c)
Proc.new { puts "I was built with params #{a} #{b} #{c}!" }
end
So we can build our Proc objects--
2.0.0-p195 :121 > p1 = build_proc(1, 2, 3)
=> #<Proc:0x98849e8#(irb):118>
2.0.0-p195 :122 > p2 = build_proc(2, 4, 6)
=> #<Proc:0x985e57c#(irb):118>
To get the state of an argument you can call binding.eval('argument') against a Proc object. This runs code in the context of that Proc's binding. So you can say--
p1.binding.eval('[a, b, c]') == p2.binding.eval('[a, b, c]')
2.0.0-p195 :127 > p1.binding.eval('[a, b, c]') == p2.binding.eval('[a, b, c]')
=> false
2.0.0-p195 :128 > p2 = build_proc(1, 2, 3)
=> #<Proc:0x97ae4b0#(irb):118>
2.0.0-p195 :129 > p1.binding.eval('[a, b, c]') == p2.binding.eval('[a, b, c]')
=> true
And obviously you can compare source locations--
p1.source_location == p2.source_location &&
p1.binding.eval('[a, b, c]') == p2.binding.eval('[a, b, c]')
You'd need a way to extract the arguments out of the binding in a universal way and you'd want to combine their hashes rather than build an array for comparison (e.g. 'a.hash ^ b.hash ^ c.hash').
This does feel horrible though! At the very least, overriding :== on Procs is probably a bad idea.

Looking for better logical XOR solution with strings

I'm writing some code to evaluate the presence of a bunch of strings, and I want to ensure that only 1 is present. They're mutually exclusive.
class MyClass
include ActiveModel::Validations
attr_accessor :a, :b, :c
validate :mutex_values
def initialize(attr = {})
attr.each do |k, v|
send("#{k}=", v)
end
end
private
def mutex_values
# here, I want to do this:
# errors.add(:base, "specify only 1") unless a ^ b ^ c
# instead I do this
errors.add(:base, "specify only 1") unless a.present? ^ b.present? ^ c.present?
end
end
MyClass.new(:a => "A", :b => "B", :c => "C").valid?
=> false
Is there another way that doesn't require repetitive use of the .present?? Monkey patch String to define an operator ^? I'm just so used to being able to do if a that it feels unnatural to need what is basically an explicit cast to boolean. I feel like this use case would 'just work' in Ruby.
Enumerable actually defines a one? method which does exactly what you need.
# So either...
[a, b, c].one?(&:present?)
# or
[a, b, c].one?(&:presence)
# ... would do the trick in this case.
Unfortunately if you want two? or etcera, you're out of luck.
You could do something like this with count:
errors.add(:base 'specify exactly 1') unless [a, b, c].count(&:present?) == 1
If you want at most one instead of exactly one, then:
errors.add(:base 'specify at most 1') unless [a, b, c].count(&:present?) > 1
For example:
> ['',nil,'6',''].count(&:present?)
=> 1
> ['',nil,'6',11].count(&:present?)
=> 2
> ['',nil,''].count(&:present?)
=> 0
If you want to check whether exactly one of methods a, b, and c returns non-null value, you can use:
[a, b, c].compact.count == 1
or even, thanks to numbers,
[a, b, c].one?

Resources