Rails - Efficient way of finding entries with specific value in model - ruby-on-rails

So I am trying to find all entries in my table that have a specific value in a particular column. The only way I can think off to do this is to look at each entry and see if it has the value but I was hoping there would be a more efficient solution - this gets unwieldy once you have a sizable database.
Does anyone have a better idea?
Update - I am creating an HTML table and I want to populate the table with all the entries in my model that have a certain value in a particular column. I am trying to do:
<%= render #users.where("column_name = 'value'") %>
as the answer below recommends but I get "undefined method `where' for nil:NilClass" error.
Update 2 - I am not sure why #users would be nil but I will try to figure that out later. For now, I tried
<% #user_message = User.where("column_name = 'value'") %>
<%= render #user_message %>
but it doesn't show any entries at all.
Update 3 - When I do, User.all in rails console, I get all the users so I know the data is there. However, when I do User.where("column_name = 'value'"), I get an empty array. I double checked the column name and value to make sure that the data was present.
Update 4 - Fixed! - I'm not sure why it didn't work in rails console but I got it to work in the site. I called my partial _user_message.html.erb. Apparently it still needs to be called _user.html.erb. Thanks for the help everyone!

Sounds like you want to do a where query, i.e.
#records = Model.where(:some_column => some_value)
Rails has excellent documentation, I suggest you take a look at the ActiveRecord Query guide:
http://guides.rubyonrails.org/active_record_querying.html
ian.

Related

Can access ActiveRecord object, but not its attributes

I'm rendering a view in Rails using form_for and nested_form_fields. Here, #procedure_step is a record that has_many :procedure_step_actions, each of which belongs_to :error, which is a ProcedureError that has (among some relations to other models) an integer :code that I'm trying to access and print out to the page. Here's my template:
<%= form_for #procedure_step do |f| %>
<%= f.nested_fields_for :procedure_step_actions do |act| %>
<%= act.object.error.code %>
<% end %>
<% end %>
When I run this, I get undefined method 'code' for nil:NilClass. Okay, so my relations are messed up and I can't access act.object.error, right? Changing my template to display that instead yields #<ProcedureError:0x0000000ece02a8>, which is what one would expect of a functioning relation. Dumping its contents to the screen using debug shows all the attributes of the record, including code, but I still can't access it with the original template! Clearly act.object.error is not nil, so Rails telling me that act.object.error is nil doesn't make any sense to me.
Frustrated, I tried to work around the problem by using act.object.error.to_json. This printed the correct JSON for the record with all its attributes. Using JSON.load() on this gave me a correct Hash of all the attributes, but using [:code] to try to access the code gives me undefined method '[]' for nil:NilClass. Again, I know that object isn't nil, but Rails still refuses to allow me to access it.
Running out of ideas, I tried to use regular expressions to pull the code out of the raw JSON string. /"code":([0-9]+)/.match(act.object.error.to_json) returned #<MatchData "\"code\":69" 1:"69">, which is right. I used [1] to try to access the code number that was matched, but again I got undefined method '[]' for nil:NilClass.
Enough with ActiveRecord, I thought to myself. I decided to turn to raw SQL queries. I got the ID of the error in question using act.object.error_id, then printed that to the screen first to make sure I could access it. Luckily, I could. Then I inserted it into my SQL query with "... WHERE id = #{act.object.error_id}". I refreshed the page again and was greeted with a SQL error. It showed the final SQL query string I had generated, but it ended with WHERE id =. The ID of the error didn't get added to the string. ProcedureError.find(action.object.error_id) gave a similar error.
I'm totally out of ideas. What could possibly be preventing me from accessing one simple integer in so many different ways?
There are at least a couple of issues here. The first is that you probably want to be using fields_for, rather than nested_fields_for, if you're using 4.x.
The second is similar to what the first answer has indicated. You have a nested fields form, which allows you to nest one level in, but you are trying to nest two levels in. By addressing your law of demeter violation you should be able to make some more progress.
Debugging things like this you can get more information by throwing in a binding.pry or byebug right in your erb.
<%- binding.pry %>
Then reload the page. Your server will be stopped at that point in your code and you can play with variable values to learn more about what's going on.
One thing I can see right off the bat is you are violating Law of Demeter here
act.object.error.code
The form object obviously has to stay but you can delegate access to the subobjects by making a method on the procedure_step which can help with handling nulls, and other error cases.
Try delegating that first as I'm not sure if the scope that is created by nested_forms_for will allow the ActiveRecord::Relation object to perform properly. I'll double check locally.
A delegation might look like the following
class ProcedureStepActions
belongs_to :error
def error_code
#error.code
end
end
EDIT:
Other things that might be helpful are the version of Ruby and Rails you are using and any other additional gems or libraries.

Print results of Active Record query

I was wondering if someone could help me or point me to a tutorial to help me understand how to send the results of a rails query into a view? At the moment, I am only able to run a query using the console, but I'm not sure how to render the results into a view. For example, I have a model called City with the attributes state, population_size, and capital. For example, if I run a query in the console:
results = City.where(:state => 'Virginia')
How can I run that same query in Rails? Specifically, where would I place that code? Sorry for the noob question, but I can't find any guides that explicitly show me how to do this. I have only found guides on how to work in the console, but now how to actually render a view of the results...
Thanks!!
You can create the instance var to use it in your views
#results = City.where(:state => 'Virginia')
Now in your view you have access to #results
You can create the instance var to access it throughout the request.
if you want an array of results.
#results = City.where(:state => 'stateName')
if you want a single object
#result = City.find_by(state: 'stateName', id: :id)
Both can help you in different circumstances.
Now in your view you have access to #results

How to search for wild card in Rails

Im trying to search my User model for all Users that start with any integer, I have code for individual letters and it works, but Im having trouble getting it working with a wild card. Right now I have this code:
in my view:
<%= link_to '#', users_charlist_path(:char => '[0123456789]' %>
and in my controller I have:
def charlist
#a = User.where('goal like ?', "#{params[:char]}%").to_a
end
how ever, '[0123456789]', doesnt seem to work as it does not return anythign to me even though I have users whose names begin with an integer. how do i do this?
The where method is a part of ActiveRecord which maps the objects to the database. So how you can query the database with a regex depends on which db you are using not on ruby. You need to look up the regex functions of the database your using. For mysql you can find them here:
http://dev.mysql.com/doc/refman/5.1/de/regexp.html
An alternative is to select all objects an use the select method to filter the results that match your needs. That method is documented here:
http://www.ruby-doc.org/core-2.1.0/Array.html#method-i-select
On big amounts of data I whould suggest to use the database even if that means your application isnt 100% portable between different database systems.

Problems working with the output of the YouTube_It gem in Rails

I've been messing around with the Youtube_It gem for the past couple of days as I'm trying to integrate it into a Rails 4 app I'm currently working on.
When I run a search query with it, it outputs an array with a ton of results. As long as I'm in the Rails console, there's no problem with manipulating it. A brief example :
require 'youtube_it'
client = YouTubeIt::Client.new(:dev_key => "dev_key")
data = client.videos_by(:query => "penguin")
data.videos.each { |v| puts v.unique_id }
This outputs a nice, tidy list of all the unique id's that were returned from the query.
When I try to do something similar within a view (I know it shouldn't really be in the view, it's simply there for testing at this point) it just outputs a huge jumbled list of what appears to be XML. This only seems to happen when I try to iterate using .each.
When I do something like :
<% data = client.videos_by(:query => "penguin") %>
<%= data.videos[1].unique_id %>
This returns exactly what I was expecting, one unique_id from the index that I chose. Great! But how do I get ALL the unique id's?
That's where I'm stuck and would really appreciate some help! :)
OK, two reasons (working from the gist you gave me on IRC, located here):
1) You are not actually using the same code as in the console. Your console uses puts unique_id which will print the value of the unique ID, but you are just using unique_id which will get the ID... and then do nothing with it. What you want is probably something like data.videos.map(&:unique_id) (or data.videos.map { |v| v.unique_id } in long form) which will return you an array of the IDs.
2) You are using <%=, which means 'evaluate this ruby line and output the return value onto the page'. The return value of an each statement is the object you called each on - ie. data.videos, so that is what is getting printed out.

Display all versions of individual records in Papertrail

I'm building a league system and currently it stores and updates the players 'elo score' depending on the result. Now, I'm trying to add in 'HighCharts' to display the players elo score over the season in a sweet looking line chart. Someone suggested I use Papertrail to store the updates and I have got that all installed.
Now here comes my problem, I can't seem to figure out how to spit out the users elo_score versions in an array easy for 'HighCharts' to use. I can get the last updates to elo_score:
Last updated score = <%= #player.versions.last.reify.elo_score %>
But I can't seem to find the syntax to spit out all the 'versions' for 'elo_score'. Something like "1000, 1020, 1043, 1020".
I've also tried:
<%= #player.versions.map { |version| version.reify.elo_score} %>
But this gives me "undefined method `elo_score' for nil:NilClass". While just <%= #player.versions.map { |version| version.reify %> spits out all information in the record and obviously not just the elo_score.
Can anyone help? Sorry if I've not made this clear, I'm absolute brand new to rails, and this is just a fun project in my spare time but I'm having a blast!
Thanks alot!
What you did here:
#player.versions.map { |version| version.reify.elo_score }
Is perfectly fine to take all those scores and put them in an array. The problem that you're getting (the nil:NilClass stuff) is coming because at least one reify is nil. That is, that some version doesn't have a reify.
If each version is supposed to have a reify, be sure to add that as a model validation, and find in your code where the reify is being set and see why it's nil.
If it's okay for a version to have a nil reify, you could accomplish it a number of ways, but the straightforward and explicit way would look like this:
elo_scores = []
#player.versions.each do |version|
unless version.reify.nil?
elo_scores << version.reify.elo_score
end
end
I would suggest putting this in to a method, like get_elo_scores, and then you could more easily call it like:
#player.get_elo_scores
EDIT For clarification from the comments:
Your User model (or Player model, whatever you named it) should have a method that looks like this:
def get_elo_scores
elo_scores = []
self.versions.each do |version|
unless version.reify.nil?
elo_scores << version.reify.elo_score
end
end
return elo_scores
end
I apologize for not making this clearer, but you won't have access to #player within this method because that only exists in the context of your controller and view. The above is now a proper instance method: it will call .versions upon itself, and the rest is fine. I also added an explicit return call at the end.
Now you will be able to call #player.get_elo_scores on any User (or Player) object.
Hope that helps!
Here's a one-liner version of #MrDanA's answer :
elo_scores = self.versions.map{|version| version.reify.elo_scores}
note that you can't check if version.reify.nil? though

Resources