Ruby on Rails - Increment by 1 from last object - ruby-on-rails

I am building a user gallery application, where user can create albums and upload images to their album. I am using nested forms for images.
In my images database, I have a column called sort_order. I want to use sort_order to manage the sorting and showing user, for ex: he is seeing 3 of 12 images, where 3 is number of sort_order and 12 is number of total images in that album.
sort_order is integer and default: 0. What I looking for is to increase/increment number of sort_order for each image based on previous sort_order of last image in same album.
For ex: image 1 will have sort_order: 1, image 2 will then have previous images sort_id +1 => sort_order: 2 and so on.
Here is the code I am using now:
after_create :previous_image
def previous_image
img = user.images.order("id ASC")
img.each do |image|
image.increment!(:sort_order, self.sort_order + 1)
end
end
This does the work but in wrong sort.
id sort_order
10 3
11 2
12 1
instead of having, id: 10 sort_order: 1, its getting 3.
This is the log:
SQL (0.5ms) UPDATE "images" SET "sort_order" = ?, "updated_at" = ? WHERE "images"."id" = ? [["sort_order", 1], ["id", 398]]
user Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 160]]
Slide Load (0.1ms) SELECT "images".* FROM "images" WHERE "images"."user_id" = ? ORDER BY id DESC [["user_id", 160]]
SQL (0.1ms) UPDATE "images" SET "sort_order" = ?, "updated_at" = ? WHERE "images"."id" = ? [["sort_order", 1], ["id", 399]]
SQL (0.1ms) UPDATE "images" SET "sort_order" = ?, "updated_at" = ? WHERE "images"."id" = ? [["sort_order", 2], ["id", 398]]
user Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 160]]
Slide Load (0.1ms) SELECT "images".* FROM "images" WHERE "images"."user_id" = ? ORDER BY id DESC [["user_id", 160]]
SQL (0.1ms) UPDATE "images" SET "sort_order" = ?, "updated_at" = ? WHERE "images"."id" = ? [["sort_order", 1], ["id", 400]]
SQL (0.1ms) UPDATE "images" SET "sort_order" = ?, "updated_at" = ? WHERE "images"."id" = ? [["sort_order", 2], ["id", 399]]
SQL (0.1ms) UPDATE "images" SET "sort_order" = ?, "updated_at" = ? WHERE "images"."id" = ? [["sort_order", 3], ["id", 398]]
It starts from bottom and not top. How can I fix it?
If there is another way to do it without having the sort_order column, I am open to it.

After receiving the form data, add an index (starting from 1) to the images array.
Considering this is your images array from the form:
images = [{name: 'Image 1', data: 123}, {name: 'Image 2', data: 456}]
Use with_index(1) to attach the sort order to every element:
images.map.with_index(1).to_a
=> [[{:name=>"Image 1", :data=>123}, 1], [{:name=>"Image 2", :data=>456}, 2]]

Related

How to avoid destroy deleting earlier related object

If the user already has a favorite model after log in, then I want the products that were added to their anonymous bookmarks to be overwritten in the favorite that is attached to their user object.
I find session_favorite (anonymous favorite), #favorite, which belongs to the user. I am rewriting line_item.favorite with the ID of session_favorite to the user's ID favorite. I reset the session and destroy that anonymous favorite, which in theory has become empty, since now line_items has the user's favorite ID.
But, for some reason, when destroying a session_favorite, line_items are also deleted. Why?
module CurrentFavorite
def set_favorite
if user_signed_in?
set_user_favorite
else
if session[:favorite]
#favorite = Favorite.find(session[:favorite])
else
#favorite = Favorite.create
session[:favorite] = #favorite.id
end
end
end
def set_user_favorite
if session[:favorite]
if current_user.favorite.nil?
#favorite = Favorite.find(session[:favorite])
session[:favorite] = nil
#favorite.update(user: current_user)
else
#block with error
session_favorite = Favorite.find(session[:favorite])
#favorite = Favorite.find_by(user: current_user)
session_favorite.line_items.each do |line_item|
line_item.update(favorite: #favorite)
end
session[:favorite] = nil
session_favorite.destroy
#favorite
end
else
if current_user.favorite.nil?
#favorite = current_user.build_favorite
#favorite.save
else
#favorite = Favorite.find_by(user: current_user)
end
end
end
end
LineItem Update (0.7ms) UPDATE "line_items" SET "favorite_id" = ?, "updated_at" = ? WHERE "line_items"."id" = ? [["favorite_id", 1], ["updated_at", "2020-06-07 05:19:54.653064"], ["id", 13]]
↳ app/models/concerns/current_favorite.rb:31
(12.9ms) commit transaction
↳ app/models/concerns/current_favorite.rb:31
(0.0ms) begin transaction
↳ app/models/concerns/current_favorite.rb:31
Movie Load (0.1ms) SELECT "movies".* FROM "movies" WHERE "movies"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
↳ app/models/concerns/current_favorite.rb:31
LineItem Update (0.7ms) UPDATE "line_items" SET "favorite_id" = ?, "updated_at" = ? WHERE "line_items"."id" = ? [["favorite_id", 1], ["updated_at", "2020-06-07 05:19:54.674229"], ["id", 14]]
↳ app/models/concerns/current_favorite.rb:31
(3.6ms) commit transaction
↳ app/models/concerns/current_favorite.rb:31
(0.0ms) begin transaction
↳ app/models/concerns/current_favorite.rb:34
LineItem Destroy (0.5ms) DELETE FROM "line_items" WHERE "line_items"."id" = ? [["id", 13]]
↳ app/models/concerns/current_favorite.rb:34
LineItem Destroy (0.1ms) DELETE FROM "line_items" WHERE "line_items"."id" = ? [["id", 14]]
↳ app/models/concerns/current_favorite.rb:34
Favorite Destroy (0.2ms) DELETE FROM "favorites" WHERE "favorites"."id" = ? [["id", 10]]
↳ app/models/concerns/current_favorite.rb:34
session_favorite still has the set of line_items associated with it. For performance reasons, Rails does not automatically reload the line_items before destroying the session_favorite so it doesn't recognize that the line_items are now associated with a different favorite.
To prevent the line_items being destroyed, refresh the association before doing the destroy:
session_favorite.line_items.reload
session_favorite.destroy

Rails join with where using AND instead of OR

I have a scope (where title is an array)
scope :with_label, ->(title) { joins(:labels).where(labels: { title: title }) }
By default this does an AND query. How can I get this to do an OR query? I can't seem to find any examples of this.
I believe this is the SQL that is generated:
Label Load (0.1ms) SELECT "labels".* FROM "labels" WHERE "labels"."project_id" = $1 AND "labels"."title" = $2 ORDER BY "labels"."title" ASC LIMIT 1 [["project_id", 8], ["title", "label1,label2,label3"]]
Rails/ActiveRecord only supports OR queries in Rails 5. In earlier versions, you need to use a SQL string to achieve an OR query:
Widget.where("name = ? OR name = ?", "foo", "bar") # postgres
When there are many possibilities, the same thing can be accomplished more efficiently with an IN query, which is generated in ActiveRecord by passing an array with more than one element to the #where method:
arr = ["foo", "bar", "baz"]
Widget.where(name: arr)
As for the SQL output you've posted:
Label Load (0.1ms) SELECT "labels".* FROM "labels" WHERE "labels"."project_id" = $1 AND "labels"."title" = $2 ORDER BY "labels"."title" ASC LIMIT 1 [["project_id", 8], ["title", "label1,label2,label3"]]
The AND here is coming from the fact that a query is being made against the product_id as well as the title, not because of anything to do with title.

Rails where clause is not working for some of the values

I am working on Easy Redmine PMS and I have written where query in rails Like:
Tracker.where(name: "+ Permits Required")
but it returns less values whereas when I have tried detect query for getting same data Like:
Tracker.all.detect{|i| i.name == "+ Permits Required"
And it is returning all the values. Also I noticed that when fetching the data directly in database then I get the value as Request Available whereas rails console returns Permits Required. I have tried this issue with postgresql and mysql both the databases and the issue is same. Here are the queries:
2.1.1 :001 > #tra = Tracker.find_by_name("+ Camps & Finished Food Store")
Tracker Load (32.8ms) SELECT "trackers".* FROM "trackers" WHERE "trackers"."name" = $1 LIMIT 1 [["name", "+ Camps & Finished Food Store"]]
=> nil
2.1.1 :002 > #tra = Tracker.all.detect{|i| i.name == ("+ Camps & Finished Food Store")}
Tracker Load (0.9ms) SELECT "trackers".* FROM "trackers"
AnonymousUser Load (27.4ms) SELECT "users".* FROM "users" WHERE "users"."type" IN ('AnonymousUser') ORDER BY "users"."id" ASC LIMIT 1
EasyTranslation Load (28.6ms) SELECT "easy_translations".* FROM "easy_translations" WHERE "easy_translations"."entity_id" = $1 AND "easy_translations"."entity_type" = $2 AND "easy_translations"."entity_column" = $3 AND "easy_translations"."lang" = $4 ORDER BY "easy_translations"."id" ASC LIMIT 1 [["entity_id", 3], ["entity_type", "Tracker"], ["entity_column", "name"], ["lang", "en"]]
EasyTranslation Load (1.5ms) SELECT "easy_translations".* FROM "easy_translations" WHERE "easy_translations"."entity_id" = $1 AND "easy_translations"."entity_type" = $2 AND "easy_translations"."entity_column" = $3 AND "easy_translations"."lang" = $4 ORDER BY "easy_translations"."id" ASC LIMIT 1 [["entity_id", 4], ["entity_type", "Tracker"], ["entity_column", "name"], ["lang", "en"]]
EasyTranslation Load (0.7ms) SELECT "easy_translations".* FROM "easy_translations" WHERE "easy_translations"."entity_id" = $1 AND "easy_translations"."entity_type" = $2 AND "easy_translations"."entity_column" = $3 AND "easy_translations"."lang" = $4 ORDER BY "easy_translations"."id" ASC LIMIT 1 [["entity_id", 5], ["entity_type", "Tracker"], ["entity_column", "name"], ["lang", "en"]]
2.1.1 :003 > #tra = Tracker.where(name: "+ Camps & Finished Food Store")
Tracker Load (0.8ms) SELECT "trackers".* FROM "trackers" WHERE "trackers"."name" = $1 [["name", "+ Camps & Finished Food Store"]]
Tracker.where(name: "Permits Required")

Spree currency convertor is not working for AED

I have included following gem in my gem file
gem 'spree_multi_currency', github: 'spree/spree_multi_currency', branch: '2-3-stable'
in my application following currencies are already present:
SGD,USD,EUR,AUD,GBP,PHP,THB,MYR
and these are converting price properly. But my requirement is to add AED currency to so I have added that also SGD,USD,EUR,AUD,GBP,PHP,THB,MYR,AED from backend
Now I automatically got this option in my header now when i click on AED it gives me following error
Started GET "/assets/world-globe.png" for 127.0.0.1 at 2016-01-26 10:26:08 +0100
Started POST "/currency/set" for 127.0.0.1 at 2016-01-26 10:26:11
+0100 Processing by Spree::CurrencyController#set as JSON Parameters: {"currency"=>"AED"} Spree::Country Load (1.1ms) SELECT "spree_countries".* FROM "spree_countries" WHERE "spree_countries"."name" = 'N/A' LIMIT 1 Spree::User Load (1.2ms) SELECT "spree_users".* FROM "spree_users" WHERE "spree_users"."id" = 1 ORDER BY "spree_users"."id" ASC LIMIT 1 Spree::Order Load (1.2ms) SELECT "spree_orders".* FROM "spree_orders" WHERE "spree_orders"."completed_at" IS NULL AND "spree_orders"."currency" = 'USD' AND "spree_orders"."guest_token" = 'ZtR5IUlQUC40ueZBlo21Pg' AND "spree_orders"."user_id" = 1 LIMIT 1 Spree::Adjustment Load (1.4ms) SELECT "spree_adjustments".* FROM "spree_adjustments" WHERE "spree_adjustments"."adjustable_type" = 'Spree::Order' AND "spree_adjustments"."adjustable_id" IN (6084) ORDER BY spree_adjustments.created_at ASC Spree::Order Load (0.9ms) SELECT "spree_orders".* FROM "spree_orders" WHERE "spree_orders"."user_id" = $1 AND "spree_orders"."completed_at" IS NULL AND (id != 6084) [["user_id", 1]] (0.9ms) BEGIN Spree::Order Exists (1.7ms) SELECT 1 AS one FROM "spree_orders" WHERE ("spree_orders"."number" = 'R501407003' AND "spree_orders"."id" != 6084) LIMIT 1 Spree::LineItem Load (1.3ms) SELECT "spree_line_items".* FROM "spree_line_items" WHERE "spree_line_items"."order_id" = $1 AND (currency != 'AED') ORDER BY created_at ASC [["order_id", 6084]] Spree::Variant Load (1.3ms) SELECT "spree_variants".* FROM "spree_variants" WHERE "spree_variants"."id" = $1 LIMIT 1 [["id", 2]] Spree::Price Load (1.3ms) SELECT "spree_prices".* FROM "spree_prices" WHERE "spree_prices"."deleted_at" IS NULL AND "spree_prices"."variant_id" = $1 AND "spree_prices"."currency" = 'AED' ORDER BY "spree_prices"."id" ASC LIMIT 1 [["variant_id", 2]] Spree::Product Load (1.3ms) SELECT "spree_products".* FROM "spree_products" WHERE "spree_products"."id" = $1 LIMIT 1 [["id", 2]] Spree::Product::Translation Load (1.3ms) SELECT "spree_product_translations".* FROM "spree_product_translations" WHERE "spree_product_translations"."spree_product_id" = $1 [["spree_product_id", 2]] (1.5ms) ROLLBACK Completed 500 Internal Server Error in 56ms
RuntimeError - no AED price found for 28 Day Ultimate Teatox (28 Day): () Users/TopFormInvestment/.rvm/gems/ruby-2.1.4#skinnymint/bundler/gems/spree-cfe7e96539b6/core/app/models/spree/order/currency_updater.rb:34:in `update_line_item_price!' () Users/TopFormInvestment/.rvm/gems/ruby-2.1.4#skinnymint/bundler/gems/spree-cfe7e96539b6/core/app/models/spree/order/currency_updater.rb:18:in `block in update_line_item_currencies!'
Please guide me how to solve this error. As I am new in spree
Go to the Products in admin panel. There you can see the price tab, click the tab and then you change the prices there itself.
You did not set an AED price for the variant 28 Day Ultimate Teatox. In update_line_items_price! it has a local variable price which returns the variants price in the newly set currency. If the price isn't present it will raise the RuntimeError you are getting.
def update_line_item_currencies!
line_items.where('currency != ?', currency).each do |line_item|
update_line_item_price!(line_item)
end
end
# Returns the price object from given item
def price_from_line_item(line_item)
line_item.variant.prices.where(currency: currency).first
end
# Updates price from given line item
def update_line_item_price!(line_item)
price = price_from_line_item(line_item)
if price
line_item.update_attributes!(currency: price.currency, price: price.amount)
else
raise RuntimeError, "no #{currency} price found for #{line_item.product.name} (#{line_item.variant.sku})"
end
end

ActsAsTaggableOn: tags not persisting in DB

I'm using the acts_as_taggable_on (3.4) plugin for tagging with Rails (4.2.4). I've tried adding custom tags both via my seed file and the console and while it appears to add the attributes, I can't then access them.
My model:
class Recipe < ActiveRecord::Base
acts_as_taggable_on :tags
acts_as_taggable_on :dietaries, :meals, :cuisines, :sources
end
Seed file:
tarte = Recipe.create(title: "Caramelized Tomato Tarte Tatin", url: "www.chocolateandzucchini.com", notes: "Lorem ipsum", favorite: false)
tarte.dietary_list.add("vegetarian," "vegan")
tarte.meal_list.add("appetizers", "mains", "dinner")
tarte.cuisine_list.add("French")
tarte.source_list.add("Chocolate and Zucchini")
Console steps (after running seed to create the recipe in the seed file above):
tarte = Recipe.first
tarte.dietary_list.add("vegetarian," "vegan")
tarte.meal_list.add("appetizers", "mains", "dinner")
tarte.cuisine_list.add("French")
tarte.source_list.add("Chocolate and Zucchini")
When I call Recipe.first.dietary_list, it runs a query
Recipe Load (0.6ms) SELECT "recipes".* FROM "recipes" ORDER BY "recipes"."id" ASC LIMIT 1
ActsAsTaggableOn::Tag Load (0.7ms)SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND (taggings.context = 'dietaries' AND taggings.tagger_id IS NULL) [["taggable_id", 1], ["taggable_type", "Recipe"]]
But it returns an empty array:
=> []
If I call Recipe.first.dietaries, it returns an empty Collection Proxy:
Recipe Load (0.6ms) SELECT "recipes".* FROM "recipes" ORDER BY "recipes"."id" ASC LIMIT 1
ActsAsTaggableOn::Tag Load (0.5ms) SELECT "tags".* FROM "tags" INNER JOIN "taggings" ON "tags"."id" = "taggings"."tag_id" WHERE "taggings"."taggable_id" = $1 AND "taggings"."taggable_type" = $2 AND "taggings"."context" = $3 [["taggable_id", 1], ["taggable_type", "Recipe"], ["context", "dietaries"]]
=> #<ActiveRecord::Associations::CollectionProxy []>
Is there something about using this tool that I'm missing? Alternatively, are there better tagging tools out there?
Solved by calling .save after entering all tags

Resources