I'm trying to learn web development as I go (I just need need to get this one project done. I don't plan on touching the subject ever again.) and I've run into the problem of getting data from a rails web page to its corresponding controller. My end goal is to get data from javascript variables and pass that to ruby, but I've decided to take small steps so for now I'm trying to get a button_to to send some hard coded strings from the new.html.erb to the corresponding create method in the controller. I've probably tried a hundred combinations of view, controller and, routs code and I can't get any of them to work. Here is the current iteration of my code for the controller, view, and routes (I'm not sure if routes even matters).
ponies_controller.rb
def create(name, pro)
##pony = Pony.new(params[:id])
#pony = Pony.new(name: name, profession: pro)
respond_to do |format|
if #pony.save
format.html { redirect_to #pony, notice: 'Pony was successfully created.' } |~
format.json { render :show, status: :created, location: #pony }
else
format.html { render :new }
format.json { render json: #pony.errors, status: :unprocessable_entity }
end
end
end
new.html.erb
<h1>New Pony</h1>
<%= render 'form', pony: #pony %>
<%= link_to 'Back', ponies_path %>
<%= button_to "create_pony", {action: create("s","ss")}, remote: true,from_class: "create_pony" %>
routes.rb (Not sure if this is important)
Rails.application.routes.draw do
resources :ponies
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
post 'ponies/:id/create' => 'pony#create', as: :create_pony
end
While this code doesn't work I think it shows how I think things should work. I feel like I should just be able to call the method and be done with things, but that is obviously wrong. What should I be doing to get button_to to post a new "pony"?
Here's the Rails way to do this in the simplest way (assuming you've set up your Pony model correctly):
# ponies_controller.rb
def create
#pony = Pony.new(pony_params)
if #pony.save
# success
else
# errors
end
end
private
def pony_params
params.require(:pony).permit(:name, :profession) # whitelist the parameters you want to accept from the pony creation form
end
and your pony form should like this
# new.html.erb
<h1> New Pony </h1>
<%= form_for #pony, remote: true do |f| %>
<%= f.text_field :name %> # this will be passed to the controller in the params hash
<%= f.text_field :profession %> # this too
<%= f.submit %>
<% end %>
also, resources :ponies will create all the routes you need for ponies so no need to define one yourself.
Related
I'm trying to get a simple button press that will store current user's id into a field but getting an error that says
ActionController::ParameterMissing (param is missing or the value is empty: request):
Here's my code.
The button code
<%= form_for(request.accept, remote: true) do |f| %>
<%= f.submit "Accept", class: "btn btn-primary" %>
<% end %>
request_controller
def accept
#request.ssp_id = current_user.id
#request.save
flash[:success] = "The request have been accepted!"
end
Thanks in advance.
The ParameterMissing error is probably because you have specified to require request model in your parameters through strong_params.
Since you are trying to update an existing record with the current_user you don't need a form.
Update your accept action in the RequestsController:
def accept
#request = Request.find params[:id]
if #request.update_attribute(:ssp, current_user)
redirect_to requests_path
flash[:success] = "The request have been accepted!"
end
end
Request model
class Request < ApplicationRecord
belongs_to :ssp, class_name: "User"
end
And your routes:
resources :requests do
member do
get "accept"
end
end
<%= link_to 'Accept request', accept_request_path(request) %>
Also as a recommendation try to use a different name for your model since the word request is wide use in Rails. I don't know if this could be a problem latter on.
I have a many-to-many relationship between my reservation db and cars db, and the following is in my reservation controller and is routed to the post.
def reserveConfirm
pick_time = params[:pick_y].to_s+"-"+params[:pick_m].to_s+"-"+params[:pick_d].to_s+" "+"#{params[:pick_h]}:00:00"
return_time = params[:return_y].to_s+"-"+params[:return_m].to_s+"-"+params[:return_d].to_s+" "+"#{params[:return_h]}:00:00"
##reservation = Reservation.find(params[:id])
#car = Car.where(:id => params[:car_id]).update(:status => 'reserved')
#reservation = Reservation.new(status:'reserved',
pick_up_time: pick_time,
return_time: return_time,
user_id:current_user.id)
if #reservation.save
#flash[:success] = #reservation.id
flash[:success] = 'shit'
redirect_to(:action => 'history',:notice => 'Check out was successfully created.',:id =>current_user.id )
else
flash[:success] = 'success'
format.html { render action: "reserve" }
format.json { render json: #reservation.errors.full_messages, status: :unprocessable_entity }
end
end
things start to get confusing from here. In my reservation controller, every time i want params[:id], i am not getting the reservation id. I have my new reservation created and routed to get in action reserve. The [:id] seems to either be nil or a car_id, since the link i have is reservation/:id(:format), and this :id is somehow the cars id instead of my new reservation id. My reserve action does Reservation.new
def reserve
#reservation = Reservation.new
#car = Car.find(params[:car_id])
if #car == nil
flash[:danger] = "no car found"
else
flash[:danger] = #car.id
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: #reservation }
end
end
I am in the jungle and everything tangles up in the woods.
In reserve action, I can find car by car_id which is the reservation/:id filed, which is 2 here. But in my reserveConfirm, i am getting a nil #car object, which forces me to use where that finds all car with id , although only one cause the id is unique. And worse, after i get #car, i want to update its status to reserved, but when i look into db, it is not ever changed.
My form, which passes data is here:
<%= form_for #reservation,:url => { :action => "reserveConfirm" } do |f| %>
<%=f.label :Date%>
<%=f.date_select :pick_up_time %>
<%= f.hidden_field :car_id, :value=> #car.id %>
<%= f.hidden_field :user_id, :value=> current_user.id %>
<%= f.submit "Confirm", data: { confirm: 'Are you sure?', class: "btn btn-default" }%>
Hope someone can kindly help me with this, much appreciate!
First of all, you should verify if you are getting #car correctly.
I guess you are able to use 'byebug' . Try writing 'byebug' at beginning of reserveConfirm method.
def reserveConfirm
byebug
#your code
end
Using byebug, you can look your rails server (in terminal) and debug your code. Try writing 'params' to check all params that you are receiving. You can write 'exit' or 'continue' using byebug. (More info: Debugging using byebug)
If params[:car_id] exists, your code should be like:
#car = Car.find(params[:car_id])
#car.status = 'reserved'
if #car.update
#code
else
#code
end
Check that and tell me how it goes.
One of my model objects has a 'text' column that contains the full HTML of a web page.
I'd like to write a controller action that simply returns this HTML directly from the controller rather than passing it through the .erb templates like the rest of the actions on the controller.
My first thought was to pull this action into a new controller and make a custom .erb template with an empty layout, and just <%= modelObject.htmlContent %> in the template - but I wondered if there were a better way to do this in Rails.
In your controller respond_to block, you can use:
render :text => #model_object.html_content
or:
render :inline => "<%= #model_object.html_content %>"
So, something like:
def show
#model_object = ModelObject.find(params[:id])
respond_to do |format|
format.html { render :text => #model_object.html_content }
end
end
In latest Rails (4.1.x), at least, this is much simpler than the accepted answer:
def show
render html: '<div>html goes here</div>'.html_safe
end
Its works for me
def show
#model_object = ModelObject.find(params[:id])
respond_to do |format|
format.html { render :inline => "<%== #model_object['html'] %>" }
end
end
This is an error I can not seem to figure out I believe I have it routed. This is the error
No route matches {:action=>"ticket_action", :controller=>"tickets"}
I get this error after this code
<h4>New Action</h4>
<% form_tag :action => 'ticket_action' do %>
<p><b>Description</b><br/>
<%= text_area 'description', 'description', 'rows' => 5 %><br/>
User: <%= select("actUser", "user_id", User.find(:all).collect{|u| [u.name, u.id] } )%>
<% end %>
I have this on my ticket_controller.rb is that the proper placement for that
#action
def ticket_action
#act = Action.new(
"ticket_id" => flash[:ticket_id],
"description" => params[:description]['description'],
"user_id" => params[:actUser]['user_id']
)
routes
actions GET /actions(.:format) actions#index
POST /actions(.:format) actions#create
new_action GET /actions/new(.:format) actions#new
edit_action GET /actions/:id/edit(.:format) actions#edit
action GET /actions/:id(.:format) actions#show
PUT /actions/:id(.:format) actions#update
DELETE /actions/:id(.:format) actions#destroy
tickets GET /tickets(.:format) tickets#index
POST /tickets(.:format) tickets#create
new_ticket GET /tickets/new(.:format) tickets#new
edit_ticket GET /tickets/:id/edit(.:format) tickets#edit
ticket GET /tickets/:id(.:format) tickets#show
PUT /tickets/:id(.:format) tickets#update
DELETE /tickets/:id(.:format) tickets#destroy
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
clients GET /clients(.:format) clients#index
POST /clients(.:format) clients#create
new_client GET /clients/new(.:format) clients#new
edit_client GET /clients/:id/edit(.:format) clients#edit
client GET /clients/:id(.:format) clients#show
PUT /clients/:id(.:format) clients#update
DELETE /clients/:id(.:format) clients#destroy
It would be helpful to post the route to debug this problem, your route may refer to tickets yet your class is ticket.
You should look into restful routes, especially given your use case. It seems you should really have an actions controller (ActionsController, named controllers/actions_controller.rb) and then post to the create action and provide a restful route (resources :actions)
My suggestion would be to read up on rest and rails first.
Additionally the flash isn't where you should store your ticket_id, ideally you should retrieve it in your actions controller's create action by posting to /action/ticket_action/1 and retrieving the id by accessing params[:id] in the controller. If you really must, store it in the session (session[:ticket_id] = "1") but 'rest' is where you should be headed. The flash will be removed and should only be set in the controller and then displayed on the next page, it will be deleted thereafter.
Update: ok thanks for posting your routes.
You can add the missing route like this if you want:
resources :tickets do
member do
post 'ticket_action'
end
end
But it would be better to follow this pattern:
In actions controller:
def new
#action = Action.new
end
Your form should look a bit like this, Rails will know to post to actions#create because #action is a new record (you can check #action.new_record? if you want)
<%= form_for #action do |f| %>
<%= f.text_area :description, :rows => 5 %>
<%= f.hidden_field :ticket_id, flash[:ticket_id] %>
<%= f.select :user_id, User.find(:all).collect{|u| [u.name, u.id] } %>
<%= f.submit "Create" %>
<% end %>
Then in your actions controller:
def create
#action = Action.new(params[:action])
end
or with less magic:
def create
#action = Action.new(:user_id => params[:action][:user_id],
:description => params[:action][:description],
:ticket_id => params[:action][:ticket_id])
if #action.save
redirect_to actions_path(#action, :notice => "Created action")
else
render :new # any errors will be in #action.errors
end
end
You should really be setting the ticket_id in the actions controller's new method though.
def new
#action = Action.new(:ticket_id => params[:ticket_id])
end
And then in your form:
<%= f.hidden_field :ticket_id %>
Your file name should be "tickets_controller.rb", plural.
is it possible to link to a method inside a different model? To execute on button press, or is there another way of doing this, something like an action in a controller?
Method inside staff model:
def clearleave
self.where("grade = '1'").update_all(:leave_balance => 22)
self.where("grade = '2'").update_all(:leave_balance => 25)
self.where("grade = '3'").update_all(:leave_balance => 30)
self.where("grade = '4'").update_all(:leave_balance => 35)
end
inside a view for a different model:
<%=button_to "Clear absences", {:controller => :staffs, :action => :clearleave} %>
Rails bases on the Model View Controller pattern (MVC). This means, that requests (e.g. trough the browser) are handled by your controllers. Controllers will collect the required data from the models and pass it to the views for display.
What you are probably aiming for is something like this:
Routes:
resources :staff do
member do
post :clearleave
end
end
Controller:
# StaffController
def clearleave
#staff = Staff.find(params[:id])
#staff.clearleave # this calls the method in your model
# here you could redirect to e.g. the show page for your staff
# redirect_to staff_path(#staff), :notice => "Cleared successfully"
end
Your button in the view would be:
<%= button_to "Clear absences", clearleave_staff_path(#staff) %>
<!-- not sure if a ", :method => :post" is required here as well -->
<!-- in rails 3 a link_to should also work -->
<%= link_to "Clear absences", clearleave_staff_path(#staff), :method => :post %>