Find the 5 longest names in ActiveRecord - activerecord

Let's say I have an articles table with thousands of articles. I am trying to figure out the most performant way to find the 5 longest article names, not the articles themselves.
This is what I have so far:
def self.five_longest_article_names
limit(5).order("(LENGTH(name)) desc").pluck(:name)
end
But that uses SQL. Is there an ActiveRecord query that I could have performed instead?

YourModel.limit(5).order("CHAR_LENGTH(name) desc").pluck(:name)
So, your method becomes:
def self.five_longest_article_names
limit(5).order("CHAR_LENGTH(name) desc").pluck(:name)
end
You could defintely use Arel, but Arels are good for complex queries. In your case, this is a simple usecase, and I think it's better to use SQL in this particular case.

You can always create your own name function for arel:
my_length = Arel::Nodes::NamedFunction.new('LENGTH', YourModel.table[:name])
YourModel.order(Arel::Nodes::Descending.new(my_length)).limit(5)
# or
YourModel.order("#{my_length.to_sql} DESC").limit(5)
I'd suggest you pass it as a named scope to your model and concatenate calls from there.

Related

Is there a way to use a dynamic function name in Elixir from string interpolation like in Ruby?

I want to be able to construct a function call from a string in elixir. Is this possible? The equivalent ruby method call would be:
"uppercase".send("u#{:pcase}")
Although the answer by #fhdhsni is perfectly correct, I’d add some nitpicking clarification.
The exact equivalent of Kernel#send from ruby in elixir is impossible, because Kernel#send allows to call private methods on the receiver. In elixir, private functions do not ever exist in the compiled code.
If you meant Kernel#public_send, it might be achieved with Kernel.apply/3, as mentioned by #fhdhsni. The only correction is since the atom table is not garbage collected, and one surely wants to call an indeed existing function, it should be done with String.to_existing_atom/1.
apply(
String,
String.to_existing_atom("u#{:pcase}"),
["uppercase"]
)
Also, one might use macros during the compilation stage to generate respective clauses when the list of functions to call is predictable (when it’s not, the code already smells.)
defmodule Helper do
Enum.each(~w|upcase|a, fn fname ->
def unquote(fname)(param),
do: String.unquote(fname)(param)
# or
# defdelegate unquote(fname)(param), to: String
end)
end
Helper.upcase("uppercase")
#⇒ "UPPERCASE"
In Elixir module and function names are atoms. You can use apply to call them dynamically.
apply(String, String.to_atom("u#{:pcase}"), ["uppercase"]) # "UPPERCASE"
Depending on your use case it might not be a good idea to create atoms dynamically (since the atom table is not garbage collected).

Ruby way of looping through nested objects

How can I rewrite the following code to be more Ruby-wayish? I'm thinking about inject but can't figure out how to do it.
def nested_page_path(page)
path = "/#{page.slug}"
while page.parent_id do
path.prepend "/#{page.parent.slug}"
page = page.parent
end
path
end
Input is an AR object, that has 0-5 consecutive parents. And output is something like '/pages/services/law'.
If you know for sure that there are no cycles in your parenting, you can do that recursively, i. e. with a function that calls itself. 5-level nesting should do just fine, trouble could arise with thousands.
def nested_page_path(page)
return "" if page.nil? # Or whatever that is root
"#{nested_page_path(page.parent)}/#{page.slug}"
end
But bear in mind, that the approach above, as well as yours, will fetch each object in a separate query. It's fine when you already have them fetched, but if not, you're in a bit of N+1 query trouble.
An easy workaround is caching. You can rebuild the nested path of this object and its descendants on before_save: that is some significant overhead on each write. There is a much better way.
By using nested sets you can get the object's hierarchy branch in just one query. Like this:
page.self_and_ancestors.pluck(:slug).join('/')
# ^
# Nested sets' goodness
What that query does is essentially "fetch me pages ordered by left bound, ranges of which enclose my own". I'm using awesome_nested_set in my examples.
SELECT "pages"."slug" FROM "pages"
WHERE ("pages"."lft" <= 42) AND ("pages"."rgt" >= 88)
ORDER BY "pages"."lft"
Without knowing your object structure it's difficult. But something recursive like this should do:
def nested_page_path(page)
path = "/#{page.slug}"
return path unless page.parent_id
path.prepend "#{nested_page_path(page.parent)}/"
end
Not sure inject is the simple answer since it operates on an Enumerable and you don’t have an obvious enumerable to start with.
I’d suggest something like this (not unlike your solution)
def nested_page_path(page)
pages = [page]
pages << pages.last.parent while pages.last.parent
'/' + pages.reverse.map(&:slug).join('/')
end
There’s scope for reducing repetition there, but that’s more or less what I’d go with.

Step definitions for cucumber data tables for storing correct answers

I am trying to find a way to test multiple choice questions. The structure is that a lesson has 8 stages and each stage contains multiple choice questions with only one correct answer. The loading of the questions is random each time so i have been looking for the best way to test whether the correct answer is clicked. For this reason i have created a data table with two columns which is obviously more extensive than this but is along these lines:
| what is the opposite of true | false |
| what comes after tuesday | wednesday |
In the feature test i have written that it is testing a correct answer match. Later I was then hoping to find a way to test that if the question and answer match were not in the data table then it is incorrect. Would someone be able to explain how I would go about doing the test definitions for this?
I have tried to use the rows_hash method but I am getting the following error
undefined method `rows_hash' for -3634850196505698949:Fixnum (NoMethodError)
Given(/^a list of answer\-value pairs$/) do |table|
#question_answer_table = hash
end
When(/^I choose a match$/) do
hash = #question_answer_table
#question_answer_table.rows_hash
return false if hash[question].nil?
return hash[question] == answer
end
I think the rows_hash method will help you.
def question_correct?(cucumber_table, question, answer)
hash = cucumber_table.rows_hash
return false if hash[question].nil?
return hash[question] == answer
end
The code works by converting a two column data table into a hash, where the first column is the key and the second is the value.
Keep in mind that this method requires your data table to be limited to two columns.
You'll find this much easier, if you don't try and do this in Cucumber using data tables. Instead push all that detail down to helper methods that are called by the step definitions. To start doing this you need to write a more abstract feature.
The first thing you need to do is to get the simplest possible lesson to work with. So
Given a simple lesson
When I answer the questions correctly
Then I should see I passed the lesson
This is the scenario you'll use to 'drive' your development.
You can implement these steps really easily by delegating e.g.
Given "a simple lesson" do
#lesson = create_simple_lesson
end
When "I answer the questions correctly" do
answer_questions lesson: #lesson
end
Then "I should see I passed the lesson" do
expect(page).to have_content "You passed"
end
To get this to work you'll have to implement some helper methods
module QuestionaireStepHelper
def create_simple_lesson
...
def answer_questions lesson: nil
...
end
World QuestionaireStepHelper
What this does is move your technical problem into a new domain. Here you have the full power of a programming language to do whatever you want: so you can do things like
create Questions that have answers and know what the correct answer is
ask Questions for thier correct answer, so you can answer them correctly
add questions to a lesson
...
Remember because you are still in the Cucumber::World, you have the full power to
drive your browser
access your database
...
When you have finished this you'll have lots of tools to write scenarios like
Given a simple lesson
When I answer the questions incorrectly
Then I should see I failed the lesson
and so on.

Ndepend find actual number of method usages

Let's say I have method A.M1.
It is called in B.M2 2 times and in B.M3 3 times.
I need to find all number of usages (like Resharper does through find usages interface). So the sum for method calls would be 5.
Following Query:
from m in Methods
where m.HasAttribute("specific attribute")
orderby m.MethodsCallingMe.Count() descending
select new { m, m.MethodsCallingMe }
gives me only 2 usages for method A.M1.
Could you please help me to find the usages number?
It's difficult or impossible to do with NDepend. NDepends shows which methods are calling specified method and not count in this situation them and even not count them recursively or through call graph.
So try to use other techniques. By first of all, why you need such metric? Some kind of method rank?
Anyway a pretty simple way to achieve it, is using RegEx experssion. You can use also NDepend API or regex and ndepend api together. For example, get all method names from source code base using nDepend API and then using regex for each method name count matches except method definition itself.

Plain Old Objects in Ruby?

I notice in Ruby it is very common to for vendor APIs to pass back results as arrays? Shouldn't Plain Old Objects (Like POJOs in Java) be more of a standard? If I write my own library shouldn't I use POJOs POROs?
I think array vs object is a false dichotomy.
It is perfectly reasonable, where an API call is returning more than one of a thing, that it is in the form of an array (and an array is a fairly simple object, and therefore arguably a 'PORO', in Ruby anyway)
Edit: in response to your comments:
The example you cite ( http://github.com/cjheath/geoip ) returns an array of differing items. I agree this is not necessarily the best format to return the data in. In that case I would have thought a hash with sensibly named keys would be a better structure.
As John Topley says, the OO nature of Ruby means people don't have to invent such terminology as 'PORO', as a hash is pretty much as simple as you can get.
It's all objects, all the time. The key is whether the objects being returned have behavior associated with them. It's fine to do this:
def read_first_and_last_name(data_source)
[data_source.read_string, data_source.read_string]
end
But the moment you find there is behavior associated with those data items...
def print_name(first_name, last_name)
puts "#{first_name} #{last_name}"
end
def read_and_print_name
first_name, last_name = read_first_and_last_name(data_source)
print_name(first_name, last_name)
end
...then they should be a class:
class FullName
def FullName.read(data_source)
FullName.new(data_source.read_string, data_source.read_strng)
end
def initialize(first_name, last_name)
#first_name = first_name
#last_name = last_name
end
def print
puts "#{#first_name} #{#last_name}"
end
end
With a name's behavior nicely encapsulated, usage becomes as simple as:
def read_and_print_name
FullName.read(data_source).print
end
What do those arrays of results contain? The answer is that in Ruby they contain objects, because everything in Ruby is an object.
POJOs in the Java world were a reaction against some of the complexities inflicted upon the world by enterprise Java e.g. EJBs. To quote Martin Fowler who coined the term:
"We wondered why people were so
against using regular objects in their
systems and concluded that it was
because simple objects lacked a fancy
name. So we gave them one, and it's
caught on very nicely."
Fortunately in Ruby it has always been natural for people to just practise object-oriented programming without the need to invent terminologies around it.
I personally use POROs in almost anything I write that isn't a complete throwaway script.
I find myself often creating a data holder type of class that would manage and hold multiple objects of my specific type and include some helper methods. I find this convenient for when someone else has to work with my code as well.
I think this question is very subjective in the sense that there isn't an answer that is always right. Sometimes just passing back an array is fine and there is no need to create an extra class. Sometimes the extra level of abstraction makes something a lot more clear to the user.

Resources