Определение взаимосвязей Ruby-on-Rails

#ruby-on-rails #ruby

#ruby-on-rails #ruby

Вопрос:

У меня есть таблица «местоположение» и таблица «роль»,

Таблица расположения:

 id|location_name|location_code|category|
1 |  location1  |   0001      | Urban  |
2 |  location2  |   0002      | Rural  |
3 |  location3  |   0003      |Suburban|
________________________________________
  

Таблица доходов:

 id|role_code|rural|urban|suburban|
1 |   1001  |  5  |  10 |   15   |
2 |   1002  |  7  |  12 |   17   |
1 |   1003  |  9  |  14 |   19   |
__________________________________
  

Таблица местоположений предназначена для определения категории области (сельская, городская или пригородная), а таблица ролей предназначена для определения цены дохода на основе категории местоположения.

как мне соединить обе таблицы вместе, чтобы всякий раз, когда пользователи вводят местоположение и роль, они видели цену?

Ответ №1:

Текущая структура не очень масштабируема по своей природе. Я бы настоятельно рекомендовал изменить способ структурирования данных. Взгляните на следующий пример.

 # Instead of storing the location category in as text you can store references
#   of location_category in locations amp; revenues table
class LocationType # Location Category
end
#  ---- ----------- 
# | id | name      |
#  ---- ----------- 
# |  1 | Urban     |
#  ---- ----------- 
# |  2 | Rural     |
#  ---- ----------- 
# |  3 | Sub Urban |
#  ---- ----------- 


# Similarly instead of storing role_code, you can store references to roles 
#   in your revenue table
class Role
end
#  ---- ------ -------- 
# | id | code | name   |
#  ---- ------ -------- 
# |  1 | 1001 | Role 1 |
#  ---- ------ -------- 
# |  2 | 1002 | Role 2 |
#  ---- ------ -------- 
# |  3 | 1003 | Role 3 |
#  ---- ------ -------- 

class Location
  belongs_to :location_type
end
#  ---- ----------- --------- ------------------ 
# | id | name      | code    | location_type_id |
#  ---- ----------- --------- ------------------ 
# |  1 | location1 | 001     |                1 |
#  ---- ----------- --------- ------------------ 
# |  2 | location2 | 002     |                2 |
#  ---- ----------- --------- ------------------ 
# |  3 | location3 | 003     |                3 |
#  ---- ----------- --------- ------------------ 

class Revenue
  belongs_to :location_type
  belongs_to :role
end
# References for roles amp; location_type stored instead of actual values
#  ---- ----------- --------- ------------------ 
# | id | role_id   | revenue | location_type_id |
#  ---- ----------- --------- ------------------ 
# |  1 |         1 |       5 |                2 |
#  ---- ----------- --------- ------------------ 
# |  2 |         2 |       7 |                2 |
#  ---- ----------- --------- ------------------ 
# |  3 |         3 |       9 |                2 |
#  ---- ----------- --------- ------------------ 
# |  4 |         1 |      10 |                1 |
#  ---- ----------- --------- ------------------ 
# |  5 |         2 |      12 |                1 |
#  ---- ----------- --------- ------------------ 
# |  6 |         3 |      14 |                1 |
#  ---- ----------- --------- ------------------ 
# |  7 |         1 |      15 |                3 |
#  ---- ----------- --------- ------------------ 
# |  8 |         2 |      17 |                3 |
#  ---- ----------- --------- ------------------ 
# |  9 |         3 |      19 |                3 |
#  ---- ----------- --------- ------------------ 
  

С помощью этой структуры теперь вы можете запускать оптимальные запросы к вашей базе данных для извлечения данных.

 # Example
location_type_id = params[:location_type_id]
role_id = params[:role_id]

@revenue = Revenue.where({
  location_type_id: location_type_id,
  role_id: role_id
}).sum(:revenue)
  

Если вы хотите, вы также можете включить location_id в свою таблицу доходов, тогда вы сможете найти доход для определенного местоположения следующим образом:

 @revenue = Revenue.where({
  role_id: role_id,
  location_id: location_id
}).sum(:revenue)
  

Ответ №2:

Самый простой подход к этому — использовать if инструкцию, чтобы проверить, является ли местоположение городским, сельским или пригородным.

Я предполагаю, что вы хотите использовать price в другой модели, поэтому я назвал модель transaction в примере кода ниже.

 if transaction_params[:price].blank?
    
  if @transaction.location.category == 'Rural'
    @transaction.price = @transaction.revenue.rural
  elsif @transaction.location.category == 'Suburban'
    @transaction.price = @transaction.revenue.suburban
  else
    @transaction.price = @transaction.revenue.urban
  end
end
  

Вы можете сделать это с помощью create метода в вашем контроллере транзакций.

Ответ №3:

Если пользователь вводит location2 и роль 1003, вы могли бы сделать:

 location = params[:location] # or some other way to get the input
role = params[:role] # or some other way to get the input

location_category = Location.find_by(name: location).category.downcase
# now location_category will be rural

Reveneu.find_by(role_code: role).send(location_category)
# with the .send method you can access the column that you need(in this case rural)
  

Ответ №4:

Предполагая, что у пользователя есть role_code amp; location_name в пользовательской модели —

 user = User.first
category = Location.find_by(name: location).category.downcase
price = Revenue.find_by(role_code: user.role_code).send(category)
puts "Your price is #{price}"
  

Ответ №5:

Простым способом получения цены было бы создать функцию, которая принимает объект Location (user_entered_location) и объект Revenue (user_entered_revenue) и возвращает цену.

 def get_price(user_entered_location, user_entered_revenue)
    if user_entered_location.category=="Urban"
        return user_entered_revenue.urban
    elsif user_entered_location.category=="Suburban"
        return user_entered_revenue.suburban
    else
        return user_entered_revenue.rural
end
  

Вы также могли бы изучить объединение таблиц.