Random jokes in a skit (activerecord) - ruby-on-rails

I am working on populating my database with test data using populate.rake:
Repertoire.includes(:jokes).each do |r|
#jokes = r.jokes
Skit.populate 8..12 do |skit|
skit.joke_id = #jokes[rand(#jokes.count)].id
end
end
This is giving me a RuntimeError: Called id for nil.
How can I populate a skit with random jokes?

sort_by {rand} should sort your array of jokes.
Or, there is also doing an .order("rand()/random()") (depending on your db) in your Repertoire query and putting a limit on the query.

Not sure if this will fix your problem but Ruby has a rand method for arrays so you should be able to call #jokes.rand.id instead. Seems like that would simplify things and maybe even fix your error.

Related

Rails query and order with same array used for query

I have method
def self.get_ayahs_by_array(ayahs_keys_array)
self.where(ayah_key: ayahs_keys_array)
end
Which does a query on the Quran::Ayah model. ayahs_keys_array is an array of keys (primary_key) in a certain order. The query returns a different order, but I want it to return as the same order as the queried array.
Example: ayahs_keys_array is [5,4,1,2,7] and I want it to return in THAT order and not [1,2,4,5,7]
Any ideas?
In MySql:
self.where(ayah_key: ayahs_keys_array).order("FIELD(ayah_key, #{ ayahs_keys_array.joins(', ') })")
For postgres is slightly more complicated as you need to build whole CASE statement. Might be easier to do it on the application level:
self.where(ayah_key: ayahs_keys_array).order_by {|r| ayahs_keys_array.index r.ayah_key}
Finally, you can try this gem: https://github.com/panorama-ed/order_as_specified. If you do, please let us know how it went as I never used it.

Access hash by primary key - ruby rails

I thought this could be done trivially but I am unable to do so.
My current code is:
#player_types = squad.player_types
Now I loop and lookup for the id,
params[:player_types].each do |p_type|
#player_types.find(p_type[:id])
end
Why does #player_types.find(p_type[:id]) have to execute the the select query when I look up the server logs, havent I loaded this. Is it because of the lazy evaluation and is there a way to load everything at the start and access it as an index in the hash?
The better way to use arel gem, and to select all record with specific ids is this:
ids = params[:player_types].map {|v| v[:id] }
#player_types.where(#player_types.class.arel_table[:id].in(ids))
If player_types is a table, you can directly select all of the player_types in the params[:player_types] array by passing the array to a where condition.
#player_types = PlayerType.where(id: params[:player_types])

Remove element from ActiveRecord_Relation in rails

How can i remove the last element from an ActiveRecord_Relation in rails?
e.g. if I set:
#drivers = Driver.all
I can add a another Driver object called #new_driver to #drivers by doing:
#drivers << #new_driver
But how can I remove an object from #drivers?
The delete method doesn't seem to work, i.e.
#drivers.delete(0)
You can use the reject! method, this will remove the object from the collection without affecting the db
for example:
driver_to_delete = #driver.first # you need the object that you want removed
#drivers.reject!{|driver| driver == driver_to_delete}
Very late too, but I arrived here looking for a fast answer and finished by thinking by myself ;)
Just to clarify about the different answers and the Rails 6.1 comment on accepted answer:
The OP wanted to remove one entry from a query, but NOT remove it from database, so any answer with delete or destroy is just wrong (this WILL delete data from your database !!).
In Ruby (and therefore Rails) convention, shebang methods (ending with !) tend to alter the given parameter. So reject! would imply modifying the source list ... but an ActiveRecord_Relation is basically just a query, NOT an array of entries !
So you'd have 2 options:
Write your query differently to specifically say you don't want some id:
#drivers.where.not(id: #driver_to_remove) # This still is an ActiveRecord_Relation
Use reject (NO shebang) on your query to transform it into an Array and "manually" remove the entry you don't want:
#drivers.reject{ |driver| driver == #driver_to_remove}
# The `reject` forces the execution of the query in DB and returns an Array)
On a performance point of view, I would personally recommend the first solution as it would be just a little more complex against the DB where the latter implies looping on the whole (eventually large) array.
Late to the question, but just had the same issue and hope this helps someone else.
reject!did not work for ActiveRecord_Relation in Rails 4.2
drop(1) was the solution
In this case #drivers.drop(0) would work to drop the first element of the relation
Since its an array of objects, have you tried to write something like #drivers.delete(#new_driver) or #drivers.delete(id: #new_driver.id) ?
This is the documentation you need:
#group.avatars << Avatar.new
#group.avatars.delete(#group.avatars.last)
--
.destroy
The problem you've got is you're trying to use collection methods on a non-collection object. You'll need to use the .destroy ActiveRecord method to get rid of the record from the database (and consequently the collection):
#drivers = Driver.all
#drivers.last.destroy
--
Scope
.delete will remove the record from the DB
If you want to pull specific elements from the db to populate the #drivers object, you'll need to use a scope:
#app/models/driver.rb
Class Driver < ActiveRecord::Base
scope :your_scope, -> { where column: "value" }
end
This will allow you to call:
#app/controllers/drivers_controller.rb
def index
#drivers = Driver.your_scope
end
I think you're getting the MVC programming pattern confused - data manipulation is meant to happen in the model, not the controller
As stated above, reject! doesn't work in Rails 4.2, but delete does, so #drivers.delete(#new_driver) works, and more generally:
#drivers.delete(Driver.where(your condition))

Rails: Getting column value from query

Seems like it should be able to look at a simple tutorial or find an aswer with a quick google, but I can't...
codes = PartnerCode.find_by_sql "SELECT * from partner_codes where product = 'SPANMEX' and isused = 'false' limit 1"
I want the column named code, I want just the value. Tried everything what that seems logical. Driving me nuts because everything I find shows an example without referencing the actual values returned
So what is the object returned? Array, hash, ActiveRecord? Thanks in advance.
For Rails 4+ (and a bit earlier I think), use pluck:
Partner.where(conditions).pluck :code
> ["code1", "code2", "code3"]
map is inefficient as it will select all columns first and also won't be able to optimise the query.
You need this one
Partner.where( conditions ).map(&:code)
is shorthand for
Partner.where( conditions ).map{|p| p.code}
PS
if you are often run into such case you will like this gem valium by ernie
it gives you pretty way to get values without instantiating activerecord object like
Partner.where( conditions ).value_of :code
UPDATED:
if you need access some attribute and after that update record
save instance first in some variable:
instance=Partner.where( conditions ).first
then you may access attributes like instance.code and update some attribute
instance.update_attribute || instance.update_attributes
check documentation at api.rubyonrails.org for details

How to get table column value?

I write follow code to get one record from the table webeehs:
webeehs_result = Webeeh.find(:all, :conditions=>["webeeh_project_id=#{project_id}"])
Then I want to get one column value from this record, how could I do?
For example, the column name is webeeh_date.
first of all, never EVER write code like that. Building your own conditions as pure strings can leave you vulnerable to SQL injection exploits. If you must do conditions, then do it like this:
:conditions => ["webeeh_project_id = ?", project_id]
if you have a Project model, you should rename the webeeh_project_id column from your Webeeh model into project_id and have an association in your Project model like has_many :webeehs
Then, you won't need to call that find anymore, just do a p = Project.find(id) and then p.webeehs will return the webeehs you need.
the result will be an array which you can iterate through. And to get your webeeh.webeeh_date member, just call it like this:
result.each do |webeeh|
date = webeeh.webeeh_date
end
webeehs_result = Webeeh.findwebeeh_dates
is enough to get all columnn values.
For a different method and performance issues check the following: http://www.stopdropandrew.com/2010/01/28/finding-ids-fast-with-active-record.html
webeeh_result will usually be an array of results for the database.
You can iterate throughit using
webeehs_result.each do |webeeh|
# use "webeeh.webeeh_date" to access the column_name or do whatever you want with it.
end

Resources