Creating items in groups in Rails - ruby-on-rails

My product table is
id type price location
1 chips $3 aisle3
I have a question with adding the products in groups.
There is a quantity field(nonmodel) where the user can enter the quantity
While adding a new product if the user enters:
type: soda
quantity: 3
Then there 3 records should be created in product model with type= soda like the following.
id type
2 soda
3 soda
4 soda
If user enters
location: aisle4
quantity: 2
Then
id location
5 ailse4
6 ailse4
Can you tell me how to pass the nonmodel field 'quantity' to the rails(model or controller) and how use it to add the products in groups as mentioned above? or should I create a column called quantity in my product table? Will the history be updated too for all these new records with after_create filter which I already have ?
Is there any good tutorial or book which shows how to pass such nonmodel html/javascript fields from view to rails and then back to the view?
Any help will be greatly appreciated.
Thanks

Try this:
class Product < ActiveRecord:Base
attr_accessor :quantity
def self.create_in_group(params)
size, i = params["quantity"].to_i, 0
size.times { Product.create(params);i+=1 }
i == size
end
end
class ProductsController < ApplicationController
def create
if Product.create_in_group(params[:product])
# success
else
# error
end
end
end
PS: In your view you can access the quantity field as though it is a product model field.

Related

Rails: filtering based on a child & parent's attribute calculation

I have 2 associated tables and would like to apply a filter based on tshirts (child table) length attribute which is +/- %5 of the parent object Student's height attribute
Unfortunately I receive an undefined method error for the parent table's name.
DB TABLES:
Student
------
id
name
height
Tshirt
------
id
color
student_id
length
MODELS:
class Student < ApplicationRecord
has_many :tshirts
class Tshirt < ApplicationRecord
belongs_to :student
def self.suitablesize
joins(:student).where('length < ? AND length > ?', (1.05*self.student.height),(0.95*self.student.height))
end
Controller:
def index
#tshirts = Tshirt.all.suitablesize
end
Error Message:
undefined method `student' for #<Class:0xc88cdc0>
EDIT:
I would like to get all tshirts which are suitable which are suitabile to owner student(s). Hence I do not want to find a single student to be an input parameter to scope method. Do you have any idea how I can solve this problem?
Explanation for the error
You are calling student on the Tshirt class, although it is an instant method:
joins(:student).where('length < ? AND length > ?', (1.05*self.student.height),(0.95*self.student.height))
Here self.student is the offending part.
Option 1: Shirts of a single student
If you want to take a student's height into account you would have to change the scope method to take a parameter:
def self.suitablesize(student)
where('length < ? AND length > ?', (1.05*student.height),(0.95*student.height))
end
And then provide the student in your controller method
def index
#tshirts = Tshirt.suitablesize([SOME STUDENT INSTANCE])
end
The part where I inserted [SOME STUDENT INSTANCE] would need to be a student instance that was e.g. retrieved via a parameter provided by the request before
def index
#student = Student.find(params[:id])
#tshirts = Tshirt.suitablesize(#student)
end
The exact parameter depends on your application (amongst other things the routes) so I can only offer general pointers.
Option 2: Shirts of all students
If it is not desired to find suitable shirts for an individual student one would have to place the calculations into the database:
def self.suitable_size
joins(:student)
.where('tshirts.length < 1.05 * students.height AND tshirts.length > 0.95 * students.height')
end
This would then return all shirts belonging to a student where the shirts length is +/- 5% of the students height.

Compare rows with similar data from two models

A DealerCommission table has the following attributes, among others:
phone_id, commission_name, payment, status, discrepancy, created_at
A CarrierCommission table has the following attributes, among others:
phone_id, commissions_name, payment, created_at
I want to select a range of dates for dealer commissions and compare records with the same phone_id to see if the payment amount match. If they match, I want to update the status to "paid." If they don't match, I want to update the status to "overpaid" or "underpaid." If there is no matching phone_id in the carrier_commission, update the status to "nonpaid." The discrepancy value is updated accordingly.
This is all set off by the user clicking a "reconcile" link that is linked to a "reconcile" action in the dealer commissions controller
I have the following non-working code:
# Dealer Commissions index
<%= link_to 'Reconcile', reconcile_dealer_commissions_path %>
# Dealer Commissions controller
def reconcile
DealerCommission.reconciliation
end
# Dealer Commission model
class DealerCommission < ActiveRecord::Base
belongs_to :dealer
def self.reconciliation
dealer_commissions = DealerCommission.where("created_at > Date.yesterday")
carrier_commissions = CarrierCommission.where("created_at > Date.yesterday")
dealer_commissions.find_each do |com|
if com.payment == carrier_commissions.payment
com.update(status: "Paid")
elsif com.payment < carrier_commissions.payment
com.update(status: "Underpaid")
elsif com.payment > carrier_commissions.payment
com.update(status: "Overpaid")
end
end
end
end
Obviously, the code doesn't reflect the full requirements but I at least wanted to get the comparison working.
I would be looking for a way to retrieve both carrier and dealer commissions in a single database query, using eager_load, and specifying a join condition with a sql fragment and using references.
http://guides.rubyonrails.org/active_record_querying.html#specifying-conditions-on-the-joined-tables
That ought to get you the matching dealer and carrier commission instances, and you can then perform your comparison and update the dealer commission appropriately.

ActiveRecord return uniq item by title condition nearest distance

I have following relation, because same product can exist in multiple stores, so DB stores the same product record in database with different store_id for each store, I also stores the coords for each product, now my query returns duplicate products by title for each store.
For quick fix how can I modify the query to it returns the closest products only and group by the product title maybe. BTW I am using geocode gem and near function to select nearby product near([#lat, #long], 20, order: #sort.blank? ? 'distance' : false)
class Product < ActiveRecord::Base
belongs_to :store
end
class Store < ActiveRecord::Base
has_many :products
end
ID TITLE STORE_ID
1 product_1 1
2 product_1 2
3 product_1 3
4 product_2 1
5 product_2 2
6 product_2 3
I think you have a misconception in your model. If the same product can be in several stores, then A product does NOT belong to a store. Cause it could be in several.
You should change your associations to a has_and_belongs_to_many or a has_many through one. But if you really want this query done, you can use the group method in your query.
Like Product.near(...).group(:title)
You can also filter after in Rails. Assuming it's already an ordered set, something like
#products.to_a.uniq(&:title)
would work.

How to add a non-existant column to a sql query

I have a little problem. I'm looking for a way to "add" a column to a sql query.
Actually I sort some product from a table with this order:
#prod = Table.find(:all,{:select=>["id, prod-id, cost"],:conditions=>["something = ? and somethingelse = ?","that thing","that other thing"],:order=>"id DESC"})
Then I put the result of this query into a Table (html) with a form to add the product into a Cart.
The problem comes now. In my Cart the product are like that:
cart: #<Cart:0x00000005ce0a68 #items=[[#<Table id: 6024, prod-id: 907509, cost: 33>]]>
And I need to add a "column" to the data in my cart. To get my Cart like that:
cart: #<Cart:0x00000005ce0a68 #items=[[#<Table id: 6024, prod-id: 907509, cost: 33, quantity: 1>]]>
Here is my Cart:
class Cart
attr_reader :items
def initialize
#items = []
#total_price = 0
end
def add_product(product)
#items << product
product
end
def total_price
#items.sum{ |item| item.prod_pxuttc}
end
def total_items
#items.length
end
end
I need to not-add any Column to my Table. Because I will have to import data from another Source Database into my Table, and I can't change the Source Database. (Yes it's a stupid process, but that's what my Customer want)
I have totaly no idea about how to give name to the process I need to do.
[edit]
I found a way to resolve my problem.
By creating a second table, with the same column plus column quantity, with a default empty row.
Then I select my product from First Table, the default row from the Second Table, and I put value from product into the variable of the default row. Then I put my new variable into my Cart.
It's a bit tricky but it works.
Maybe define Cart as the following will solve the problem.
class Product
attr_accessor quantity
end
class Cart
...
end

RoR sum related records during controller create

I have tables = expenses and invlines (invoice lines).
Expense belongs_to Invline
Invline has_many expenses
Using the Invlines input form, I have the user select the Expenses.
When the Invlines record is saved, I would like to summarize the expenses and place into invline.price
In the Invlines controller I'm trying to use:
def create
#invline = Invline.new(params[:invline])
#invline.price ||= #invline.expenses.amount.sum
But, I get
undefined method `amount'
Ideas?
Thanks!
Replace:
#invline.price ||= #invline.expenses.amount.sum
with
#invline.price ||= #invline.expenses.sum(:amount)
The .expenses call returns a list of expenses, but only a particular expense has amount.

Resources