Related
I have a hash like so:
def my_requests
result = {
accepted: [],
rejected: [],
pending: [],
}
self.requests.each do |request|
serialized_request = RequestSerializer.new(request)
if request.accept == nil
result[:pending].push(serialized_request)
elsif request.accept
result[:accepted].push(serialized_request)
else
result[:rejected].push(serialized_request)
end
end
result
end
I will have a logged in user. I am trying to organize the logged in user's availabilities by id.
How do I sort each array by id. I know if this was just an array I can do:
array.sort_by{|request| request.id}
But how do I iterate through each key's array? I've tried multiple different ways and the only one that works is if I end up mapping over the hash and then another loop to sort the requests. But that doesn't return a hash. Is there a way for me to keep the structure and sort it?
The availabilities serializer is below:
class RequestSerializer < ActiveModel::Serializer
attributes :id, :start_time, :payment, :number_of_hours, :availability_id, :date, :name, :accept, :postcode, :phone_number
end
Below is one of the key, value pair outputs.
:rejected=>[#<RequestSerializer:0x00007fa416e168a8 #object=#<Request id: 64, payment: 200, number_of_hours: 20, accept: false, start_time: "2000-01-01 16:20:00", venue_id: 1, availability_id: 4, created_at: "2020-08-30 12:15:04", updated_at: "2020-08-30 12:15:52">, #instance_options={}, #root=nil, #scope=nil>, #<RequestSerializer:0x00007fa416e167b8 #object=#<Request id: 4, payment: 160, number_of_hours: 4, accept: false, start_time: "2000-01-01 16:15:00", venue_id: 2, availability_id: 5, created_at: "2020-06-17 21:19:07", updated_at: "2020-06-17 21:21:32">, #instance_options={}, #root=nil, #scope=nil>, #<RequestSerializer:0x00007fa416e166c8 #object=#<Request id: 71, payment: 100, number_of_hours: 1, accept: false, start_time: "2000-01-01 09:45:00", venue_id: 1, availability_id: 6, created_at: "2020-10-01 08:45:43", updated_at: "2020-10-01 08:46:04">, #instance_options={}, #root=nil, #scope=nil>, #<RequestSerializer:0x00007fa416e16560 #object=#<Request id: 66, payment: 30, number_of_hours: 3, accept: false, start_time: "2000-01-01 16:30:00", venue_id: 1, availability_id: 26, created_at: "2020-08-30 12:31:02", updated_at: "2020-08-30 12:32:10">, #instance_options={}, #root=nil, #scope=nil>, #<RequestSerializer:0x00007fa416e163f8 #object=#<Request id: 68, payment: 20, number_of_hours: 3, accept: false, start_time: "2000-01-01 12:00:00", venue_id: 1, availability_id: 28, created_at: "2020-09-01 08:17:26", updated_at: "2020-09-01 13:09:54">, #instance_options={}, #root=nil, #scope=nil>]
Thanks!
result.transform_values { |array| array.sort_by(&:request_id) }
If the arrays are not not arrays of requests, but RequestSerializer, just call .object on them to get the request to sort by.
result.transform_values do |array|
array.sort_by { |serializer| serializer.object.request_id }
end
Another option would be to define request_id on RequestSerializer
You have to sort each hash value separately:
result.each_value { |array| array.sort_by!(&:id) }
Hash#each_value traverses the values and sort_by! sorts the array in-place.
If you need to create a new sorted copy:
result.each_with_object({}) do |(key, value), list|
list[key] = value.sort_by(&:id)
end
As Stefan posted in the comments. I can use a database query to order the requests prior to splitting them into their arrays.
The answer that worked (without doing multiple loops) was:
def my_requests
result = {
accepted: [],
rejected: [],
pending: [],
}
requests.order(:id).each do |request|
serialized_request = RequestSerializer.new(request)
if request.accept == nil
result[:pending].push(serialized_request)
elsif request.accept
result[:accepted].push(serialized_request)
else
result[:rejected].push(serialized_request)
end
end
result
end
Simply by removing self. and using the .order query and the id attribute, everything comes out ordered!
Thanks Stefan! (and everyone else)
(Others worked with multiple methods or loops but as I was using Rails, the query is the quickest and easiest).
I am stuck with an issue, any help would be appreciated.
I have a rails query
array = Issue.where("tracker_id =? AND project_id = ?",8,140).first.custom_field_values
This returns an array like this :
[#<CustomFieldValue:0x000000074d8b98 #custom_field=#<IssueCustomField id: 4, type: "IssueCustomField", name: "Phase Injected", field_format: "list", possible_values: ["Planning", "Requirements", "Design", "Coding", "Testing"], regexp: "", min_length: nil, max_length: nil, is_required: true, is_for_all: true, is_filter: true, position: 4, searchable: false, default_value: "", editable: true, visible: true, multiple: false, format_store: {"url_pattern"=>"", "edit_tag_style"=>""}, description: "", formula: nil, is_computed: false>, #customized=#<Issue id: 43, tracker_id: 8, project_id: 140, subject: "Cost of rework is not calculated for past sprints", description: "", due_date: nil, category_id: nil, status_id: 1, assigned_to_id: 5, priority_id: 2, fixed_version_id: 1, author_id: 8, lock_version: 3, created_on: "2018-07-26 05:40:19", updated_on: "2018-08-09 10:46:12", start_date: "2018-07-26", done_ratio: 0, estimated_hours: nil, parent_id: 42, root_id: 42, lft: 2, rgt: 3, is_private: false, closed_on: nil, sprint_id: nil, position: nil>, #value="Planning", #value_was="Planning">,.....]
The above array has more then 10 results pasted the first one.
How do I search inside this array for the name = 'Phase Injected' and get the result that is #value which is 'planning'.
Currently I am trying to go inside the array by:
<% array.each do |cf| %>
<% if cf.custom_field.name = "Phase Injected" %>
<%= cf %> #this returns #value
<% end %>
<% end %>
can I not do array.find_by_something and get the value?
Thanks
It returns the active record relation object, not the array in the first place. Yes, it quacks as an array, though.
You should filter the data directly in the database instead of an extremely ineffective array filtering:
Issue.
joins(:issue_custom_fields).
where(tracker_id: 8, project_id: 140).
where('`issue_custom_fields`.`name` = "Phase Injected"')
or, as #Stefan suggests in comments:
Issue.
joins(:issue_custom_fields).
where(tracker_id: 8, project_id: 140).
where(issue_custom_fields: { name: 'Phase Injected' })
I have a model called Event, where I have stored_accessor "list" (stored like data: {"list"=>[{"key"=>"key1", "value"=>"value1"}]}).
I need to make a search query o
#<Event id: "1", title: "HHHH", description: nil, data: {"list"=>[{"key"=>"key1", "value"=>"value1"}, {"key"=>"key2", "value"=>"value2"}]}, created_at: "2017-04-14 21:06:22", updated_at: "2017-04-20 10:36:08">
#<Event id: "2", title: "HHHH", description: nil, data: {"list"=>[{"key"=>"key1", "value"=>"value1"}]}, created_at: "2017-04-14 21:06:22", updated_at: "2017-04-20 10:36:08">
#<Event id: "3", title: "HHHH", description: nil, data: {"list"=>[{"key"=>"key11", "value"=>"value11"}, {"key"=>"key12", "value"=>"value12"}]}, created_at: "2017-04-14 21:07:22", updated_at: "2017-04-20 10:37:08">
#<Event id: "4", title: "HHHH", description: nil, data: {"list"=>[{"key"=>"key111", "value"=>"value111"}, {"key"=>"key112", "value"=>"value112"}]}, created_at: "2017-04-14 21:08:22", updated_at: "2017-04-20 10:38:08">
I have a serach params like
1) {'key'=> 'key1', 'value'=> 'value1'}
2) ["key"=>"key1", "value"=>"value1"}, {"key"=>"key2", "value"=>"value2"}]
In first case, it should return Event id 1 and 2.
In second case, it should return Event id 1. (event if return 1 and 2 both could be acceptable).
I am not sure with json and array combination.
Please help.
You may do it with PostgreSQL jsonb's operator #>. Also you need to write the full path for search params: {'list' => [{'key'=> 'key1', 'value'=> 'value1'}]}. Try this code:
to_contain1 = {'list' => [{'key'=> 'key1', 'value'=> 'value1'}]}
to_contain2 = {'list' => [{'key'=> 'key2', 'value'=> 'value2'}]}
Event.
where("data #> ?", to_contain1.to_json})
# returns events 1 & 2
Event.
where("data #> ?", to_contain1.to_json).
where("data #> ?", to_contain2.to_json)
# returns event 1
When I call:
preivous_lessons = #item.where("track_id = ?", lesson.track_id)
I get this active record realtion:
[#<CodeLesson id: 2, name: "Python", permalink: "python", lesson_content: "", instructions: "Print your name to the console.", hints: "", starting_code: "\"\"\"\r\nThis is a comment\r\n\"\"\"\r\n\r\nprint(\"Hello, World\"...", language_id: "12", order: 1, track_id: 2, user_id: 1, created_at: "2014-02-14 16:01:12", updated_at: "2014-02-15 21:14:43", visible: true>, #<CodeLesson id: 8, name: "Test Lesson", permalink: "test-lesson", lesson_content: nil, instructions: nil, hints: nil, starting_code: nil, language_id: "26", order: nil, track_id: 2, user_id: 1, created_at: "2014-02-20 19:23:15", updated_at: "2014-02-20 19:23:15", visible: false>]
How do I convert this into a usable array of models so I can do something like this:
preivous_lessons.each do |i|
highest = i.order if i.order > highest
end
As OP confirmed from my comment, that my hint solved his problem, I am putting it as an answer to the post :
preivous_lessons = #item.where("track_id = ?", lesson.track_id)
highest = preivous_lessons.maximum(:order)
Documentation of maximum :
Calculates the maximum value on a given column. The value is returned with the same data type of the column, or nil if there's no row.
preivous_lessons = #item.where("track_id = ?", lesson.track_id).all
My company has an old website that was built many years ago in PHP. I believe the database schema represents the slow accumulation of requests that were never thought about in a strategic way. Now we are throwing out the PHP code and building the site using Rails. The database schema remains, mostly unchanged.
I'm just getting my head around Rails, so this will be perhaps a simple question.
I have an article table where the data looks like this:
id: 1102129
article_type_id: 5
old_article_id: 0
title: Zombie Film Locations
subtitle: Hollywood-inspired survival tips for destinations teeming with the undead
display_date: 0000-00-00
author_id: 29
thumbnail_image_id: 12033473
index_image_id: 12033473
article_image_id: 12033473
is_archived: 0
is_featured: 1
is_published: 1
date_to_show: 2011-10-04 00:00:00
off_the_path: 0
created: 2011-10-04 12:45:07
modified: 2011-10-11 15:33:59
fact_check_date: 0000-00-00 00:00:00
unpublish_date: 0000-00-00
is_qsfeatured: 1
featured_order: 0
Second row:
id: 1102128
article_type_id: 14
old_article_id: 0
title: Hotel Adagio [id]35677
subtitle: Hotel Adagio
display_date: 2011-09-29
author_id: 0
thumbnail_image_id: NULL
index_image_id: NULL
article_image_id: NULL
is_archived: 0
is_featured: 0
is_published: 1
date_to_show: 2011-09-29 12:50:38
off_the_path: 0
created: 2011-09-29 12:50:38
modified: 2011-09-29 12:50:38
fact_check_date: NULL
unpublish_date: NULL
is_qsfeatured: 0
featured_order: NULL
The image data looks like:
id: 6722
old_id: 0
type: Index
association_type: TopTen
association_id: 1102129
position: 0
copyright: AMC
caption: The Walking Dead portrays an abandoned, corpse-ridden downtown Atlanta, one of 10 zombie film locations we've scouted out to help you survive (and hide) should the dead rise.
alt_text: Zombie film locations
url: photos/index-TopTens/walkingdeadindex.jpg
_url:
name: index
published: 0
description:
Second row:
id: 6723
old_id: 0
type: Thumbnail
association_type: TopTen
association_id: 1102129
position: 0
copyright: AMC
caption: The Walking Dead portrays an abandoned, corpse-ridden downtown Atlanta, one of 10 zombie film locations we've scouted out to help you survive (and hide) should the dead rise.
alt_text: Zombie film locations
url: photos/thumb-TopTens/walkingdeadthumb.jpg
_url:
name: thumbnail
published: 0
description:
The association_id in the images table is the id of the article, though there is no foreign key specified in the database.
How do I get all the images when I get the article?
Right now in the controller I do:
#articles = Article.where(:article_type_id => 5).order("id DESC").limit(5)
In the view I do stuff like:
<%= article.title %>
But how can I reference the images, from the article model?
To make this more complicated, the images are polymorphic, so I can not simply create a foreign key from images to articles. Images also sometimes get mapped to "travel_guides" and "slideshows", which are 2 other tables we have.
UPDATE:
Changed Article so now it has:
has_many :images, :foreign_key => 'association_id'
Changed my controller code to:
#articles = Article.where(:article_type_id => 5).order("id DESC").limit(5).joins(:images)
But in my view I do:
<%= article.images.url %>
and I get "no method url" errors.
I was doing:
<%= article.image.url %>
without the "s" on images, and then I got "no method 'image'".
UPDATE:
So, okay, so, on the command line, I run "rails c" to get into the console, and then I run the code that I'm using in my controller:
#articles = Article.where(:article_type_id => 5).order("id DESC").limit(5).joins(:image)
Which gives me:
#articles = Article.where(:article_type_id => 5).order("id DESC").limit(5).joins(:image)
Article Load (11.5ms) SELECT `articles`.* FROM `articles` INNER JOIN `images` ON `images`.`association_id` = `articles`.`id` WHERE `articles`.`article_type_id` = 5 ORDER BY id DESC LIMIT 5
=> [#<Article id: 1102129, article_type_id: 5, old_article_id: 0, title: "Zombie Film Locations", subtitle: "Hollywood-inspired survival tips for destinations t...", display_date: nil, author_id: 29, thumbnail_image_id: 12033473, index_image_id: 12033473, article_image_id: 12033473, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-10-04 00:00:00", off_the_path: false, created: "2011-10-04 12:45:07", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 1, slug: "zombie-film-locations">, #<Article id: 1102129, article_type_id: 5, old_article_id: 0, title: "Zombie Film Locations", subtitle: "Hollywood-inspired survival tips for destinations t...", display_date: nil, author_id: 29, thumbnail_image_id: 12033473, index_image_id: 12033473, article_image_id: 12033473, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-10-04 00:00:00", off_the_path: false, created: "2011-10-04 12:45:07", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 1, slug: "zombie-film-locations">, #<Article id: 1102129, article_type_id: 5, old_article_id: 0, title: "Zombie Film Locations", subtitle: "Hollywood-inspired survival tips for destinations t...", display_date: nil, author_id: 29, thumbnail_image_id: 12033473, index_image_id: 12033473, article_image_id: 12033473, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-10-04 00:00:00", off_the_path: false, created: "2011-10-04 12:45:07", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 1, slug: "zombie-film-locations">, #<Article id: 1102122, article_type_id: 5, old_article_id: 0, title: "Nude Vacations", subtitle: "These places to get naked around the world make for...", display_date: nil, author_id: 574, thumbnail_image_id: 12024629, index_image_id: 12024629, article_image_id: 12024629, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-09-23 00:00:00", off_the_path: false, created: "2011-09-23 13:13:41", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 2, slug: "nude-vacations">, #<Article id: 1102122, article_type_id: 5, old_article_id: 0, title: "Nude Vacations", subtitle: "These places to get naked around the world make for...", display_date: nil, author_id: 574, thumbnail_image_id: 12024629, index_image_id: 12024629, article_image_id: 12024629, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-09-23 00:00:00", off_the_path: false, created: "2011-09-23 13:13:41", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 2, slug: "nude-vacations">]
So, despite the join, none of the image data shows up.
UPDATE:
Huh, now I see that in that block that I'm getting on the rails console, I see that each article is returning 3 times, I assume because of the JOIN:
Article id: 1102129, article_type_id: 5, old_article_id: 0, title: "Zombie Film Locations", subtitle: "Hollywood-inspired survival tips for destinations t...", display_date: nil, author_id: 29, thumbnail_image_id: 12033473, index_image_id: 12033473, article_image_id: 12033473, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-10-04 00:00:00", off_the_path: false, created: "2011-10-04 12:45:07", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 1, slug: "zombie-film-locations">,
,
,
So I get 3 articles because of the 3 associations with images, yet I do not get the images. This is the worst of both worlds.
It would be easier to do a separate query for the images, really.
UPDATE:
This SQL gives me what I want but I don't seem able to turn this into a Rails query:
SELECT articles.title, articles.subtitle, images.url, images.caption
FROM articles
JOIN images ON articles.id = images.association_id
WHERE images.type='Thumbnail'
ORDER BY articles.id desc
LIMIT 5 \G
UPDATE:
I have not been able to get this to work. I think a Ruby tutor to teach me some basic Ruby and Rails stuff. I am happy to pay. I'm reposting my questions here: http://tutorruby.com/question/show?id=3235
To access the images from an article you need to add an association in the Article class:
class Article
has_many :images, :foreign_key => :association_id
end
You mentioned that sometimes images are mapped to travel_guides and slideshows (2 additional tables). You have to add an association for each table. So you might do something like:
class Article < ActiveRecord::Base
has_many :images, :foreign_key => :association_id
has_many :travel_guides, :foreign_key => :association_id
has_many :slideshow_images, :foreign_key => :association_id
end
It is generally also a good idea to set up the reverse associations:
class Image < ActiveRecord::Base
belongs_to :article, :foreign_key => :association_id
end
class TravelGuide < ActiveRecord::Base
belongs_to :article, :foreign_key => :association_id
end
class SlideshowImage < ActiveRecord::Base
set_table_name :slideshows
belongs_to :article, :foreign_key => :association_id
end
Some things to consider:
I left off the :dependent option in the *has_many* associations. This is generally not a good idea. You can set :depedent => :destroy so that you can call some cleanup logic in your image classes (to delete the image files).
If you do not have simple joins, you should consider adding the :conditions option to the has_many (or the belongs to).
Single table inheritance and or polymorhpic associations are both other tools you can use if the above suggestions don't solve all of your problems.
When you specify "has_many" in your images association, you are saying that an article has a collection of images, so article.images returns an array. There is no method 'url' defined on array. To access the url method, you need to access each individual array member, and call the url on that object. Something like:
article.images[0].url
or
article.images.first.url
You need to specify the association in the models. There is a namin convention like you sait but your table doesnt follow that but thats not a problem at all. There are two possible solutions.
1.) You rename the column in the database (what wont work when the app is still in production with PHP)
2.) You specify the association using the :foreign_key parameter like this:
Article:
has_many :images, :foreign_key => 'association_id'
Picture:
belongs_to :article, :foreign_key => 'association_id'
But there are some things that you need to attend. You will get some problems naming your table images because theres also an public folder "images" and when you call a picture beginning with a number rails interprets it as an id and trys to fetch an Image instance from the database instead of delivering the image.
Secound problem might get that thers a field called "association_type" which suggestes that thers a polymorphy association. YOu might rename this too when you switch to rails.
articles = Article.includes(:images).where(:article_type_id => 5, :images => { :image_type => 'Thumbnail' }).order('articles.id DESC').limit(5) #no database query is fired yet by rails
article = articles.first # Here we fire the first query, and this query also fetches the image of the article
article.images.first #again fires no query but returns the first image of the article
There is another case where you should fire db query to fetch only one image from the database.
Then you should do something like,
articles = Article.where(:article_type_id => 5).order("id DESC").limit(5) #again fires no db query
article = articles.first #fires db query to get first article
image = article.images.first #fires query for only first image of the article
First method is efficient if you have less number of images per article, but second method is efficient if there is large number of images per article
Now your rails query for the sql posted above,
SELECT articles.title, articles.subtitle, images.url, images.caption
FROM articles
JOIN images ON articles.id = images.association_id
WHERE images.type='Thumbnail'
ORDER BY articles.id desc
LIMIT 5
articles = Article.joins(:images).select("articles.title, articles.subtitle, images.url, images.caption").where("images.type = 'Thumbnail'").order("articles.id DESC").limit(5)
article = articles.first
first_image = article.images.first