Preserving order or array in has_many relationship - ruby-on-rails

I have a model CardSet which has_many :cards, :order => "cards.order". When I update some_card_set.cards = cards_in_a_particular_order, and then some_card_set.save, I want it so some_card_set.cards returns the next time with the cards in the same order I entered them in. How can I achieve this?

Either do it manually, or use one of a ton of acts_as_ordered plugins, like this or this etc.

Assuming a table design similar to
cards {
id INT PRIMARY KEY,
value VARCHAR(5),
suite VARCHAR(10)
}
card_sets {
id INT PRIMARY KEY,
name VARCHAR(30),
}
Then I would have a join table something like:
card_set_orders {
card_set_id INT,
card_id INT,
order_index INT
}
You would have to change your has many to reflect the join syntax. Then you could have an 'on load' function 'order' for the set. So you'll need:
1) a new migration
2) a new activerecord model
3) ordering method that you can invoke on find, or manually
4) updated has_many

Related

How can I get graphql-ruby to use joins when accessing subfields?

I have a model like this
class Foo
has_many :bars
end
and a query like this
query foos(
$offset: Int
$sort_by: String
$should_paginate: Boolean
) {
foos(
offset: $offset
sort_by: $sort_by
should_paginate: $should_paginate
) {
id
name
bars {
When I fetch this query, I get one select * from "foos" for each bar that's in the collection.
How can I have this all be smarter and do fewer SQL queries?
Look at https://github.com/Shopify/graphql-batch
It uses allows you to lazy-load your associations at once on demand.

Rails/Postgresql: Foreign keys stored in an array not returning all associated rows

I have two models
Product { id, name, tags_id[] }
Tag { id, name }
tags_id is an array that stores the ids of Tags.
class Product < ActiveRecord::Base
has_many :tags, foreign_key: 'id'
end
Let's say I have a product with two tags(1,2)
When I query for the product, it only loads one tag, the first one.
Product.includes(:tags).all
Here is how the query looks like:
SELECT "tags".* FROM "tags" WHERE "tags"."id" IN (1)
Is there an option I need to pass to has_many of Product to receive both the tags? Is this even possible?
Thanks for the help.
Try tag_ids, not tags_id column.
As I know it, you can't do that. Just place standard product_id column for tags, and remove tag_ids column.
Your current setup would not work.
You need to check has_array_of gem from here.

How to query an ActiveRecord table using conditions based on another table?

I have two models - Blog and BlogTag. Blog has_many :blog_tags and BlogTag belongs_to :blog:
blog.rb
has_many :blog_tags
blog_Tag.rb
belongs_to :blog
I want to query the database to select all blogs that have tags matching in the blog_tags table based on what a user enters in a form field. Something like this:
Blog.where(blog_tags contain [array of tags])
Is there a way to do this with ActiveRecord?
Assuming BlogTag has a column name.
Blog.joins(:blog_tags).where(blog_tags: { name: [array of tags] }).uniq
This would still return Blogs, but only blogs with blog tags whose name is in the array.
Another approach to this is by passing a BlogTag relation into a Blog scope.
Blog.where(id: BlogTag.where(name: tags).select(:blog_id))
So instead of a JOIN, ActiveRecord will construct a subquery
SELECT * FROM blogs WHERE id IN (
SELECT blog_id FROM blog_tags WHERE name IN ('tag1', 'tag2', 'tag3')
)

Fetch COUNT(column) as an integer in a query with group by in Rails 3

I have 2 models Category and Article related like this:
class Category < ActiveRecord::Base
has_many :articles
end
class Article < ActiveRecord::Base
belongs_to :category
def self.count_articles_per_category
select('category_id, COUNT(*) AS total').group(:category_id)
end
end
I'm accessing count_articles_per_category like this
Article.count_articles_per_category
which will return articles that have 2 columns: category_id and total.
My problem is that total column is a string. So the question is: is there a method to fetch that column as an integer?
PS: I tried to do a cast in the database for COUNT(*) and that doesn't help.
I try to avoid doing something like this:
articles = Article.count_articles_per_category
articles.map do |article|
article.total = article.total.to_i
article
end
No, there is no support in ActiveRecord to automatically cast datatypes (which are always transferred as strings to the database).
The way ActiveRecord works when retrieving items is:
for each attribute in the ActiveRecord model, check the column type, and cast the data to that type.
for extra columns, it does not know what data type it should cast it to.
Extra columns includes columns from other tables, or expressions.
You can use a different query, like:
Article.group(:category_id).count
Article.count(:group => :category_id)
These return a hash of :category_id => count. So you might get something like {6=>2, 4=>2, 5=>1, 2=>1, 9=>1, 1=>1, 3=>1}.
Using the count method works because it implicitly lets ActiveRecord know that it is an integer type.
Article.group(:category_id).count might give you something you can use. This will return a hash where each key represents the category_id and each value represents the corresponding count as an integer.

Which model relationship should be used here?

Table: Raw_Data
Fields: id
name
Table: Actual_Data
Fields: id
raw_data_id
name
A use can either add data manually to Actual_Data (in which case it's raw_data_id is NULL) or they can select a Raw_Data to insert into Actual_Data (in which case it's raw_data_id is set).
Is the following relationships correct in this case?
For Raw_Data:
-none-
For Actual_Data:
has_one :raw_data
You are right the relationship should be the same as you said,
class ActualDate < ActiveRecord::Base
has_one :raw_data
end
class RawData < ActiveRecord::Base
belong_to :actual_data
end
As per the rails convention, the foreign key should belongs to the table which has belongs_to association, so here actual_data_id should be in raw_datas table.
Edit:
We don't need raw_data_id in actual_datas table.
I guess the better option is belongs_to.
Raw_Data has many or has one Actual_Data
Actual_Data belongs to Raw Data.
You just have to remember to check if raw_data is nil before doing any operations.
manually_created = ActualData.create(:name => "Something");
builded = #RawData.build_actual_data(:name => "Something else");
The first will have the column set to null, and the second exaple, will set raw_data_id to #RawData.id value.

Resources