I am currently creating a rails form. Up until now it has been passing data to the database with ease. Recently, however it no longer finds any of the data I need in the database, it can only find the user table and none of the connected tables.
Here is a partial of my form:
<h1>Energy Assistance Application</h1>
<br />
<%= form_for(#user) do |f| %>
<%= render 'county_fields', f: f%>
<%= render 'contact_info_fields', f: f %>
<%= render 'household_members_fields', f: f%>
<%= render 'household_type_fields', f: f%>
Here is part of my controller:
def create
addresses = params[:addresses].permit([:county]).to_h
contact_info = params[:contact_info].permit(params[:contact_info].keys).to_h
household = params[:household_type].permit([:house_type]).to_h
household_members = member_params
utilities = utility_params
dhis = dhi_params
#workflow = CreatesUser.new(address_info: addresses,
contact: contact_info, household: household, members: household_members, utilities: utilities, dhis: dhis)
#workflow.create
redirect_to users_path
end
CreatesUser:
def initialize(address_info: [], has_mail: false, contact: [], household: [], members: [],
utilities: [], dhis: [])
#address_info = address_info
#contact = contact
#household = household
#members = members["household_members_attributes"]
#utilities = utilities["utilities_attributes"]
#dhis = dhis["dhis_attributes"]
end
def build
self.user = User.new(startdate: Time.zone.today)
user.addresses = get_addresses
user.contact_info = get_contact
user.household_type = get_household
user.household_members = get_members
user.utilities = get_utilities
user.dhis = get_dhis
user
end
def create
build
result = user.save
result ? print("Saved!\n") : print("Failed!\n")
end
My index.html.erb:
<h1>All Users</h1>
<% #users.each do |user|%>
<%= user.utilities%>
<ul>
<li>County:
<% user.addresses.each do |address|%>
<%=address.county%>
<%end%>
</li>
<% if !user.contact_info.nil? %>
<li>Phone: <%= user.contact_info.phone%></li>
<li>Phone Type:<%= user.contact_info.phone_type%></li>
<li>Email: <%= user.contact_info.email%></li>
<%end%>
<li>Household: <%= user.household_type.house_type%></li>
</ul>
When the workflow creates, it saves successfully, but when I run my index I get this error:
Completed 500 Internal Server Error in 19ms (ActiveRecord: 1.1ms)
ActionView::Template::Error (undefined method `house_type' for nil:NilClass):
12: <li>Phone Type:<%= user.contact_info.phone_type%></li>
13: <li>Email: <%= user.contact_info.email%></li>
14: <%end%>
15: <li>Household: <%= user.household_type.house_type%></li>
16: </ul>
17:
18: <h3> Household Members </h3>
app/views/users/index.html.erb:15:in `block in _app_views_users_index_html_erb___590344624549979162_70244223831340'
I do not know why this is happening, even when I go back to older branches that used to work, they also fail here.
Thank you for any help you can give me. If you need more info, I will happily give it to you.
I think your problems in your form. Recheck your params ( household_type ), it must have a value when submit.
And another way, if you want update difference model based on current model, you should use Active Record Nested Attributes
Related
I am trying to make the vote total editable from a JSon parsed API. I have the following in my rosters controller:
def index
#rosters = HTTParty.get('https:api', :headers =>{'Content_Type' => 'application/json'})
#allrosters = Roster.all
#allrostershash = {}
#allrosters.each do |roster|
image_url = roster['image_url']
#allrostershash[ image_url ] = roster
end
#rosters.each do |roster|
img_url = roster['image_url']
unless #allrostershash[img_url]
Roster.create(roster)
end
end
end
def count_vote
roster_id = params[:id]
roster = Roster.find_by(roster_id)
newvote = roster.vote + 1
if roster.update({vote: newvote})
redirect_to rosters_path
end
end
Roster is the name of my class above. In my rails views I have the following:
<% #rosters.each do |roster| %>
<div class='each'>
<%= image_tag(roster['image_url'], class: 'image') %>
<%= hidden_field_tag(roster['id']) %>
<p class='name'> <%= roster['name'] %> </p>
<p class='title'> <%= roster['title'] %> </p>
<p> <%= roster['bio'] %> </p>
<p> <b> Want to work with <%= roster['name'] %>? </b> <%= link_to image_tag('yes.jpg', class: 'yes'), rosters_path, method: :patch %>
<br>
<%= roster['vote'] %> People have said Yes! </p>
<br>
</div>
<% end %>
I would like that every time someone clicks on yes.jpg, the roster['vote'] increases by 1.
Currently my routes are set up as follows:
get 'rosters', to: 'rosters#index'
patch 'rosters', to: 'rosters#count_vote'
I'm trying to accomplish this without jquery or ajax, that's why I have the if roster.update portion to redirect to rosters_path, so it basically refreshes the page upon click. Right now it isn't updating the vote total however, I'm not sure what I'm missing. I would like to do it all on a single page so if its not possible without JQuery, any guidance in right direction is appreciated.
count_vote will silently fail if it cannot find your Roster or if the update cannot be saved. Change it so it raises an exception of anything fails.
def count_vote
roster = Roster.find(params[:id])
roster.vote += 1
roser.save!
redirect_to rosters_path
end
find will raise RecordNotFound if the Roster cannot be found. save! will raise an error if the changes cannot be saved.
These are the only params currently for some reason ActionController::Parameters {"_method"=>"patch", "authenticity_token"=>"qbORnCLNnI9P1zUZ02VEP3qJMwYOGa5sGw6KblPFj99mvjwZQj9VnDQ2e+6ZStJi3PJZ3MidSMsdoWlwOgBN9w==", "controller"=>"rosters", "action"=>"count_vote"} permitted: false> how would I add an id param? – Sohel 5 hours ago
I'm not very familiar with how views work, but I think as in this example, I believe you need to pass the roster into rosters_path.
<%= link_to image_tag('yes.jpg', class: 'yes'), rosters_path(roster), method: :patch %>
Similarly, if you want count_vote to redirect back to the roster you just changed...
redirect_to rosters_path(roster)
I have an app where users can create their own forms and then apply them to their own clients
The forms are created dynamically, meaning users can add as many questions they want, and each question has many choices (think of a survey structure).
So far so good, now I'm struggling when applying the forms, specifically getting the answers saved, persisted and showing properly when rendering the edit view.
When rendering the edit view, each question has their choices multiplied by how many questions/answers the answered_form has (I don't know exactly which of them, I am guessing here).
Answers are persisted to database, although each question has their choices multiplied, the selected answer is checked and is checked in the collection of the original answer. (answer one checked in the first 3 choices, answer two in the second 3 choices, answer three in the third 3 choices and answer four in the forth 3 choices)
I've read 2 similar questions here in SO, RoR nested attributes produces duplicates when edit, and Nested form update action producing duplicate results, but I already have the :id in strong parameters (you can see it in the code below).
I want to make myself clear here: creating the form, with nested question and nested choices is working perfectly fine, and also editing the created form. The struggle is when USING, ANSWERING or APPLYING it in the APP.
Code:
_form.html.erb:
<%= form_for [#child, #answered_form] do |f| %>
<%= f.hidden_field :form_id %>
<%= f.hidden_field :child_id %>
<div class="answered_form">
<h1><%= #form.f_title %></h1>
<h3><%= #form.f_description %></h3>
<br>
<% questions = #form.questions %>
<% i = 1 %>
<% questions.each do |question| %>
<%= i.to_s + ". " %><%= question.q_title %>
<br />
<% choices = question.choices %>
<%= f.fields_for :answers do |a| %>
<% choices.each do |choice| %>
<%= a.radio_button :a_content, choice.c_description %>
<%= a.label :a_content, choice.c_description, :value => choice.c_description, class: 'no-margin' %>
<br />
<% end %>
<% end %>
<br />
<% i += 1 %>
<% end %>
</div>
<div class="text-center">
<%= f.submit yield(:button_text), class: "btn btn-primary btn-lg" %>
</div>
<% end %>
answered_forms_controller.rb:
class AnsweredFormsController < ApplicationController
before_action :correct_answered_form, only: [:edit, :update, :destroy]
def new
#child = current_user.children.find(params[:child_id])
#form = current_user.forms.find(params[:form_id])
#answered_form = #child.answered_forms.new(form_id: params[:form_id])
#answered_form.answers.build
end
def create
#answered_form = AnsweredForm.create(answered_form_params)
if #answered_form.save
flash[:success] = "New survey " + #answered_form.form.f_title + " applied to patient!"
redirect_to current_user.children.find(params[:child_id])
else
render 'new'
end
end
def edit
#child = current_user.children.find(params[:child_id])
#form = current_user.forms.find(params[:form_id])
end
def update
if #answered_form.update_attributes(answered_form_params)
flash[:success] = "Survey updated!"
redirect_to #answered_form.child
else
render 'edit'
end
end
def show
end
def destroy
#child = current_user.children.find(params[:child_id])
#form = current_user.forms.find(params[:form_id])
#answered_form.destroy
redirect_to :back
end
private
# Strong params for creating and updating forms
def answered_form_params
params.require(:answered_form).permit(:form_id, :child_id, answers_attributes: [:id, :a_content, :a_boolean, :_destroy, :choice_id])
end
# Confirms the correct answered_form
def correct_answered_form
#answered_form = AnsweredForm.find(params[:id])
end
end
Logs:
POST:
Started POST "/children/1-juan-gomez-pereira/answered_forms" for ::1 at 2016-07-08 11:55:01 -0400
Processing by AnsweredFormsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hFrRfEwVG4XSkdbPwrohm1QEQ0FtE/as3sM2Fj3Av3reVHJxZBVKPeuAeD713H7gVyZn7eppnULDhLJQz+EBeg==", "answered_form"=>{"form_id"=>"1", "child_id"=>"1", "answers_attributes"=>{"0"=>{"a_content"=>"Bajo"}, "1"=>{"a_content"=>"Sí"}, "2"=>{"a_content"=>"Derecha"}, "3"=>{"a_content"=>"Pesado"}}}, "commit"=>"Aplicar", "child_id"=>"1-juan-gomez-pereira"}
PATCH:
Started PATCH "/children/1-juan-gomez-pereira/answered_forms/3" for ::1 at 2016-07-08 11:55:54 -0400
Processing by AnsweredFormsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"oGdqgUR95HMkMff40Gq1zWar/CH64F0jsN3oRHT1q/H6acmMbH21yx0gWQnnDOq2ZYnYjX2aNs2tmmwChtQV8Q==", "answered_form"=>{"form_id"=>"1", "child_id"=>"1", "answers_attributes"=>{"0"=>{"a_content"=>"Bajo", "id"=>"9"}, "1"=>{"a_content"=>"Bajo", "id"=>"10"}, "2"=>{"a_content"=>"Bajo", "id"=>"11"}, "3"=>{"a_content"=>"Confuso", "id"=>"12"}, "4"=>{"a_content"=>"No", "id"=>"9"}, "5"=>{"a_content"=>"Sí", "id"=>"10"}, "6"=>{"a_content"=>"Confuso", "id"=>"11"}, "7"=>{"a_content"=>"Confuso", "id"=>"12"}, "8"=>{"a_content"=>"Confuso", "id"=>"9"}, "9"=>{"a_content"=>"Izquierda", "id"=>"10"}, "10"=>{"a_content"=>"Confuso", "id"=>"11"}, "11"=>{"a_content"=>"Izquierda", "id"=>"12"}, "12"=>{"a_content"=>"Liviano", "id"=>"9"}, "13"=>{"a_content"=>"Liviano", "id"=>"10"}, "14"=>{"a_content"=>"Pesado", "id"=>"11"}, "15"=>{"a_content"=>"Liviano", "id"=>"12"}}}, "commit"=>"Actualizar", "child_id"=>"1-juan-gomez-pereira", "id"=>"3"}
I noticed that when POST, the id for answer is not passed as a parameter. If I check the console, I can see that answer was created properly.
I think this line could be the problem
<% choices.each do |choice| %>
If you have built question.answers, you can iterate on them only using f.fields_for :answers and skip the above line. I assume choices are not much different from answers.
Please clear me if i am wrong.
So the problem was in this line of the code:
<%= f.fields_for :answers do |a| %>
fields_for helper generates fields for the entire collection of the object for whom your are calling it.
In this case, #answered_form had 4 answers after creating it, so when calling fields_for in edit, it was generating 4 fields set for each question.
To solve this, you need to specify a collection that fits your needs and pass it through the fields_for helper:
<%= f.fields_for :answers, ANSWERS_COLLECTION do |a| %>
I'm building a basic forum application in Ruby on Rails (v4.1.7) and I'm having an issue with displaying the topics in descending order based on their last post. The code I'm using below will show the topics in the correct descending order, however the last post times and last poster name are wrong.
When I view the topic with comments#index, these data are correct. Both comments#index and topics#index call the same partial to display the topic:
I believe this may have to do with me calling topic.comments.last
Testing it out, it seems to be displaying the FIRST comments userdata and created_at, rather than the last, however the forums ARE showing up in the correct order.
Partial: _topic.html.erb:
<article class="topic">
<h2><%= link_to(topic.title, topic_comments_path(topic)) %></h2>
<div class="author">
By <strong><%= topic.user.name %> </strong>
on <%= topic.created_at.strftime('%b %d %Y') %>
</div>
<div class="stats">
Viewed <%= pluralize(topic.view_count, 'time') %>.
<% if topic.comments.any? %>
Last comment <%= time_ago_in_words(topic.comments.last.created_at) %> ago
by <%= topic.comments.last.user.name %>.
<% else %>
No comments.
<% end %>
<span class="pull-right">
<%= pluralize(topic.comments.count, 'comment') %>.
</span>
</div>
</article>
topics_controller#index (produces incorrect data):
def index
#topics = Topic.includes(:comments).order('comments.created_at desc')
end
I have also attempted:
def index
#topics = Topic.includes(:comments).paginate(page: params[:page]).order('comments.created_at desc')
end
topics/index.html.erb(wrong data):
<% provide(:title, 'Forum Index') %>
<%= render partial: #topics, spacer_template: 'shared/hr' %>
Viewing a specific thread (in this case the topic.comments.last.user.name and topic.comments.last.created_at are the correct values):
def index
#context = context
#comments = #context.comments.paginate(page: params[:page])
end
#...
private
def context
Topic.find(params[:topic_id]) if params[:topic_id]
end
topics/index.html.erb (right data):
<% provide(:title, #context.title) %>
<h1>View Discussion</h1>
<%= render(partial: 'topics/topic', object: #context) %> # Partial with right data
<hr />
<%= render(partial: 'comment',
collection: #comments,
spacer_template: 'shared/hr',
locals: { topic: #context }) || 'No comments.' %>
<hr />
<%= render partial: 'comment_form', locals: { context: #context,
comment: #context.comments.new } %>
topic.comments.last
should be
topic.comments.first
because you're placing the latest comments first.
Where it's working fine, it is because you aren't ordering the comments and the last will fetch the comment with the highest primary index value which is most likely the ID.
Hope that clears it up.
And just FYI:
topic.comments.count
will fire up another query in your view. Change the count to size
I'm trying to follow the tutorial Searching and Buying Twilio Phone Numbers here -->http://www.twilio.com/docs/howto/search-and-buy
For now, All I want to do is to list the available phone numbers. Right now I have a find_numbers controller, with new, create, destroy.
The New Action has paramaters which the user fills out, and the create action renders the show, and the show is supposed to put it all together, and list the numbers.
However, with the code that I have, I get the error
NoMethodError in Find_numbers#create
Showing C:/Sites/dct/app/views/find_numbers/show.html.erb where line #1 raised:
undefined method `each' for nil:NilClass
I think it's because my #numbers variable is returning nil, because the search parameters aren't set correctly.
Here's my view for the new action :
<div class="container">
<div class="row">
<div class="span6 offset3">
<%= form_tag("/find_numbers", :method => "post" ) do %>
<%= label_tag(:in_postal_code, "Near US postal code (e.g. 94117):") %>
<%= text_field_tag(:in_postal_code) %>
<%= label_tag(:near_number, "Near this other number (e.g. +4156562345)") %>
<%= text_field_tag(:near_number) %>
<%= label_tag(:contains, "Matching this pattern (e.g. 415***EPIC):") %>
<%= text_field_tag(:contains) %>
<%= submit_tag("Search", :class => "btn btn-large btn-primary") %>
<% end %>
</div>
</div>
</div>
This is the find_numbers controller
class FindNumbersController < ApplicationController
def new
#user = current_user
end
def create
#user = current_user
render 'find_numbers/show'
end
def show
#user = current_user
client = Twilio::REST::Client.new(#user.twilio_account_sid, #user.twilio_auth_token)
search_params = {}
%w[in_postal_code near_number contains].each do |p|
search_params[p] = params[p] unless params[p].nil? || params[p].empty?
end
local_numbers = client.account.available_phone_numbers.get('US').local
#numbers = local_numbers.list(search_params)
end
end
And this, is the show view
<%= number.friendly_name %>
<%= number.phone_number %>
I'm getting closer to the answer since this morning(China time), but still running around in circles! Any help greatly appreciated.
You might want to learn a little more about rails. The book I used to get started is http://pragprog.com/book/rails4/agile-web-development-with-rails
What you are doing right now seems to go against how rails is designed to work but you might be able to put the following in your create action:
#user = current_user
client = Twilio::REST::Client.new(#user.twilio_account_sid, #user.twilio_auth_token)
search_params = {}
%w[in_postal_code near_number contains].each do |p|
search_params[p] = params[p] unless params[p].nil? || params[p].empty?
end
local_numbers = client.account.available_phone_numbers.get('US').local
#numbers = local_numbers.list(search_params)
render 'find_numbers/show'
Also remember that you have the object #numbers so in your show view you'll have to do an each loop like:
<% #numbers.each do |number| %>
<%= number.friendly_name %>
<%= number.phone_number %>
<% end %>
I don't know anything about Twilio so I can't check over your use of their API.
I'm creating a little newsletter application, with 'double opt-in restrictions', when I simply fill in my form (subscription page) and submit the form I get redirected to my subscribed page (which is all normal) however my form appends a querystring to my action attribute of my form (http://localhost:3000/newsletter/subscribe?format=)
routes:
match 'newsletter/subscription' => 'newsletter_subscriptions#subscription'
post 'newsletter/subscribe' => 'newsletter_subscriptions#subscribe'
controller:
class NewsletterSubscriptionsController < ApplicationController
respond_to :html
# GET /newsletter/subscription
def subscription
respond_with (#subscription = NewsletterSubscription.new)
end
# POST /newsletter/subscribe
def subscribe
# If there's already an unconfirmed record with the submitted email, use that object otherwise create a new one based on the submitted email
sub_new = NewsletterSubscription.new
sub_new.email = params[:newsletter_subscription]['email']
sub_old = NewsletterSubscription.find_by_email_and_confirmed sub_new.email, 0
#subscription = sub_old || sub_new
if #subscription.save
Newsletter.delay.subscribed(#subscription) # with delayed_job
else
render :action => "subscription"
end
end
...
end
view (newsletter_subscription/subscription.html.erb):
<h1>New newsletter_subscription</h1>
<%= form_for(#subscription, :url => newsletter_subscribe_path(#subscription)) do |f| %>
<% if #subscription.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#subscription.errors.count, "error") %> prohibited this newsletter_subscription from being
saved:</h2>
<ul>
<% #subscription.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email %>
<br/>
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
PS: I would be pleased if someone could evaluate my ruby code please (posted above), I'm still learning a lot and would like to see some 'guidelines' or feedback, I think I still can learn a lot.
Try removing the #subscription argument you're passing into newsletter_subscribe_path. Since there isn't an :id in the route and it's a new object, passing it doesn't really make sense. I'm assuming that's what is being interpreted as the format.
<%= form_for(#subscription, :url => newsletter_subscribe_path) do |f| %>
As for improvements you can make to the code, the biggest thing I see is moving the old/new subscription logic into the model.
# in NewsletterSubscription
def self.with_email(email)
find_by_email_and_confirmed(email, 0) || new(:email => email)
end
# in controller
#subscription = NewsletterSubscription.with_email(params[:newsletter_subscription]['email'])
if #subscription.save
#...
Also respond_to and respond_with aren't really necessary here since you're just dealing with HTML views. You can remove that.