我正在开发一个应用程序,用户可以在其中获得个人食物日记。
这非常简单:用户可以在Nutrients桌上搜索营养素(让我们说牛奶) - 目前通过一个非常简单的搜索表单 - 然后应该可以节省他的金额在第二个表上消耗了这种营养素(连同营养素_id),称为Diaries(将nutrient_id保存为外键,并将整数字段称为" amount")。
我的搜索有效。我也可以在Diaries中创建新记录,但我必须手动输入nutrient_id。
我现在的问题是如何让这件事变得轻松起来?理想情况下,用户会发现营养素点击它并将被重定向到显示此营养素的页面以及“#34; amount"和一个保存按钮,用于在日记表上保存两个信息(nutrient_id和amount)。
在一天结束时,我认为用户将被引导到我的日记控制器的新动作 - 问题是我的应用程序如何设置此操作的营养素_用于之前用户选择的营养素?
很抱歉,如果这是一个太简单的问题,但我几周前刚开始编码。
非常感谢您的帮助!
我的代码如下所示:
nutrient.rb
class Nutrient < ActiveRecord::Base
has_many :diaries
def self.search(search)
where("name LIKE ?", "%#{search}%")
end
end
diary.rb
class Diary < ActiveRecord::Base
belongs_to :nutrient
end
nutrients_controller.rb
class NutrientsController < ApplicationController
before_action :set_nutrient, only: [:show, :edit, :update, :destroy]
# GET /nutrients
# GET /nutrients.json
def index
@nutrients = Nutrient.all
end
def search
if params[:search]
@nutrients = Nutrient.search(params[:search]).order("created_at DESC")
if @nutrients.present?
@nutrients
else
flash[:notice] = "Nutrient not found in database"
end
end
end
# GET /nutrients/1
# GET /nutrients/1.json
def show
end
# GET /nutrients/new
def new
@nutrient = Nutrient.new
end
# GET /nutrients/1/edit
def edit
end
# POST /nutrients
# POST /nutrients.json
def create
@nutrient = Nutrient.new(nutrient_params)
respond_to do |format|
if @nutrient.save
format.html { redirect_to @nutrient, notice: 'Nutrient was successfully created.' }
format.json { render :show, status: :created, location: @nutrient }
else
format.html { render :new }
format.json { render json: @nutrient.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /nutrients/1
# PATCH/PUT /nutrients/1.json
def update
respond_to do |format|
if @nutrient.update(nutrient_params)
format.html { redirect_to @nutrient, notice: 'Nutrient was successfully updated.' }
format.json { render :show, status: :ok, location: @nutrient }
else
format.html { render :edit }
format.json { render json: @nutrient.errors, status: :unprocessable_entity }
end
end
end
# DELETE /nutrients/1
# DELETE /nutrients/1.json
def destroy
@nutrient.destroy
respond_to do |format|
format.html { redirect_to nutrients_url, notice: 'Nutrient was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_nutrient
@nutrient = Nutrient.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def nutrient_params
params.require(:nutrient).permit(:name)
end
end
diaries_controller.rb
class DiariesController < ApplicationController
before_action :set_diary, only: [:show, :edit, :update, :destroy]
# GET /diaries
# GET /diaries.json
def index
@diaries = Diary.all
end
# GET /diaries/1
# GET /diaries/1.json
def show
end
# GET /diaries/new
def new
@diary = Diary.new
end
# GET /diaries/1/edit
def edit
end
# POST /diaries
# POST /diaries.json
def create
@diary = Diary.new(diary_params)
respond_to do |format|
if @diary.save
format.html { redirect_to @diary, notice: 'Diary was successfully created.' }
format.json { render :show, status: :created, location: @diary }
else
format.html { render :new }
format.json { render json: @diary.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /diaries/1
# PATCH/PUT /diaries/1.json
def update
respond_to do |format|
if @diary.update(diary_params)
format.html { redirect_to @diary, notice: 'Diary was successfully updated.' }
format.json { render :show, status: :ok, location: @diary }
else
format.html { render :edit }
format.json { render json: @diary.errors, status: :unprocessable_entity }
end
end
end
# DELETE /diaries/1
# DELETE /diaries/1.json
def destroy
@diary.destroy
respond_to do |format|
format.html { redirect_to diaries_url, notice: 'Diary was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_diary
@diary = Diary.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def diary_params
params.require(:diary).permit(:nutrient_id, :amount)
end
end
的routes.rb
Rails.application.routes.draw do
resources :diaries
resources :nutrients do
collection do
get :search
end
end
_form.html.erb(对于新的日记记录)
<%= form_for(@diary) do |f| %>
<% if @diary.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@diary.errors.count, "error") %> prohibited this diary from being saved:</h2>
<ul>
<% @diary.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :nutrient_id %><br>
<%= f.number_field :nutrient_id %>
</div>
<div class="field">
<%= f.label :amount %><br>
<%= f.number_field :amount %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
答案 0 :(得分:2)
有几种方法可以解决这个问题,一种最快且最有可能最好的方法是将diaries
嵌套在nutrients
下,因为日记belongs_to :nutrients
resources :nutrients do
resources :diaries
collection do
get :search
end
end
这样您的所有diaries
路径方法都会接受@nutrient参数,您的路线就像:/nutrients/4/diaries/1
所以在你的diaries_controller中,你可以拥有:
class DiariesController < ApplicationController
before_action :set_nutrient
def new
@diary = @nutrient.diaries.new
end
def create
@diary = @nutrient.diaries.new(diary_params) # you can safely remove the nutrient_id from the strong params
... remaining logic here
end
...
private
def set_nutrient
@nutrient ||= Nutrient.find(params[:nutrient_id])
end
# You cans skip/ignore this method, if you don't want to be too strict
def set_diary
@diary ||= @nutrient.diaries.find(params[:id])
end
end
然后在您看来,您可以:
<%= form_for([@nutrient, @diary]) do |f| %>
<% if @diary.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@diary.errors.count, "error") %> prohibited this diary from being saved:</h2>
<ul>
<% @diary.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :amount %><br>
<%= f.number_field :amount %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
正如我所提到的,还有其他方法可以做到这一点,因为你也可以使用hidden_fields
,但这对我来说似乎是最干净的方式。
如果您并不总是希望嵌套您的日记路线,您可以预期:[{1}}和您的路线before_action
上的[不应嵌套的操作列表,例如show] 。希望我能够帮助或让我知道您可能遇到的其他混淆。