Rails: 创建动态路由、控制器
Rails: Create Dynamic routes, controllers
我几乎没有公开为 REST API 端点的数据库视图。当前的实现是添加视图后,我们添加 Rails 代码,如
- 添加新路线
- 添加控制器和其他代码以查询returns json响应的视图
这种方法的缺点是我们每次添加数据库视图时都需要向应用程序添加代码,有时这也不是即时的,这是另一个问题。
有没有办法,可能通过使用 Meta Programming
或其他方法,我们能够查询数据库以获取视图列表并生成必要的路由和代码以 return 有效响应.
下面是代码的相关部分
namespace :api do
namespace :v1 do
[
'leases',
# a new will go in here
]
end
end
class Api::V1::LeasesController < Api::V1::ApplicationController
api :GET, '/leases', "Retrieve paginated well month data"
param :authentication_token, String, "Token for authentication"
def index
result = Api::Lease.ransack(params[:q]).result.page(params[:page]).per(10000)
render json: result.to_json
end
end
class Api::Lease < ExternalRecord
self.table_name = 'View_Leases' #View in External Postgres server
end
谢谢。
您可以通过给定的连接进行任意 SQL 查询
namespace :v1 do
resources :views, only: :show
end
class ViewsController
def show
table_name = "View_#{params[:id].titleize}"
offset = (params[:page].to_i || 1) * 10_000 - 10_000
limit = 10_000
sql = "SELECT #{table_name}.* FROM #{table_name} OFFSET #{offset} LIMIT #{limit};"
data = ActiveRecord::Base.connection.execute(sql)
render json: data.to_json
end
end
但后来忘了使用搜查。 Ransack 需要一个模型,它依赖于推断的列类型将查询转换为模型本身的一系列 where、join 等。
当然,如果您制作自己的 SQL 字符串,您应该保护自己免受 SQL 注入。
如果你想保留查询的全部功能,你最好在你的应用程序和你的视图之间放置类似 Hasura 的内容,并将传入的查询转换为对 hasura 的 GraphQL 请求(它将处理为你休息)。
Is there a way, probably by using Meta Programming or something else we are able to query the database to get the list of views and generate the necessary routes and code to return a valid response.
是的,但实际实施取决于所使用的数据库。在 Postgres 上,您可以通过查询 pg_catalog.pg_views
:
来获取视图列表
pg_views = Arel::Table.new('pg_catalog.pg_views')
query = pg_views.project(:schemaname, :viewname)
.where(
pg_views[:schemaname].in('pg_catalog', 'information_schema').not
)
result = ActiveRecord::Base.connection.execute(query)
# ...
但是这里需要更改框架。视图是否一定需要对应于它自己的路线,或者您可以创建更好的 RESTful 设计吗?
例如,如果您按 year/month 列出,您可以轻松设置覆盖它的单一路线:
namespace :api do
namespace :v1 do
resources :leases do
get '/leases/by_month/:year/:month', as: :by_month, action: :by_month
end
end
end
你能用元编程设置模型吗?
当然可以。 类 in Ruby 是 first-class 对象,您可以使用 Class.new
:
创建它们
# Setup a base class for shared behavior
class ApplicationView < ActiveRecord::Base
self.abstract_class = true
end
str = 'Foo'
model = Class.new(ApplicationView) do |klass|
# do your model specific thing here...
end
# Classes get their name by being assigned to a constant
ApplicationView.const_set(str, model)
ApplicationView::Foo.all # SELECT * FROM foos;
ActiveRecord 和 ActiveModel 不太喜欢匿名 classes(classes 没有分配给常量)因为他们做了一堆基于 class 的假设姓名。这里我们将常量嵌套在 ApplicationView 中只是为了避免命名空间崩溃。
有时在库代码中使用的另一种方法是创建一个包含代码的字符串来定义 class 并对其求值。
您还可以设置查询不同 tables/views.
的单个模型
你能用元编程设置控制器和视图(如在 MVC 中)吗?
是的。但你不应该需要它。您可以简单地创建可以处理各种模型的通用控制器。请记住,控制器对应于单个模型的想法只是适用于琐碎情况的约定。
我几乎没有公开为 REST API 端点的数据库视图。当前的实现是添加视图后,我们添加 Rails 代码,如
- 添加新路线
- 添加控制器和其他代码以查询returns json响应的视图
这种方法的缺点是我们每次添加数据库视图时都需要向应用程序添加代码,有时这也不是即时的,这是另一个问题。
有没有办法,可能通过使用 Meta Programming
或其他方法,我们能够查询数据库以获取视图列表并生成必要的路由和代码以 return 有效响应.
下面是代码的相关部分
namespace :api do
namespace :v1 do
[
'leases',
# a new will go in here
]
end
end
class Api::V1::LeasesController < Api::V1::ApplicationController
api :GET, '/leases', "Retrieve paginated well month data"
param :authentication_token, String, "Token for authentication"
def index
result = Api::Lease.ransack(params[:q]).result.page(params[:page]).per(10000)
render json: result.to_json
end
end
class Api::Lease < ExternalRecord
self.table_name = 'View_Leases' #View in External Postgres server
end
谢谢。
您可以通过给定的连接进行任意 SQL 查询
namespace :v1 do
resources :views, only: :show
end
class ViewsController
def show
table_name = "View_#{params[:id].titleize}"
offset = (params[:page].to_i || 1) * 10_000 - 10_000
limit = 10_000
sql = "SELECT #{table_name}.* FROM #{table_name} OFFSET #{offset} LIMIT #{limit};"
data = ActiveRecord::Base.connection.execute(sql)
render json: data.to_json
end
end
但后来忘了使用搜查。 Ransack 需要一个模型,它依赖于推断的列类型将查询转换为模型本身的一系列 where、join 等。
当然,如果您制作自己的 SQL 字符串,您应该保护自己免受 SQL 注入。
如果你想保留查询的全部功能,你最好在你的应用程序和你的视图之间放置类似 Hasura 的内容,并将传入的查询转换为对 hasura 的 GraphQL 请求(它将处理为你休息)。
Is there a way, probably by using Meta Programming or something else we are able to query the database to get the list of views and generate the necessary routes and code to return a valid response.
是的,但实际实施取决于所使用的数据库。在 Postgres 上,您可以通过查询 pg_catalog.pg_views
:
pg_views = Arel::Table.new('pg_catalog.pg_views')
query = pg_views.project(:schemaname, :viewname)
.where(
pg_views[:schemaname].in('pg_catalog', 'information_schema').not
)
result = ActiveRecord::Base.connection.execute(query)
# ...
但是这里需要更改框架。视图是否一定需要对应于它自己的路线,或者您可以创建更好的 RESTful 设计吗?
例如,如果您按 year/month 列出,您可以轻松设置覆盖它的单一路线:
namespace :api do
namespace :v1 do
resources :leases do
get '/leases/by_month/:year/:month', as: :by_month, action: :by_month
end
end
end
你能用元编程设置模型吗?
当然可以。 类 in Ruby 是 first-class 对象,您可以使用 Class.new
:
# Setup a base class for shared behavior
class ApplicationView < ActiveRecord::Base
self.abstract_class = true
end
str = 'Foo'
model = Class.new(ApplicationView) do |klass|
# do your model specific thing here...
end
# Classes get their name by being assigned to a constant
ApplicationView.const_set(str, model)
ApplicationView::Foo.all # SELECT * FROM foos;
ActiveRecord 和 ActiveModel 不太喜欢匿名 classes(classes 没有分配给常量)因为他们做了一堆基于 class 的假设姓名。这里我们将常量嵌套在 ApplicationView 中只是为了避免命名空间崩溃。
有时在库代码中使用的另一种方法是创建一个包含代码的字符串来定义 class 并对其求值。
您还可以设置查询不同 tables/views.
的单个模型你能用元编程设置控制器和视图(如在 MVC 中)吗?
是的。但你不应该需要它。您可以简单地创建可以处理各种模型的通用控制器。请记住,控制器对应于单个模型的想法只是适用于琐碎情况的约定。