Rails数据表,两个控制器中的类似表

时间:2017-07-25 03:37:56

标签: jquery ruby-on-rails ruby datatable

我正在使用JQuery Datatables gem,我已经成功地让它为我的一个控制器工作。 SteamGames

SteamGames控制器

def index
  @steam_games = SteamGame.all
  respond_to do |format|
    format.html
    format.json { render json: SteamGamesDatatable.new(view_context) }
  end
end

数据表本身非常简单,就像我从git那里得到的那样。

class SteamGamesDatatable
  delegate :params, :link_to, :number_to_currency, to: :@view

  def initialize(view)
    @view = view
  end

  def as_json(options = {})
    {
      sEcho: params[:sEcho].to_i,
      iTotalRecords: SteamGame.count,
      iTotalDisplayRecords: games.total_entries,
      aaData: data
    }
  end

private

  def data
    games.map do |game|
      [
        link_to(game.game_name, game),
        "<img src='#{game.img_icon_url}'/>",
        game.created_at.strftime("%B %e, %Y"),
        game.updated_at.strftime("%B %e, %Y"),
      ]
    end
  end

  def games
    @games ||= fetch_games
  end

  def fetch_games
    games = SteamGame.order("#{sort_column} #{sort_direction}")
    games = games.page(page).per_page(per_page)
    if params[:sSearch].present?
      games = games.where("game_name like :search", search: "%#{params[:sSearch]}%")
    end
    games
  end

  def page
    params[:iDisplayStart].to_i/per_page + 1
  end

  def per_page
    params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
  end

  def sort_column
    columns = %w[game_name img_icon_url created_at]
    columns[params[:iSortCol_0].to_i]
  end

  def sort_direction
    params[:sSortDir_0] == "desc" ? "desc" : "asc"
  end
end

现在我正在为另一个控制器Collections设置它,但我知道我非常多余,但我不知道如何解决它。

&#34;类别&#34;是用户和SteamGames之间的中间件链接。

所以我想也许我可以复制整个数据表代码并将SteamGame替换为Collection.steam_game,就像我在Rails控制台中那样,但它通知我

NoMethodError (undefined method 'steam_game' for #<Class:0x00000007159670>):

这样做的目的是,如果我去/collection/:id我只会看到收藏所拥有的游戏。 /steamgames向我显示了我数据库中的每个游戏。

如何在新控制器中轻松利用以前的逻辑?

如果我不能,那么如何在控制器中正确引用关系链接呢?

仅供参考我这是因为好奇而试图为收藏品制作的数据表

class CollectionsDatatable
  delegate :params, :link_to, :number_to_currency, to: :@view

  def initialize(view)
    @view = view
  end

  def as_json(options = {})
    {
      sEcho: params[:sEcho].to_i,
      iTotalRecords: Collection.count,
      iTotalDisplayRecords: games.total_entries,
      aaData: data
    }
  end

private

  def data
    games.map do |game|
      [
        link_to(game.game_name, game),
        "<img src='#{game.img_icon_url}'/>",
        game.created_at.strftime("%B %e, %Y"),
        game.updated_at.strftime("%B %e, %Y"),
      ]
    end
  end

  def games
    @games ||= fetch_games
  end

  def fetch_games
    games = Collection.steam_game.order("#{sort_column} #{sort_direction}") ##<--- This is where the error comes from
    games = games.page(page).per_page(per_page)
    if params[:sSearch].present?
      games = games.where("game_name like :search", search: "%#{params[:sSearch]}%")
    end
    games
  end

  def page
    params[:iDisplayStart].to_i/per_page + 1
  end

  def per_page
    params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
  end

  def sort_column
    columns = %w[game_name img_icon_url created_at]
    columns[params[:iSortCol_0].to_i]
  end

  def sort_direction
    params[:sSortDir_0] == "desc" ? "desc" : "asc"
  end
end

我想也许SteamGamesController中的一个额外函数可能就足够了,所以我可以覆盖def fetch_games函数但我不完全理解SteamGamesDatatable.new(view_context)在控制器中调用的内容。我假设~initize(view)函数?

收藏模式

class Collection < ApplicationRecord
    belongs_to :user
    belongs_to :steam_game
end

SteamGames实际上非常相似

收集/ SteamGames的架构

create_table "collections", force: :cascade do |t|
    t.string "platform"
    t.string "name"
    t.bigint "user_id"
    t.bigint "steam_game_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["steam_game_id"], name: "index_collections_on_steam_game_id"
    t.index ["user_id"], name: "index_collections_on_user_id"
  end

  create_table "steam_games", force: :cascade do |t|
    t.integer "appid", null: false
    t.string "game_name", default: "", null: false
    t.string "img_icon_url", default: "assets/32x32-no.png"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

更新2 - 传递其他初始化

class CollectionsDatatable
  delegate :params, :link_to, :number_to_currency, to: :@view

  def initialize(view, steam_games_resource)
    @view = view
    @steam_games_resource = steam_games_resource
  end

  def as_json(options = {})
    {
      sEcho: params[:sEcho].to_i,
      iTotalRecords: @steam_games_resource.count,
      iTotalDisplayRecords: games.total_entries,
      aaData: data
    }
  end

private

  def data
    games.map do |game|
      [
        link_to(game.game_name, game),
        "<img src='#{game.img_icon_url}'/>",
        game.created_at.strftime("%B %e, %Y"),
        game.updated_at.strftime("%B %e, %Y"),
      ]
    end
  end

  def games
    @games ||= fetch_games
  end

  def fetch_games
    games = @steam_games_resource.order("#{sort_column} #{sort_direction}")
    games = games.page(page).per_page(per_page)
    if params[:sSearch].present?
      games = games.where("game_name like :search", search: "%#{params[:sSearch]}%")
    end
    games
  end

  def page
    params[:iDisplayStart].to_i/per_page + 1
  end

  def per_page
    params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
  end

  def sort_column
    columns = %w[game_name img_icon_url created_at]
    columns[params[:iSortCol_0].to_i]
  end

  def sort_direction
    params[:sSortDir_0] == "desc" ? "desc" : "asc"
  end
end

控制器

  def show
    @collection = Collection.find(params[:id])
    respond_to do |format|
      format.html
      format.json { render json: CollectionsDatatable.new(view_context, @collection.steam_game) }
    end
  end

我已经修改了初始化以接受一个新参数,这可能会让我感到复杂。我还浏览了数据表以删除Collection.steam_game的实例。

现在我得到了 undefined method计数&#39;对于#`的回应,这让我相信它正在尝试.count一个单一的游戏。我认为这是因为每个记录都插入到Collection表中 - 所以即使它输出了一个&#39; steam_game&#39;,也没有计数。

到目前为止,我认为我的模型可能没有正确设置。

会员应该有一个&#34; Collection&#34; - 集合有platformname。该系列应该有游戏。理论上这是正确的,但我注意到每个游戏都在创建一个新的收藏行。

我应该有一个 用户 采集 GameCollections 游戏

系统,其中GameCollection只是&#39; union&#39;?用户有收藏?

最终更新

感谢@ Yaro的回答,它有助于指导我找到合适的解决方案。

我选择了4步同步。 用户 - &gt;收集&lt; - &gt;游戏集合&lt; - Steam_Games

这样,我就可以找到所有拥有X steam_game的用户,并找到所有拥有X steam_game

的收藏集

修复逻辑后,我能够使用提供的建议使用相同的数据表。

我的CollectionsController

  def show
    @collection = Collection.find(params[:id])
    respond_to do |format|
      format.html
      format.json { render json: SteamGamesDatatable.new(view_context, @collection.steam_games) }
    end
  end

现在仅显示适用于此特定集合的游戏。我现在需要重新访问命名约定,但这正是我所需要的。

(旁注,它也可以创建完全重复的CollectionsDatatable,但感觉非常重复)

1 个答案:

答案 0 :(得分:1)

  

我不完全理解SteamGamesDatatable.new(view_context)在控制器中调用的内容。我假设~initize(view)函数?

你是对的,#new确实调用了SteamGamesDatatable的#initialize方法。只要您不覆盖#initialize作业,就可以向@view添加任何逻辑。

我认为这里值得注意的问题是你试图调用Collection.steam_game - 你得到NoM​​ethodError,因为Collection类实际上不知道在哪里寻找这个方法。我想你要找的是collection.steam_games。这有两个部分 - 首先,您需要一个Collection实例来表示具体记录,而现在您提供了一般表示该表的类。其次,我怀疑,在你的Collection模型中你有has_and_belongs_to_many :steam_games,所以没有单一形式(steam_game)你的模型可以查找。

至于你的问题的本质 - 如何重用你的代码,这就是我要做的:我只留下类SteamGamesDatatable并在其实例化中添加另一个参数:

def initialize(view, games_resource)
  @view = view
  @games_resource = games_resource
end

您的Steam游戏控制器#index操作的games_resource将是所有Steam游戏(SteamGame.all),对于您的收藏控制器,它将是该具体收藏的蒸汽游戏(例如{{1} }})。然后,在@collection.steam_games中,您将使用fetch_games而不是具体模型来获取游戏。

如果您遵循此路径并发现自己需要为集合添加一些单独的数据表逻辑,则始终可以将所有复制的代码移动到模块中,并将该模块包含在您可以使用的任意数量的类中。我希望分享逻辑。

希望这会对你有所帮助。

<强>更新

  

我是否应该使用User Collection GameCollections游戏

     

系统,GameCollection只是'联盟'?和用户   收藏?

是的,对不起,我只是猜到了你的数据库表结构,这可能会导致一些冗余的操作。

但基本上是的,如果你的Collection属于一个steam_game,你将无法输出一个集合的'all'蒸汽游戏,因为每个集合有一个游戏。所以你的方法是正确的 - 只需在集合和蒸汽游戏之间创建一个连接表。

所以最后你将拥有这些关系:

  • 用户games_resource
  • GameCollection has_many :collections
  • 收藏belongs_to :collection; belongs_to :steam_game
  • SteamGame belongs_to :user; has_many :game_collections; has_many :steam_games, through: :game_collections

Collection和SteamGame之间的关系看起来有点像has_many :game_collections; has_many :collections, through: :game_collections,但风格指南却不赞成这一点。