Rails 5 ActiveRecord,如何包含关联表中的字段?

时间:2017-06-06 04:45:13

标签: ruby-on-rails ruby ruby-on-rails-5

使用Rails 5,给出模型:

chef_positions
* id
* name

skills
* id
* name

chef_position_skills
* id
* chef_position_id
* skill_id

我有一个控制器方法,可以通过chef_position_id返回chef_position_skills:

  def index
    chef_position = ChefPosition.find(params[:chef_position_id])
    render json: chef_position.chef_position_skills
  end

返回:

 [{"id":1,"chef_position_id":2,"skill_id":1,"created_at":"2017-06-05T15:44:06.821Z","updated_at":"2017-06-05T15:44:06.821Z"},{"id":2,"chef_position_id":2,"skill_id":2,"created_at":"2017-06-05T15:44:06.821Z","updated_at":"2017-06-05T15:44:06.821Z"}]

如何让控制器执行以下操作:

  1. 包括每条记录的skill.name
  2. 不包含时间戳
  3. 谢谢, 布雷特

3 个答案:

答案 0 :(得分:2)

如果您尚未在模型中chef_positions.rb

,则需要先将两者关联起来
has_many :skills, through: :chef_position_skills

然后在你的控制器中,

ChefPosition.where(id: params[:chef_position_id]).joins(:skills).select('chef_positions.id, skills.name')

答案 1 :(得分:1)

def index
  chef_position = ChefPosition.find(params[:chef_position_id])
  render json: chef_position.chef_position_skills.map(&:json_data)
end

# ChefPositionSkill#json_data
def json_data
  to_json(
    include: { skill: { only: [:name] } },
    only: [:id, :chef_position_id, :skill_id]
  )
end

定义方法json_data(仅为方便起见),并使用.map为每个chef_position_skill调用它。

includeonly是标准的json序列化器方法,可以帮助确定需要包含的内容。

唯一的缺点(据我所知),现在你的最终json中会有另一个属性"skill": { "name": "skill_name" }

答案 2 :(得分:1)

使用

render json: chef_position.chef_position_skills.
  map {|s| s.slice(:id, :chef_position_id, :skill_id).merge s.skill.slice(:name) }

我没有相同的型号,但这是一个类似的例子:

irb(main):026:0> u.slice(:id, :email).merge u.funds.slice(:min)
=> {"id"=>1, "email"=>"test@example.com", "min"=>1000000}

但我认为你真的很喜欢包含在Rails 5中的JBuilder。

https://github.com/rails/jbuilder