Ruby on Rails ActiveRecord select - ruby-on-rails

I am trying to create a ActiveRecord database by using Ruby on Rails
I have created a database Schema:
To create tables destinations, productions, rules I am using rails generate model Name parameter:integer
How to create a table rule_input with foreign key to rule?
Also, how to create a table or a model sources that would join all these tables and I could get source like: source = Source.find(1) and for example render json: {source: source}?

How to create a table rule_input with foreign key to rule?
Assuming you are asking for cli command - "rails generate model rule_input rule:references"
Also, how to create a table or a model sources that would join all these tables and I could get source like: source = Source.find(1) and for example render json: {source: source}?
Single table inheritance may be a possible solution here.
class Source < ActiveRecord::Base; end
class Rule < Source
has_many :rule_inputs
end
class Production < Source; end
class Destination < Source; end
class RuleInput < ActiveRecord::Base
belongs_to :rule
end
Basically single table inheritance lets different models inherit from a parent model within a single table, as long as your data structure between models are fairly similar this would be a viable option for you. (STI eliminate having 3 tables with all the same columns)

As #maxhungry mentioned you can do STI (Single Table Inheritance) to eliminate using three tables Rules, Productions and Destinations and replace it with "type" column using Source model.
Here are some good articles on STI and about refactoring such models.
https://about.futurelearn.com/blog/refactoring-rails-sti/
http://samurails.com/tutorial/single-table-inheritance-with-rails-4-part-1/
And about your question - do I need to think about model as an object or as a table?
Model is not same as Table as we can have table-less models. You may read this Rails model without a table. So if you subclass your model from ActiveRecord::Base then it will point to a Table. For example, this code
class Product < ActiveRecord::Base
end
This will create a Product model, mapped to a products table at the database. But if you just say
class Product
end
then its a table-less model.

Related

Is it possible to use a joined table as a basis for a model?

What are my options for molding existing database table(s) to my model in rails? I have a has_one and belongs_to relation between two tables, but I'd like to join them and use that as a model (and select only the fields relevant). As this is an external table I'd also like to minimize the amount of queries.
I am inheriting an existing app and would like to not touch anything from the existing environment and slowly migrate. The existing database seems to have been made different from the rails way. I have a model of IdCard and IdCardRequest. One would assume that one IdCard hasmany IdCardRequests, however the IdCard has a property to the last IdCardRequest. It seems that the basic info such as applicant_name is a property of the IdCardRequest rather than IdCard. Luckily they both have a common property id_card_number and I could join it based on that by specifying foreign_key and primary_key to id_card_number. However for now I'd like a model IdCard with the rest of the fields of the IdCardRequest as property.
class IdCard < ExternalTable
self.table_name = 'id_cards'
belongs_to :security_id_request, :foreign_key => 'request_id'
default_scope { includes(:id_request) }
end
class IdRequest < ExternalTable
self.table_name = 'id_request'
has_one :id_card, :foreign_key => 'request_id'
end
# I would like IdCard.first.applicant_lastname
# I have to call IdCard.first.id_request.applicant_lastname
# I have to call IdCard.first.id_request.applicant_firstname
# I could write a delegate_to for every property, but this seems cumbersome and inefficient.
Do you have the option of creating a database view that encapsulates both tables, and renames columns to rails conventions?
e.g.
create view id_card_requests as
select
existing_column as desired_rails_column_name,
...
from id_cards
join id_card_requests on <whatever the join is>
You can then make a rails model IdCardRequests that will work as normal. You can make one of the columns a primary key in the view, or tell the model to use one of the columns with self.primary_key = :my_key_column

Creating an activerecord object with new relationship from select query

I would like to create a list of model objects that designate a new relationship without having to use raw sql.
Suppose I have the following models:
class MealCombination < ActiveRecord::Base
belongs_to :drink
belongs_to :food
end
class Food < ActiveRecord::Base
has_many :meal_combinations
end
class Drink < ActiveRecord::Base
has_many :meal_combinations
end
I would like to create a list of MealCombination objects that do not presently exist in the database.
Say my query would look something like this:
select distinct DRINK.id, FOOD.id from FOOD, DRINK where DRINK.alchohol_volume > 5 and FOOD.spice_factor > 45;
What is the most efficient way to create the MealCombination objects from this selection?
Iterating through an array returned back from the raw sql seems inefficient. I do not want to persist the objects into the database.
The easiest way to do this would probably be to create a view called "meal_combinations" in your database which will represent your select query you want to do. ActiveRecord should treat the view as a table for the most part, but you should definitely add
def read_only?
true
end
to any class definition that uses a view. The main disadvantage to having a lot of views is that they make database migrations a little more of a pain to manage if you ever want to change columns in the underlying tables.

One table - two models

I have hierarchical structure for model Board (implemented using ancestry gem).
Instead of one model and some scopes, I'd like to have two models: Board for root level elements (ancestry column value is nil), and Category for the rest(ancestry column value is not nil). They would be using the same table boards.
How can I do something like this?
You can explicity define a table for a model using set_table_name or self.table_name depending on your rails version. Also you can define a default scope for every query made for this model, using default_scope, so a combination of both should be what you are searching for:
class Category < AR:Base
self.table_name = 'boards'
default_scope where('boards.ancestry IS NOT NULL')
end
You could specify the table name of the category model and generate a default scope:
class Category < ActiveRecord::Base
self.table_name = "boards"
default_scope where('boards.ancestry IS NOT NULL')
end
And you should be able to interact with both models wit the boards-Table.
Or you stay with one model and add two modules for the specific stuff. That depends on your preferences.

Seed a has_and_belongs_to_many table relationship

I have a project with 2 models linked through a habtm relationship and
would like to seed the default relationships values as they are fixed and needed for the
web aplication to work.
Can't seem to find a way to access the model join table and seed the default values to the object1_id, object2_id as the table is not linked to a model. It's currently being done via SQL directly on postgreSQL.
Any suggestions?
You would need to generate a join table if you have not already done so:
rails g migration CreateJoinTable users roles
And as long as you have habtm in their respective classes:
# app/models/user.rb
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
end
Just push the object you are creating onto the associative array:
# db/seeds.rb
bill = User.create(name: "bill")
bill.roles << Role.create(title: "admin")
If you can think of any place where you would want to access the model directly, create the model. Otherwise direct sql query is probably fine.

rails how to mapping a virtual view to a model

class CashOrderStatus < ActiveRecord::Base
belongs_to:cash_order
end
usually the db need a table cash_order_statuses to mapping this model,but now i want to
mapping this model to a specific sql view like
select * from order_statues where cash_order_id is not null <=> CashOrderStatus
does rails provide some way to achieve this
There are multiple ways to fulfill your requirement:
In your CashOrderStatus model, you can set table name to override default ORM mapping:
class CashOrderStatus > ActiveRecord::Base
set_table_name "order_statuses"
belongs_to:cash_order
end
You can implement STI(Single Table Inheritance) functionality where in your database table "order_statuses" one more column will be there: type which will hold the derived model class name(In this case, CashOrderStatus).
So your model will look like this:
class CashOrderStatus > OrderStatus
set_table_name "order_statuses"
belongs_to:cash_order
end
And OrderStaus model will be derived from AR::Base class. Try it.
NOTE: Sorry for the class inheritance notation. It should be < instead of >. There is formatting issue in my stackoverflow account, so I put like this :-)

Resources