I am trying to find all values of a given model by a combination of two fields.
I have the following model:
create_table "users", :force => true do |t|
t.string "name"
t.string "url"
t.integer "clicks_given"
t.integer "clicks_received"
t.datetime "created_at"
t.datetime "updated_at"
end
and I have defined this method for the model:
def credits
credits = self.clicks_given - self.clicks_received
end
I am trying to find all users above a given credits:
#users = User.find(:all, :conditions => { "credits >= ?", -5 })
and:
#users = User.find(:all, :conditions => { "clicks_given - clicks_received >= ?", -5 })
Fail. What should is the correct statement to to find the right users?
Pass the condition as an array instead of a hash:
#users = User.find(:all, :conditions => [ "clicks_given - clicks_received >= ?", -5 ])
The first version will not work since "credits" is not a database column.
EDIT:
Or in Rails 3 syntax, with your order:
#users = User.where("clicks_given - clicks_received >= ?", 5).order("clicks_given - clicks_received")
Why don't directly use -5 in condition like this:
#users = User.find(:all,
:conditions =>"clicks_given-clicks_received>=-5")
and if you have a variable in place of -5 then you can write something like this:
#users = User.find(:all,
:conditions => ["clicks_given-clicks_received >= ?",-5])
Related
Hi Im creating an ec site in my rails.
My migration:
(Item) has :name and :price.
(Basket_Item) has :item_id(fk), :basket_id(fk) and :quantity.
The system User will add some items to their basket.
So Basket_items is JOIN Table between (Item) and (Basket)
see like below.
What I want to do:
Get a price of Item and get a quantity from Basket_Items which is selected by user. Then I want to create #total_price = item_price * item_quantity.
Can anyone help me to create the #total_price please.
This is my a try code but it doesn't work on rails console.
Basket_items
class CreateBasketItems < ActiveRecord::Migration[5.2]
def change
create_table :basket_items do |t|
t.references :basket, index: true, null: false, foreign_key: true
t.references :item, index: true, null: false, foreign_key: true
t.integer :quantity, null: false, default: 1
t.timestamps
end
end
end
///
Items
class CreateItems < ActiveRecord::Migration[5.2]
def change
create_table :items do |t|
t.references :admin, index: true, null: false, foreign_key: true
t.string :name, null: false, index: true
t.integer :price, null: false
t.text :message
t.string :category, index: true
t.string :img
t.string :Video_url
t.text :discription
t.timestamps
end
end
end
///
This is my try a code but it doesn't work on rails console.
basket = current_user.prepare_basket
item_ids = basket.basket_items.select(:item_id)
items = basket.items.where(id: item_ids)
items_price = items.select(:price)
items_quantity = basket.basket_items.where(item_id: item_ids).pluck(:quantity)
def self.total(items_price, items_quantity)
sum(items_price * items_quantity)
end
#total_price = basket.total(items_price, item_quantity)
There are a few issues with your code:
You are trying to call a class method on an instance of the class. That's not gonna work, second you are passing in arrays into the calculation.
basket = current_user.prepare_basket
item_ids = basket.basket_items.select(:item_id)
items = basket.items.where(id: item_ids)
items_price = items.select(:price) # => Array of prices from the items in the basket
items_quantity = basket.basket_items.where(item_id: item_ids).pluck(:quantity) # => Array of quantities from the items in the basket
def self.total(items_price, items_quantity)
sum(items_price * items_quantity) # => So this line will do: sum(['12,95', '9.99'] * [1, 3])
end
#total_price = basket.total(items_price, item_quantity)
As you can see, that ain't gonna work. First you need to change the method and remove the self.
def total(items_price, items_quantity)
# ...
end
Now you can call the total method on a basket object: basket.total(items_price, items_quantity)
And inside the total method you need to loop through each items to do the calculation and add all the results.
def total(items_price, items_quantity)
total_price = 0
items_price.each_with_index do |price, index|
total_price += price * items_quantity[index]
end
total_price
end
But this solution could also fail, because you don't know sure that the order in the items_price is matching with the order of items_quantity. So a better approach would be to do the calculation for each basket_item seperate.
# Basket model
def total
total_price = 0
basket_items.each do |basket_item|
total_price += basket_item.total_price
end
total_price
end
# BasketItem model
def total_price
quantity * item.price
end
Now you can call it like this: basket.total
I'm trying to use the filterrific gem on a rails app to filter cities by a price lower than $1000 for example. - https://github.com/jhund/filterrific
but can't seem to set it up, i've added the code to the model and controllers but I get undefined method `sorted_by' for #<City::ActiveRecord_Relation:0x00007fc191173040> Did you mean? sort_by
Model -
class City < ApplicationRecord
has_one :guide, dependent: :destroy
filterrific(
default_filter_params: { sorted_by: 'created_at_desc' },
available_filters: %i[
sorted_by
search_query
with_created_at_gte
]
)
end
Controller -
class CitiesController < ApplicationController
def index
#cities = City.all
(#filterrific = initialize_filterrific(
City,
params[:filterrific]
)) || return
#cities = #filterrific.find.page(params[:page])
respond_to do |format|
format.html
format.js
end
end
Schema -
create_table "cities", force: :cascade do |t|
t.string "name"
t.string "internet"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "weather"
t.string "image"
t.string "country"
t.string "price"
end
It looks like you have copied and pasted the example from the documentation without really understanding what you are trying to do.
The error message is coming from your default_filter_params here:
filterrific(
default_filter_params: { sorted_by: 'created_at_desc' }, <<<
...
)
For this to work you need a sorted_by scope which takes a parameter 'created_at_desc'. There are examples in the documentation here: http://filterrific.clearcove.ca/pages/active_record_scope_patterns.html
An example for the sorted_by scope would be:
scope :sorted_by, (lambda do |sort_option|
direction = (sort_option =~ /desc$/) ? 'desc' : 'asc'
case sort_option.to_s
when /^created_at_/
order("cities.created_at #{ direction }")
when /^name_/
order("cities.name #{ direction }")
else
raise(ArgumentError, "Invalid sort option: #{ sort_option.inspect }")
end
end)
to filter by price you will also need a scope like so:
scope :with_price_lte, (lambda do |price|
where('price >= ?', price)
end)
so your model filterrific clause should look like:
filterrific(
default_filter_params: { sorted_by: 'created_at_desc' },
available_filters: %i[
sorted_by
with_price_lte
]
)
There's more to it as you have to have a filterrific form in your view which returns the parameters for your scopes and an index.js.erb view which updates your list of cities, but this should help you get a little further.
I got this query and would like to order the results by 'delivery_time':
d = Date.today.at_midnight
orders = car.orders.where("finished_at IS NOT NULL AND delivery_time > ?", d).order(delivery_time: :desc)
The problem is, the order method doesn't work - it still gets ordered by id! Whatever I put into the order method arguments doesn't seem to work.
This is what my orders table partially looks like:
create_table "orders", force: true do |t|
t.datetime "delivery_time"
t.datetime "finished_at"
t.datetime "created_at"
t.datetime "updated_at"
end
car.rb:
has_many :orders, -> { order "delivery_time ASC" }
.explain output:
SELECT `orders`.* FROM `orders` WHERE `orders`.`car_id` = 1 AND (finished_at IS NOT NULL AND delivery_time > '2014-09-09 03:00:00') ORDER BY delivery_time ASC, `orders`.`delivery_time` DESC
In order to override ordering, try using reorder instead of order.
orders = car.orders.where(
"finished_at IS NOT NULL AND delivery_time > ?", d
).reorder(delivery_time: :desc)
I have...
/app/models/search.rb:
serialize :result
def multisearch
self.result = PgSearch.multisearch(self.term)
self.status = "closed"
self.save
return result
end
/db/schema.rb:
create_table "searches", :force => true do |t|
t.string "term"
t.string "status"
t.text "result"
end
I get the following error when I try `self.save?
ArgumentError: wrong number of arguments (2 for 1)
from /Users/steven/.rvm/gems/ruby-1.9.2-p320/gems/arel-3.0.2/lib/arel/expressions.rb:3:in `count'
I get a similar error when I test result.serialize:
ArgumentError: wrong number of arguments (0 for 1)
from /Users/steven/.rvm/gems/ruby-1.9.2-p320/gems/activerecord-3.2.11/lib/active_record/attribute_methods/serialization.rb:49:in `serialize'
How can I fix this?
Answer was to convert to an array before serialization: self.result = PgSearch.multisearch(self.term).to_a
I have a call on my posts_controller.rb index action:
#articles = Article.order("id desc")
I now want to be able to order by:
date
id
some_counter_attribute
My querystring will have sort=date/id/count like:
www.example.com/articles/?sort=date
How should I implement this in my controller now? Should I just use if statements?
if params[:sort] == "date"
#articles = Article.order("created_at desc")
elsif params[:sort] == "count"
#articles = ...
..
Or is there a better way?
Should this logic be in the controller or Model ideally?
Try this:
class ArticlesController
def index
#articles = Article.order(sort_order)
end
private
def sort_order
##sort_order ||= {
"date" => "created_at DESC",
"id" => "id DESC",
"comments" => "comment_count ASC"
}
##sort_order[params[:sort]]
end
end
Off course there are gems for doing this sort of things:
MetaSearch
SearchLogic
Straightforward approach could be:
#articles = Article.order("#{params[:sort]} desc")
But for "date" you have to sort by created_at. So try this:
mylist = {"date" => "created_at",
"id" => "id",
"counter" => "some_counter_attribute"}
#articles = Article.order("#{mylist[params[:sort]]} desc")