I have 2 models, one of patients and another of indicadions, I think I have the relationships between the models correctly placed, what I cannot make it work is that the patient_id is placed in the hidden field
my models:
patient: has_many :prescription, dependent: :destroy
indication: belongs_to :patient
my view:
<%= form_with(model: prescription) do |form| %>
<% if prescription.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(prescription.errors.count, "error") %> prohibited this prescription from being saved:</h2>
<ul>
<% prescription.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form.hidden_field :patient_id, value: "patient_id" %>
<div class="form-group">
<%= form.label :content %>
<%= form.text_area :content, class:'form-control' %>
</div>
<%= form.submit "SAVE",class:'btn save' %>
<% end %>
The controller:
class PrescriptionsController < ApplicationController
before_action :set_prescription, only: %i[ show edit update destroy ]
# GET /prescriptions or /prescriptions.json
def index
#prescriptions = Prescription.all
end
# GET /prescriptions/1 or /prescriptions/1.json
def show
end
# GET /prescriptions/new
def new
#prescription = Prescription.new
end
# GET /prescriptions/1/edit
def edit
end
# POST /prescriptions or /prescriptions.json
def create
#prescription = Prescription.new(prescription_params)
respond_to do |format|
if #prescription.save
format.html { redirect_to #prescription, notice: "La receta se creó con éxito." }
format.json { render :show, status: :created, location: #prescription }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /prescriptions/1 or /prescriptions/1.json
def update
respond_to do |format|
if #prescription.update(prescription_params)
format.html { redirect_to #prescription, notice: "Prescription was successfully updated." }
format.json { render :show, status: :ok, location: #prescription }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
# DELETE /prescriptions/1 or /prescriptions/1.json
def destroy
#prescription.destroy
respond_to do |format|
format.html { redirect_to prescriptions_url, notice: "Prescription was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_prescription
#prescription = Prescription.find(params[:id])
end
# Only allow a list of trusted parameters through.
def prescription_params
params.require(:prescription).permit(:content, :patient_id)
end
end
Instead of using a hidden input you might actually want to nest the routes to makes the relationship explicit instead of implicit:
resources :patients do
resources :perscriptions, shallow: true
end
class PrescriptionsController < ApplicationController
before_action :set_patient
before_action :set_prescription, only: %i[ show edit update destroy ]
# GET /patients/1/prescriptions or /patients/1/prescriptions.json
def index
#prescriptions = #patient.perscriptions
end
# GET /prescriptions/1 or /prescriptions/1.json
def show
end
# GET /patients/1/prescriptions/new
def new
#prescription = Prescription.new
end
# GET /prescriptions/1/edit
def edit
end
# POST /patients/1/prescriptions or /patients/1/prescriptions.json
def create
#prescription = #patient.perscriptions.new(prescription_params)
respond_to do |format|
if #prescription.save
format.html { redirect_to #prescription, notice: "La receta se creó con éxito." }
format.json { render :show, status: :created, location: #prescription }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /prescriptions/1 or /prescriptions/1.json
def update
respond_to do |format|
if #prescription.update(prescription_params)
format.html { redirect_to #prescription, notice: "Prescription was successfully updated." }
format.json { render :show, status: :ok, location: #prescription }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #prescription.errors, status: :unprocessable_entity }
end
end
end
# DELETE /prescriptions/1 or /prescriptions/1.json
def destroy
#prescription.destroy
respond_to do |format|
format.html { redirect_to prescriptions_url, notice: "Prescription was successfully destroyed." }
format.json { head :no_content }
end
end
private
def set_patient
#patient = Patient.find(params[:patient_id])
end
def set_prescription
#prescription = Prescription.find(params[:id])
end
# Only allow a list of trusted parameters through.
def prescription_params
params.require(:prescription).permit(:content)
end
end
<%= form_with(model: [#patient, #perscription]) do |form| %>
<% if prescription.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(prescription.errors.count, "error") %> prohibited this prescription from being saved:</h2>
<ul>
<% prescription.errors.each do |error| %>
<li><%= error.full_message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= form.label :content %>
<%= form.text_area :content, class:'form-control' %>
</div>
<%= form.submit "SAVE", class:'btn save' %>
<% end %>
Related
I use devise gem for authentication. I generated a scaffold for model M. I would like to update the created_by field with the user id from the login page. How do I achieve this?
I have 2 fields in the model F1 and F2.
The form that scaffold creates shows input for users to enter values for F1 and F2. How do I update the value for created_by field using the current_user from devise? Because the create action seems to be entering only the fields from the form.
<%= form_with(model: M, local: true) do |form| %>
<% if M.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(M.errors.count, "error") %> prohibited this movie from being saved:</h2>
<ul>
<% M.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= form.label :F1 %>
<%= form.text_field :F1 %>
</div>
<div class="field">
<%= form.label :F2 %>
<%= form.text_field :F2 %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
How to I update the model with current_user value in the above form without exposing that field to the user?
This is my controller:
class MsController < ApplicationController
before_action :set_M, only: [:show, :edit, :update, :destroy]
# GET /Ms
# GET /Ms.json
def index
#Ms = M.all
#categories = #Ms.uniq.pluck(:category)
#Ms_by_category = Hash.new
#categories.each do |category|
#Ms_by_category[category] = M.where(:category => category)
end
end
# GET /Ms/1
# GET /Ms/1.json
def show
end
# GET /Ms/new
def new
#M = M.new
end
# GET /Ms/1/edit
def edit
end
# POST /Ms
# POST /Ms.json
def create
#M = M.new(M_params)
respond_to do |format|
if #M.save
format.html { redirect_to #M, notice: 'M was successfully created.' }
format.json { render :show, status: :created, location: #M }
else
format.html { render :new }
format.json { render json: #M.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /Ms/1
# PATCH/PUT /Ms/1.json
def update
respond_to do |format|
if #M.update(M_params)
format.html { redirect_to #M, notice: 'M was successfully updated.' }
format.json { render :show, status: :ok, location: #M }
else
format.html { render :edit }
format.json { render json: #M.errors, status: :unprocessable_entity }
end
end
end
# DELETE /Ms/1
# DELETE /Ms/1.json
def destroy
#M.destroy
respond_to do |format|
format.html { redirect_to Ms_url, notice: 'M was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_M
#M = M.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def M_params
params.require(:M).permit(:title, :category, :rating)
end
end
So simple in creating action change your method, for example, you just need to create the client
before_action :authenticate_user!
def create
#client = Client.new(name: params[:name], address: params[:address],created_by: current_user.email )
if #client.save
redirect_to #client
else
render 'new'
end
end
There should be a field like created_by exist in the table.
You need to add users reference to M model and add associations. created_by is not the best name for it. Let imagine that M is abbreviation for Music. In this case you need to create a migration
add_reference :musics, :user
Add to the Music model
belongs_to :user
And to the User model
has_many :musics
And change in the controller
def new
#music = current_user.musics.new
end
def create
#music = current_user.musics.new(M_params)
respond_to do |format|
if #music.save
format.html { redirect_to #music, notice: 'Music was successfully created.' }
format.json { render :show, status: :created, location: #music }
else
format.html { render :new }
format.json { render json: #music.errors, status: :unprocessable_entity }
end
end
end
I have this error First argument in form cannot contain nil or be empty
In the next code and have no idea how to resolve. I checked other similar questions but no luck.
I also share the controller which seems the issue but still no idea how to fix it
<%= form_for #upload do |f| %>
<% if #upload.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#upload.errors.count, "error") %> prohibited this document from being saved:</h2>
<ul>
<% #upload.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.file_field :file %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Controller:
This what makes the thing in my app. But I don't see the issue.
class UploadsController < ApplicationController
before_action :upload_params, only: [:show, :edit, :update, :destroy]
def index
#uploads = Upload.all
end
def show
send_data(#upload.file_contents,
type: #upload.content_type,
filename: #upload.filename)
end
def new
#upload = Upload.new
end
def edit
end
def create
#upload = Upload.new(upload_params)
respond_to do |format|
if #upload.save
format.html { redirect_to upload_path, notice: 'Document was successfully created.' }
format.json { render :show, status: :created, location: #upload }
else
format.html { render :new, notice: 'Wrong file' }
format.json { render json: #upload.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #upload.update(upload_params)
format.html { redirect_to #upload, notice: 'Document was successfully updated.' }
format.json { render :show, status: :ok, location: #upload }
else
format.html { render :edit }
format.json { render json: #upload.errors, status: :unprocessable_entity }
end
end
end
def destroy
#upload.destroy
respond_to do |format|
format.html { redirect_to uploads_url, notice: 'Document was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_upload
#upload = Upload.find(params[:id])
end
def upload_params
params.require(:upload).permit(:file)
end
end
It's pretty obvious from the error I would say. The #upload object must not be nil. Please make sure you initiate that object before rendering this view (usually in the controller).
Looking at your controller code, please change the before_action to call set_upload.
before_action :set_upload, only: [:show, :edit, :update, :destroy]
I'm trying to create a has-many association within a ruby on rails app where a user has-many goals and a goal has-many steps
I can't seem to figure out how to link the creation of a Step for a certain Goal. I've been playing around with it for a while and looking around on here but haven't found a solution.
Below are my Goal_controller, Step_Controller, Step form, and Goal form
Goal Controller:
class GoalsController < ApplicationController
before_action :set_goal, only: [:show, :edit, :update, :destroy]
before_filter :authorize
# GET /goals
# GET /goals.json
def index
#goals = Goal.all
end
# GET /goals/1
# GET /goals/1.json
def show
#goal = Goal.find(params[:id])
session[:current_goal] = #goal.id
end
# GET /goals/new
def new
#goal = Goal.new
end
# GET /goals/1/edit
def edit
end
# POST /goals
# POST /goals.json
def create
#goal = current_user.goals.new(goal_params)
respond_to do |format|
if #goal.save
format.html { redirect_to #goal, notice: 'Goal was successfully created.' }
format.json { render :show, status: :created, location: #goal }
else
format.html { render :new }
format.json { render json: #goal.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /goals/1
# PATCH/PUT /goals/1.json
def update
respond_to do |format|
if #goal.update(goal_params)
format.html { redirect_to #goal, notice: 'Goal was successfully updated.' }
format.json { render :show, status: :ok, location: #goal }
else
format.html { render :edit }
format.json { render json: #goal.errors, status: :unprocessable_entity }
end
end
end
# DELETE /goals/1
# DELETE /goals/1.json
def destroy
#goal.destroy
respond_to do |format|
format.html { redirect_to goals_url, notice: 'Goal was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_goal
#goal = Goal.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def goal_params
params.require(:goal).permit(:Goal, :Description, :Date, :DueDate, :user_id)
end
end
Step Controller:
class StepsController < ApplicationController
#before_action :set_step, only: [:show, :edit, :update, :destroy]
before_filter :authorize
# GET /steps
# GET /steps.json
def index
#steps = Goal.find(params[:goal_id]).steps.all
end
def new
#step = Goal.find(params[:goal_id]).steps.new
end
# GET /steps/1
# GET /steps/1.json
def show
end
# GET /steps/1/edit
def edit
end
def create
#step = Goal.find(params[:goal_id]).steps.new(step_params)
respond_to do |format|
if #step.save
format.html { redirect_to #step, notice: 'Step was successfully created.' }
format.json { render :show, status: :created, location: #step }
else
format.html { render :new }
format.json { render json: #step.errors, status: :unprocessable_entity }
end
end
redirect_to(goal_steps_url(#goal))
end
def update
#step.update(step_params)
respond_to do |format|
if #step.update(step_params)
format.html { redirect_to #step, notice: 'Step was successfully updated.' }
format.json { render :show, status: :ok, location: #step }
else
format.html { render :edit }
format.json { render json: #step.errors, status: :unprocessable_entity }
end
end
end
# POST /steps
# POST /steps.json
def destroy
#step.destroy
respond_to do |format|
format.html { redirect_to steps_url, notice: 'Step was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_step
#step = Goal.find(params[:goal_id]).Step.find(params[:id])
end
def step_params
params.require(:step).permit(:requirement, :completionTime, :goal_id)
end
end
Step Form:
<%= form_for(#step) do |f| %>
<% if #step.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#step.errors.count, "error") %> prohibited this step from being saved:</h2>
<ul>
<% #step.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :requirement %><br>
<%= f.text_field :requirement %>
</div>
<div class="field">
<%= f.label :completionTime %><br>
<%= f.number_field :completionTime %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Goal Form:
<%= form_for(#goal) do |f| %>
<% if #goal.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#goal.errors.count, "error") %> prohibited this goal from being saved:</h2>
<ul>
<% #goal.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :Goal %><br>
<%= f.text_field :Goal %>
</div>
<div class="field">
<%= f.label :Description %><br>
<%= f.text_area :Description %>
</div>
<div class="field">
<%= f.label :Date %><br>
<%= f.date_select :Date %>
</div>
<div class="field">
<%= f.label :DueDate %><br>
<%= f.date_select :DueDate %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
It looks like you will be missing your goal_id when you submit your step creation form. You will need to store it either in a hidden field in your step form, or as part of the route (e.g. POST /goals/10/steps).
I'm very new to Ruby on Rails, so forgive if this is a stupid mistake.
I used a rails generate scaffold command to generate a "board" scaffold with a title:string and message:text. Now, I'm trying to go to localhost:3000/boards/new and I'm getting a "NoMethodError in Boards#show" error when I try to access board.message. I don't get any error when I try to access board.title.
Code:
form.html.erb
<%= form_for(#board) do |f| %>
<% if #board.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#board.errors.count, "error") %> prohibited this board from being saved:</h2>
<ul>
<% #board.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :message %><br />
<%= f.text_area :message %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm specifically getting the error on line 20 (<%= f.text_area :message %>)
board.rb
class Board < ActiveRecord::Base
attr_accessible :message, :title
has_many :posts
end
*boards_controller.rb*
class BoardsController < ApplicationController
# GET /boards
# GET /boards.json
def index
#boards = Board.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #boards }
end
end
# GET /boards/1
# GET /boards/1.json
def show
#board = Board.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #board }
end
end
# GET /boards/new
# GET /boards/new.json
def new
#board = Board.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #board }
end
end
# GET /boards/1/edit
def edit
#board = Board.find(params[:id])
end
# POST /boards
# POST /boards.json
def create
#board = Board.new(params[:board])
respond_to do |format|
if #board.save
format.html { redirect_to #board, notice: 'Board was successfully created.' }
format.json { render json: #board, status: :created, location: #board }
else
format.html { render action: "new" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
# PUT /boards/1
# PUT /boards/1.json
def update
#board = Board.find(params[:id])
respond_to do |format|
if #board.update_attributes(params[:board])
format.html { redirect_to #board, notice: 'Board was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #board.errors, status: :unprocessable_entity }
end
end
end
# DELETE /boards/1
# DELETE /boards/1.json
def destroy
#board = Board.find(params[:id])
#board.destroy
respond_to do |format|
format.html { redirect_to boards_url }
format.json { head :no_content }
end
end
end
routes.rb
Anonymous::Application.routes.draw do
resources :boards
resources :posts
root :to => "boards#index"
end
Can anyone please explain this to me?
Rails newbie working on associating tasks with lists and running into trouble when I try and interact with forms after I start the rails server.
Here's the error I'm getting. Any ideas?
Thanks!
NoMethodError in TasksController#create
undefined method `find_or_create_by_name' for #<Class:0x00000102a8bad0>
Rails.root: /Users/user/rails_projects/todolist
Application Trace | Framework Trace | Full Trace
app/models/task.rb:15:in `list_name='
app/controllers/tasks_controller.rb:43:in `new'
app/controllers/tasks_controller.rb:43:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"B7g7u+v5USPRhefdFPt84xGkKjB1nVwy62IJj6SHJpc=",
"task"=>{"description"=>"Milk",
"list_name"=>"Shopping"},
"commit"=>"Create Task"}
ListsController:
class ListsController < ApplicationController
# GET /lists
# GET /lists.json
def index
#lists = List.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #lists }
end
end
# GET /lists/1
# GET /lists/1.json
def show
#list = List.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #list }
end
end
# GET /lists/new
# GET /lists/new.json
def new
#list = List.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #list }
end
end
# GET /lists/1/edit
def edit
#list = List.find(params[:id])
end
# POST /lists
# POST /lists.json
def create
#list = List.new(params[:list])
respond_to do |format|
if #list.save
format.html { redirect_to #list, notice: 'List was successfully created.' }
format.json { render json: #list, status: :created, location: #list }
else
format.html { render action: "new" }
format.json { render json: #list.errors, status: :unprocessable_entity }
end
end
end
# PUT /lists/1
# PUT /lists/1.json
def update
#list = List.find(params[:id])
respond_to do |format|
if #list.update_attributes(params[:list])
format.html { redirect_to #list, notice: 'List was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #list.errors, status: :unprocessable_entity }
end
end
end
# DELETE /lists/1
# DELETE /lists/1.json
def destroy
#list = List.find(params[:id])
#list.destroy
respond_to do |format|
format.html { redirect_to lists_url }
format.json { head :no_content }
end
end
end
TasksController:
class TasksController < ApplicationController
# GET /tasks
# GET /tasks.json
def index
#tasks = Task.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #tasks }
end
end
# GET /tasks/1
# GET /tasks/1.json
def show
#task = Task.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #task }
end
end
# GET /tasks/new
# GET /tasks/new.json
def new
#task = Task.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #task }
end
end
# GET /tasks/1/edit
def edit
#task = Task.find(params[:id])
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(params[:task])
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render json: #task, status: :created, location: #task }
else
format.html { render action: "new" }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# PUT /tasks/1
# PUT /tasks/1.json
def update
#task = Task.find(params[:id])
respond_to do |format|
if #task.update_attributes(params[:task])
format.html { redirect_to #task, notice: 'Task was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
#task = Task.find(params[:id])
#task.destroy
respond_to do |format|
format.html { redirect_to tasks_url }
format.json { head :no_content }
end
end
end
Task model:
class Task < ActiveRecord::Base
attr_accessible :description, :list_name
belongs_to :list, :foreign_key => "list_id"
def name
#list = List.find(params[:id])
end
def list_name
list.name if self.list
end
def list_name=(str)
self.list = List.find_or_create_by_name(str)
end
end
List model:
class List < ActiveRecord::Base
attr_accessible :title
has_many :tasks
def name
#list = List.find(params[:id])
end
end
Partial for Tasks:
<%= form_for(#task) do |f| %>
<% if #task.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#task.errors.count, "error") %> prohibited this task from being saved:</h2>
<ul>
<% #task.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :list_name %><br />
<%= f.text_field :list_name %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Partial for Lists:
<%= form_for(#list) do |f| %>
<% if #list.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#list.errors.count, "error") %> prohibited this list from being saved:</h2>
<ul>
<% #list.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The dynamic finders find_or_create_by_*... have been deprecated in Rails 4, as can be read about here.
However find_or_create_by is still supported.
In other words, instead of
find_or_create_by_name( 'Alice' ) # DEPRECATED
do
find_or_create_by( name: 'Alice' ) # OK
Rails' dynamic finders (find_by_... and find_or_create_by_...) are generated using the attributes of a model. You were using find_or_create_by_name when name wasn't an attribute on the List model.
Changing that to find_or_create_by_title(...) fixes the problem.