unable to retrieve data from a form in rails - ruby-on-rails

i am trying to access the data from a form.
<% form_tag(:action => "test") do %>
<p>
Name:
<%= text_field_tag("name","web programmer") %>
</p>
<%= submit_tag ("Save data") %>
<% end %>
this form is in views/challenges/show.html
I have written this piece of code in challenges_controller
def test
#name = params[:name]
end
before_filter :test
now,If i try to access #name variable in views/challenges/show.html
heres the code for that part
<% if #name != null %>
<%= #name %>
<% end %>
I get the following error
"undefined local variable or method `null' "
i have addded the following route to my routes.rb
get 'challenges/test'
Can someone help me out with this issue?

You need to display your form so instead of using <% %> you need to use <%= %>, checkout this answer for differences between them. By default forms use POST verb and you have defined a route for GET request. Change your form to this:
<%= form_tag({action: :test}, {method: :get}) do %>
<p>
Name:
<%= text_field_tag("name","web programmer") %>
</p>
<%= submit_tag ("Save data") %>
<% end %>

Related

Render in a different order on the page breaks the routing

I have Challenges containing Puns, and it is possible to vote on puns. On the Challenge Show page, all puns are rendered and show their votes count. This is currently on the view page:
<%= render #challenge.puns.reverse %>
<br>
<div id="form">
<%= render "puns/form" %>
</div>
I want the puns form to appear above the items (puns) already submitted. But if swap them around, like this:
<div id="form">
<%= render "puns/form" %>
</div>
<%= render #challenge.puns.reverse %>
I get a controller error and pun.id is not suddenly not available and the voting link breaks.
No route matches {:action=>"upvote", :challenge_id=>"9", :controller=>"puns", :id=>nil}, missing required keys: [:id]
Here is the puns/form part that is causing the issue
<% if signed_in? %>
<% if current_user.voted_for? pun %>
<%= pun.votes_for.size %>
<span class="pun_text"><%= link_to pun.pun_text, challenge_pun_path(#challenge, pun.id) %></span>
<% else %>
<%= link_to like_challenge_pun_path(#challenge, pun.id), method: :put do %>
<span class="heart_like">❤</span> <%= pun.votes_for.size %>
<% end %>
<span class="pun_text"><%= link_to pun.pun_text, challenge_pun_path(#challenge, pun.id) %></span>
<% end %>
<% end %>
It is the like_challenge_pun_path that throws an error but I cannot understand why. I am declaring #challenge again here, so it should be able to get the id.
Here is the form for the puns:
<%= form_for([#challenge, #challenge.puns.build]) do |f| %>
<span class=".emoji-picker-container">
<%= f.text_area :pun_text, placeholder: "Add pun", data: { emojiable: true } %>
</span>
<%= f.submit %>
<% end %>
Also, here is my routes setup
resources :challenges do
resources :puns do
member do
put "like", to: "puns#upvote"
put "dislike", to: "puns#downvote"
end
end
end
and the corresponding action to upvote
def upvote
#pun = #challenge.puns.find(params[:id])
#pun.upvote_by current_user
redirect_to #challenge
end
Can anyone help?
I think the code is for the puns collection.
I assume the issue is that in the form you have something like:
#challenge.puns.build
So in #challenge.puns collection appears not persisted record (without id), so path for this model cannot be generated.
As a quick solution I suggest:
<%= render #challenge.puns.reverse.select(&:persisted?) %>
UPDATE:
As I assumed you have
<%= form_for([#challenge, #challenge.puns.build]) do |f| %>
You can also try:
<%= form_for([#challenge, Pun.new]) do |f| %>
Or solve it in the controller. But need to see controller code for it.

Rails 5. How to submit from the form_tag to custom action?

I'm a real newbie at Ruby and Rails, and I've been looking for the solution for two days. I need to submit data from form_tag to action 'create' in my controller to add new entries to database, but looks like I'm doing something terribly wrong, because absolutely nothing happens, and it seems that form_tag doesn't even redirect to needed action.
Here's the page code:
<h1>Todos</h1>
<% #projects.each do |project| %>
<tr>
<h2><%= project.title %></h2>
<% project.todos.each do |todo| %>
<ul style="list-style-type:disc">
<li><%= todo.text %></li>
</ul>
<% end %>
</tr>
<% end %>
<%= form_tag({controller: "mega", action: "create"}, method: "get", remote: true) do %>
<h2>New todo</h2>
<p>
<%= text_field_tag 'text' %>
</p>
<p>
<%= select_tag 'title', options_from_collection_for_select(#projects, 'id', 'title') %>
</p>
<p>
<%= link_to 'CANCEL' %>
<%= link_to 'OK', "", :onclick => "$('#form_id').submit()" %>
</p>
<% end %>
And the controller:
class MegaController < ApplicationController
def index
#projects = Project.all
#todos = Todo.all
end
def update
end
def create
#newTodo = Todo.create(text: params[:text])
#newProject = Project.find_by(title: params[:title])
#newProject.todos << #todo
#newTodo.save
end
end
My routes file. I seriously don't know how it works:
Rails.application.routes.draw do
get 'mega/index'
root 'mega#index'
get 'mega/update'
post 'mega/create'
resources :todos
resources :projects
end
You create resources with a POST request. Never GET.
GET requests should be idempotent - they should not update or alter resources on the server. One very important reason is that they are stored in the browser's history, so pressing the back button will cause unintended consequences for the user.
In Rails flavor MVC instead of tacking the action name on the path of the route you use the HTTP verb to create routes to the correct action:
GET /things things#index
POST /things things#create
I'm not going to attempt to salvage your code (it's deeply flawed) and instead show you how you would solve this the rails way as it is much simpler:
<%= form_for(Todo.new) do |f| %>
<h2>New todo</h2>
<%= f.text_field :text %>
<%= f.collection_select(:project_id, #projects, :id, :title, prompt: true) %>
<%= f.submit %>
<% end %>
This would submit to todos#create - if you want to route it to an unconventional action you can use the url option:
<%= form_for(Todo.new, url: polymorphic_path(controller: 'foo', action: 'bar')) do |f| %>
It's best to learn the rules before you break them.

strong parameters with multi-model form

I have the following form:
<%= form_tag classification_code_rules_path do %>
<% #classification_code_rules.each do |rule| %>
<%= fields_for "classification_code_rule[]", rule do |pf| %>
<%= pf.text_field :name %>
<% end %>
<% end %>
<%= submit_tag %>
<% end %>
It sends what I want to the server:
Parameters: { ... "classification_code_rule"=>[{"name"=>"dasdsaf"}, {"name"=>"sfsdgdfhgf"}, {"name"=>"hfghfgjhgjhg"}], "commit"=>"Save changes"}
Since classification_code_rule is an array, I handle the params as follows:
def classification_code_rule_params
params[:classification_code_rule].each do |rule_param|
rule_param.permit!
end
end
But I am getting the following error:
When assigning attributes, you must pass a hash as an argument.
How can I handle this situation where the strong param is an array?
Try something like this
params.require(:classification_code_rule).map do |rule_param|
ActionController::Parameters.new(rule_param.to_hash).permit!
end

Add id to url wont work

I have two model less views.
An index view:
<% #icd1.each do |f| %>
<%= link_to "#{f.von} #{f.bis} #{f.bezeichnung}", icd_show_path(f) %>
</p>
<% end %>
And an show view:
<% #icd1.each do |f| %>
<%= link_to "#{f.von} #{f.bis} #{f.bezeichnung}", icd_show_path(f) %>
</p>
<% f.icd2.each do |s| %>
<%= s.von %><%= s.bis %><%= s.bezeichnung %>
</p>
<% end %>
<% end %>
My controller:
class IcdController < ApplicationController
def index
#icd1 = Icd1.all
end
def show
#icd1 = Icd1.find(params[:id])
end
end
But somehow the link in the index view, wont work:
<%= link_to "#{f.von} #{f.bis} #{f.bezeichnung}", icd_show_path(f) %>
When i try to access the show page i get the error:
Couldn't find Icd1 without an ID
and the url only shows
http://localhost:3000/icd/show
without an id!
My routes:
get "icd/index"
get "icd/show"
1st: Very confusing naming: controller icd, model icd1..
2nd:
get "icd/show/:id", to: "icd#show", as: "icd_show"
or
get "icd/:id/show", to: "icd#show", as: "icd_show"
depends what url you want to get. It is confusing.
but I think this is what you need in your url;
<%= link_to "#{f.von} #{f.bis} #{f.bezeichnung}", icd_show_path(f) %>
and also the routes:
get "icd/:id", to: "icd#show", as: "icd_show"
after this next url will be available:
../icd/1 that will call action show from icd controller

Rails and Ajax - form_remote_tag Can't find my error

On my site, the user can watch his profile. In his profile he can have a look at his data (i.e. signature).
Now I want my users being able to edit this data while watching it.
So I coded the following in my view:
<div id="profile-signature">
<p>
<b>Signature:</b>
<%=h #user.signature %>
</p>
<%= form_remote_tag(:update => "signature",:url => { :action => :update_signature }) %>
<%= text_area(:signature,:class=>"form-textarea") %>
<%= submit_tag "Save Signature" %>
</div>
in my user controller, I created a new action update_signature
def update_signature
puts 'in function!'
#user = current_user
puts #user.login
puts params[:signature]
#user.signature = params[:signature]
#user.save
puts 'saved'
end
Now, submitting the form, puts params[:signature] will output: classform-textareasfsffsfs
where sfsffsfs is the text I entered.
Reloading and my page and output the signature on page (<%=h #user.signature %>), I get:
"--- !map:HashWithIndifferentAccess classform-textarea: sfsffsfs "
Why do I get this strange string instead of just sfsffsfs (in this case)?
What to do, to update the data (<%=h #user.signature %>) automatic without page reload?
Use text_area_tag for getting the text_area field values . With reloading the page there is a mismatch in the div id it should be signature not profile-signature .
<div id="profile-signature">
<p>
<b>Signature:</b>
<%=h #user.signature %>
</p>
<%= form_remote_tag(:update => "signature",:url => { :action => :update_signature }) %>
<%= text_area(:signature,:class=>"form-textarea") %>
<%= submit_tag "Save Signature" %>
</div>
Make the following changes
<div id="signature">
<p>
<b>Signature:</b>
<%=h #user.signature %>
</p>
<%= form_remote_tag(:update => "signature",:url => { :action => :update_signature }) %>
<%= text_area_tag(:signature,:class=>"form-textarea") %>
<%= submit_tag "Save Signature" %>
</div>
Hope this helps !
It looks like your text_area call isn't quite right, looking at the docs it should be like this:
text_area(object_name, method, options = {})
so your css class is being set as the method, instead you should use text_area_tag:
<%= text_area_tag(:signature, #user.signature, :class=>"form-textarea") %>
Then the correct value (the text in the text area) should be submitted as the params you're expecting.

Resources