Creating a table per account - ruby-on-rails

I have an SMS gateway with a central price table referenced by all accounts. However, there is a requirement for unique prices for different routes for accounts.
I cannot serve this from the same price table. I was thinking of having a prices table for every account which is created automatically on account creation and specific pricing can be defined for specific account.
Any idea how i can implement this in Ruby on Rails? How can i make sweeping changes accross all tables?
The schema for table looks like this;
create_table "prices", :force => true do |t|
t.string "country"
t.string "network"
t.decimal "price_euros", :precision => 10, :scale => 3
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.decimal "price_ugx", :precision => 10, :scale => 3
t.decimal "price_kes", :precision => 10, :scale => 3
t.decimal "price_tzs", :precision => 10, :scale => 3
t.decimal "price_usd", :precision => 10, :scale => 3
end
Thank you

Related

Rails Admin and dealing with Calculated Totals,Subtotals and Discount fields

Ok so I have a table orders, order_items, and items. Everything works fine except for 1 thing.
class CreateOrders < ActiveRecord::Migration[5.0]
def change
create_table :orders do |t|
t.integer :seller_id
t.integer :customer_id
t.string :shipping_method
t.string :shipping_terms
t.string :payment_method
t.date :delivery_date
t.date :due_date
t.decimal :total_discount, :precision =>8, :scale => 2
t.decimal :subtotal, :precision =>8, :scale => 2
t.decimal :sales_tax, :precision =>8, :scale => 2
t.decimal :total, :precision =>8, :scale => 2
t.timestamps
end
end
end
class CreateOrderItems < ActiveRecord::Migration[5.0]
def change
create_table :order_items do |t|
t.integer :order_id
t.integer :item_id
t.integer :quantity
t.decimal :discount, :precision =>8, :scale => 2
t.decimal :line_total, :precision =>8, :scale => 2
t.boolean :packed
t.string :packed_by
t.string :ffr
t.timestamps
end
end
end
class CreateItems < ActiveRecord::Migration[5.0]
def change
create_table :items do |t|
t.integer :sku
t.string :name
t.decimal :price, :precision =>8, :scale => 2
t.string :description
t.decimal :weight, :precision =>8, :scale => 2
t.timestamps
end
end
end
Basically there needs to be calculations done either as the items are being added to the order or before everything is saved.
On the Orders table the following needs to happen
Calculate : total_discount(dollar amount), sub_total, :sales_tax, :total
On OrderItems table the following needs to happen
Calculate : line_total, discount(dollar amount)
There has to be a sane way to do this but I have yet to figure it out. Either I really do not know what I am looking for or I am googling all the wrong things.

Customise database entries for every user

I have an e-commerce site where pricing for the prices are referenced in the prices table under the pricing model.
However, how can i be able to customise prices for individual clients for the same goods. How can i do that using the Price model.
I have tried adding user_id to the table but it seems have to price the same good for every individual client. How can i go about that?
The current table looks like this;
create_table "prices", :force => true do |t|
t.string "country"
t.string "network"
t.decimal "price_euros", :precision => 10, :scale => 3
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.decimal "price_ugx", :precision => 10, :scale => 3
t.decimal "price_kes", :precision => 10, :scale => 3
t.decimal "price_tzs", :precision => 10, :scale => 3
t.decimal "price_usd", :precision => 10, :scale => 3
end
There are various ways of achieving this. If each customer had the same discount across all goods, then you could add a discount attribute to the User model and apply this to the displayed prices.
If you want unique prices across the products which are unique for each user, then I would create a new model called UserPrice and have 3 attributes: user_id, product_id, price.
I would then have a method in my Product model called price_for_user along the following lines:
def price_for_user(user)
UserPrice.find_by_user_id_and_product_id(user.id,self.id).price
end
When iterating over your products in the view, you could write:
<%= #product.price_for_user(current_user) %>
Obviously, you'll need to adjust variables as required for your situation. I would also index the user_id and product_id columns in the UserPrice table for speed.
NB: If it was me, in my controller, I would also consider looking up all UserPrices by user and creating a hash and then in the view displaying the price by doing a lookup in the hash. This might be quicker.
def index
#products = Product.all
#user_prices = UserPrice.where(user_id: current_user.id).index_by(&:product_id)
end
In your view:
<%= #user_prices[product.id].price %>

Ruby on Rails ActiveRecord Database Migration Failure

I have a preexisting sqlserver database 'MyDatabase' populated with data. Within this database I have two schemas, 'dbo' and 'Master'.
dbo is the default schema and contains tables:
OWNER
LOCATION
Master schema contains tables:
BANK
ZONE
Tables OWNER, LOCATION, BANK, and ZONE contain several attributes a piece.
I have initialized a RoR server and have verified that the appropriate gems are installed (activerecord, tiny_tds, activerecord-sqlserver-adapter), as well as that in database.yml the correct information is provided such that a connection can be established. I ~am~ able to connect to the database. I am able to add and remove tables.
The unusual thing to me is that when I run rake db:migrate, only attributes from the dbo schema become automatically initialized in the schema.rb file of my RoR server:
ActiveRecord::Schema.define(:version => 20131014210258) do
create_table "BANK", :id => false, :force => true do |t|
end
create_table "LOCATION", :id => false, :force => true do |t|
t.string "VarA", :limit => 50
t.string "VarB", :limit => 50
t.decimal "VarC", :precision => 28, :scale => 0
t.integer "VarD"
t.string "VarE", :limit => 500
end
create_table "OWNER", :id => false, :force => true do |t|
t.string "VarF", :limit => 50
t.string "VarG", :limit => 50
t.string "VarH", :limit => 50
t.string "VarI", :limit => 50
t.string "VarJ", :limit => 50
end
create_table "ZONE", :id => false, :force => true do |t|
end
end
Why is it that the attributes are not automatically populated for tables from my Master schema? I have significantly reduced the scope of my database for this question...in actuality there are dozens of tables with dozens of attributes per, so doing the work manually is really not an option.
Is there a way to assign a specific schema(s) towards which ActiveRecord will default to search and generate attributes for?
Help! & Thank you in advance!

Rails scaffold strange undefined_method error for specific table

I'm currently working on an admin tool for an existing database and encountered a strange problem when scaffolding a particular table.
Here is the schema of the table using rake db:schema:dump:
create_table "locality", :force => true do |t|
t.integer "version", :limit => 8, :null => false
t.string "truth_id", :null => false
t.string "truth_record_id", :null => false
t.binary "deleted", :limit => 1, :null => false
t.string "internal_code", :null => false
t.string "iso_code"
t.string "materialized_path", :null => false
t.string "invariant_name", :null => false
t.binary "published", :limit => 1, :null => false
t.float "geo_point_latitude", :default => 0.0
t.float "geo_point_longitude", :default => 0.0
t.string "class", :null => false
t.integer "hut_count", :default => 0
t.integer "hotel_count", :default => 0
t.string "destination_url"
end
add_index "locality", ["truth_record_id"], :name => "truth_record_id", :unique => true
I used the schema_to_scaffold gem to create my scaffold from the dumped schema:
rails g scaffold locality version:integer truth_id:string truth_record_id:string
deleted:binary internal_code:string iso_code:string materialized_path:string
invariant_name:string published:binary geo_point_latitude:float
geo_point_longitude:float class:string hut_count:integer hotel_count:integer
destination_url:string
This workflow worked for a lot of other tables but when accessing /localities or Locality.all in the rails console all i get its:
irb(main):001:0> Locality.all
Locality Load (2.1ms) SELECT `locality`.* FROM `locality`
NoMethodError: undefined method `attribute_method_matcher' for "Country":String
Where does "Country":String come from?
At first I thought the model name 'locality' is somehow reservers by rails for i18n stuff but the same problem happens when naming the model 'Bla'.
I'm using rails 3.2.13 and a MySQL Database.
I believe that your column: class is invalid. How would you have access to that column since the class is already a method of any object in ruby?
I think that this causes the mess. The class column's value of your loaded locality is "Country" right?
So the problem was column named class, which ruby obviously hates.
Solution posted in this StackOverflow question: Legacy table with column named "class" in Rails
or more specifically in this blog post (Accessed 25.03.2013):
http://kconrails.com/2011/01/28/legacy-database-table-column-names-in-ruby-on-rails-3/

Rails 3 Association NoMethodError

I am relatively new to Rails and am a little bit in the Deep end.
I am working in Rails 3 with a pre-existing MSSQL DB and having to retrofit out the models to fit.
I seem to have created my models without too many issues but have hit an issue with associations.
Here's my Schema for the two tables in question
create_table "ip_addresses", :id => false, :force => true do |t|
t.integer "id", :null => false
t.integer "computer_id", :null => false
t.string "ip", :limit => 64, :null => false
t.string "ip_subnet", :limit => 64, :null => false
t.datetime "timestamp", :null => false
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "computers", :id => false, :force => true do |t|
t.integer "id", :null => false
t.string "uid", :limit => 128
t.string "enclosure_uid", :limit => 128
t.string "name", :limit => 128
t.integer "status_id", :null => false
t.integer "designation_id", :null => false
t.integer "hardware_type_id", :null => false
t.string "hardware_model", :limit => 128
t.string "processor_model", :limit => 128
t.integer "processor_speed"
t.integer "processor_cores_per_proc", :limit => 1
t.integer "processor_count"
t.decimal "memory", :precision => 9, :scale => 2
t.decimal "physical_disk", :precision => 9, :scale => 2
t.integer "san_disk"
t.string "os_name", :limit => 128
t.string "os_version", :limit => 128
t.string "os_patchlevel", :limit => 128
t.integer "campus_id", :null => false
t.text "description"
t.datetime "modification_date", :null => false
t.datetime "os_installdate"
t.datetime "created_at"
t.datetime "updated_at"
end
Here are the two models
class Computer < ActiveRecord::Base
has_many :ip_addresses
end
class IpAddress < ActiveRecord::Base
belongs_to :computer
end
It seems like the Association is working when I use the IpAddress Class, but not from the Computer class.
see below.
>> IpAddress.first.computer.name
"GC-PRD-PS02"
>> Computer.first.ip_addresses.ip
NoMethodError: undefined method `ip' for #<Class:0x10291cb18>
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.10/lib/active_record/base.rb:1014:in `method_missing'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.10/lib/active_record/associations/association_collection.rb:444:in `send'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.10/lib/active_record/associations/association_collection.rb:444:in `method_missing'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.10/lib/active_record/base.rb:1127:in `with_scope'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.10/lib/active_record/associations/association_proxy.rb:207:in `send'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.10/lib/active_record/associations/association_proxy.rb:207:in `with_scope'
from /usr/local/lib/ruby/gems/1.8/gems/activerecord-3.0.10/lib/active_record/associations/association_collection.rb:440:in `method_missing'
from (irb):40
What is strange is that I can see the entire row object of the IpAddress Class by using
>> Computer.first.ip_addresses
[#<IpAddress id: 175, computer_id: 687, ip: "10.0.246.80", ip_subnet: "255.255.255.192", timestamp: "2011-08-03 11:17:57", created_at: "2011-10-07 01:06:16", updated_at: "2011-10-07 01:06:16">, #<IpAddress id: 176, computer_id: 687, ip: "192.168.234.235", ip_subnet: "255.255.255.255", timestamp: "2011-08-03 11:17:57", created_at: "2011-10-07 01:06:16", updated_at: "2011-10-07 01:06:16">, #<IpAddress id: 177, computer_id: 687, ip: "192.168.159.1", ip_subnet: "255.255.255.0", timestamp: "2011-08-03 11:17:57", created_at: "2011-10-07 01:06:16", updated_at: "2011-10-07 01:06:16">, #<IpAddress id: 178, computer_id: 687, ip: "192.168.42.1", ip_subnet: "255.255.255.0", timestamp: "2011-08-03 11:17:57", created_at: "2011-10-07 01:06:16", updated_at: "2011-10-07 01:06:16">]
I have search quite a bit to try and work this one out. I'm sure it's just my way of doing associations. Any help would be much Appreciated.
Thanks,
Rob
As Computer.first.ip_addresses is an array, you need to do :
Computer.first.ip_addresses.first.ip
if you want the fist ip
Computer.first.ip_addresses.map(&:ip)
if you want all ips
Calling ip on a collection - that looks like the problem. Computer.first.ip_addresses[0].ip should work (presuming ip_addresses contains at least one element).
Also for learning, note what puts Computer.first.ip_addresses.class gives you.

Resources