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.
Related
I created a button where users can input stuff in a field and then press the button to update the database (put request) which can be seen here in show.html.erb:
<% provide(:title, #user.name) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
<br>
<%= #user.email %>
<% if #errors %>
<p>THE FORM COULD NOT BE SAVED </p>
<ul id='errors'>
<% #errors.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<% end %>
<br>
<% if is_admin? %>
<% if !#user.admin %>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", :action => "set_wistia_project_ID", :method => :patch, :form_class => "form-control" %>
<% end %>
</div>
</div>
<% end %>
<% end %>
</h1>
</section>
</aside>
</div>
The function is in user_controller.rb:
# Sets wistia_project_ID.
def set_wistia_project_ID
#user = User.find(params[:id])
#user.set_project_id
unless #user.valid?
#errors = #user.errors.full_messages
render :show
end
end
That function calls another function, just to separate things more clearly. This other function lives in user.rb:
# Sets the wistia_project_ID.
def set_project_id!(val)
self.wistia_project_ID = val # self is necessary here
save # or self.save, but the self is unnecessary here
end
My routes.rb:
.
.
.
resources :users do
member do
patch 'set_wistia_project_ID'
end
end
My problem is that right now, when you press the button, it says: Completed 500 Internal Server Error in 26ms (ActiveRecord: 0.7ms)
and
NoMethodError (undefined method `set_project_id' for #<User:0x000055b1a0914ab8>
2019-06-26T14:46:34.940086+00:00 app[web.1]: Did you mean? wistia_project_id):
Zavitoski got it right. I suggest, however, that you're doing a number of things more fundamentally wrong. Given that you're early in your rails journey, I hope you don't mind if I point a few things out.
First, and to be nit-picky, yes, you created a button. But, it is not a button "where users can input stuff in a field and then press the button to update the database". You created a button on a form. And you created a field on that form. The user can input stuff into the field. And when clicked, the button submits the form which includes the information in the field.
Now, on that form, you did:
<%= form_for(#user) do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", :action => "set_wistia_project_ID", :method => :patch, :form_class => "form-control" %>
<% end %>
There are a few things wrong with:
:action => "set_wistia_project_ID"
First, set_wisteria_project_ID is not a very ruby-ish action name. set_wistia_project_id would be more like it. Also, you're using old-form key-value formatting. And, you can use a symbol instead of a string for your action name so your code is prettier. Something, perhaps, like:
<%= f.submit "Save", action: :set_wistia_project_id, method: :patch, form_class: "form-control" %>
But, that's a mistake, too. Because you don't need a set_wistia_project_id action. (It's an action or a method, not a function.) You already have the update action. And form_for is smart enough to submit to this action if #user is an instance of User. So, really, you should do:
<%= form_for #user do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", form_class: "form-control" %>
<% end %>
I'm not sure what form_class is, but I'll trust that it's correct.
Now, in your UsersController, just do:
class UsersController < ApplicationController
def update
#user = User.find(params[:id])
if user.update(user_params)
# do something successful
else
# do something unsuccessful
end
end
private
def user_params
# NOTE: You'll probably want to permit other stuff here, too.
params.require(:user).permit(:wistia_project_id)
end
end
Get rid of this:
class User < ApplicationRecord
# Sets the wistia_project_ID.
def set_project_id!(val)
self.wistia_project_ID = val # self is necessary here
save # or self.save, but the self is unnecessary here
end
end
Because you're just duplicating the update method. And, you probably want that attribute to be wistia_project_id, not wistia_project_ID. (Again, you never see _ID as the suffix in rails core and you might as well be conventional.) And, if you make sure you have your association set up correctly, ActiveRecord should make sure that wistia_project_id is actually a valid value.
And write your routes.rb like this:
resources :users
Because you don't need all that set_wistia_project_id business.
It appears that you are not calling the function by the name you defined, neither passing the parameter (project_id) needed.
def set_wistia_project_ID
#user = User.find(params[:id])
#user.set_project_id!(params[:wistia_project_id])
unless #user.valid?
#errors = #user.errors.full_messages
render :show
end
end
This should use the function you created and pass the parameter from the form.
I have a Rails app that searches through a DB and returns items. At the moment in my view it automatically returns the default search results ("") without me needing to hit my submit_tag. How do I go about only making this action happen once I have hit the submit_tag? Any help would be greatly appreciated!
Here is my view:
<%= form_tag(new_design_path, method: :get) do %>
<%= label_tag(:q, "Search all designs:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %><br>
<!-- Button to return one random design -->
<%= form_tag(new_design_path, method: :get) do %>
<%= label_tag(:q, "Inspire me! Click here for a random design:") %>
<%= submit_tag("Random Design") %>
<% end %>
<h2>Search results:</h2>
<% #random.each do |design| %>
<h3><%= design['name'] %></h3>
<h5><%= image_tag design['thumbnail_url'] %></h5>
<% end %>
<% #search.each do |design| %>
<div class="design">
<h3 class="design_name"><%= design['name'] %></h3>
<h5><%= image_tag design['thumbnail_url'] %></h5>
<%= button_to 'Save to Favourites',
designs_path(
design: design.slice('name', 'thumbnail_url')
),method: :post %>
</div>
<% end %>
And my controller:
class DesignsController < ApplicationController
def index
#designs = Design.all.order("created_at DESC")
end
def new
# returns an array of hashes
#search = SpoonflowerApi.new.find(params[:q])['results']
#random = SpoonflowerApi.new.random(rand(1..740579), 1)['results']
end
def create
#design = Design.new(design_params)
#design.save
if #design.save
flash[:notice] = 'Design has been added to favourites!'
else
flash[:notice] = 'Design already in Favourites!'
end
redirect_to new_design_path
end
def destroy
#design = Design.find(params[:id])
#design.destroy
flash[:notice] = 'Design removed from favourites!'
redirect_to designs_path
end
private
def design_params
params.require(:design).permit(:name, :thumbnail_url)
end
end
new is used to populate the initial form, so if you don't want anything for those fields you should just set both #search and #random to an empty array in new. You don't show any code for your model, so it's not really clear what Api is.
show should be called once you submit the form
def new
#search = []
#random = []
end
then move the logic to provide the search results or random record into the show method
def show
# not sure what you want to do here
# since it seems like you have 2 buttons you need logic to provide data
# based on the button
# maybe something like this
if params[:q].nil?
#search = []
#random = Api.new.random(rand(1..740579), 1)['results']
else
#search = Api.new.find(params[:q])['results']
#random = []
end
end
If I understood you correctly, your view showing some search results before you click the search button.
Since you directly send the params[:q] to SpoonflowerApi, I am guessing that it returns some default value and your view draw it.
Simply update your controller to:
def new
#search=[]
#search = SpoonflowerApi.new.find(params[:q])['results'] unless params[:q].nil?
#random = SpoonflowerApi.new.random(rand(1..740579), 1)['results']
end
I have a book review/discussion site and would like to order all the users books on their profile page based on wether they are currently reading that book. I added a column to the book model called current and when users add a book they can check a box that says "I'm currently reading this." If the user clicks the box then the book object has a :current attribute with a value of "1". If they don't click the box then the value of :current is "0".
In my view I have this code to tell the user which books they are currently reading, and it works fine.
<% if book.current == "1" %>
<h4>I am currently reading this book</h4>
<% end %>
However in my show user controller I can't make it order the incomiing objects by the :current status.
Here's what I've tried:
def show
#user = User.find_by_id(params[:id])
#books= Book.all.sort { |p1, p2| p1.current <=> p2.current }
end
and
def show
#user = User.find_by_id(params[:id])
#books = Book.all
#books = #books.order(:current)
end
and
def show
#user = User.find_by_id(params[:id])
#books = Book.all
#books = #books.order(current: :desc)
end
and, just to make sure it was going the right way
def show
#user = User.find_by_id(params[:id])
#books = Book.all
#books = #books.order(current: :asc)
end
None work. And, none throw errors, they just don't sort it. The "current" book that is last instead of first. Here's the code that displays and loops out the users books. This code also works fine.
<% #user.books.each do |book| %>
<% if params[:id].to_s == book.user_id.to_s %>
<ul class="profileDisplay" >
<img alt="Book Jacket" class="homepageImages" src=<%= book.image %> >
<% if book.current == "1" %>
<h4>I am currently reading this book</h4>
<% end %>
<p><b>Contributor: </b><%= book.user.name %></p>
<p><b>Title: </b><%= book.title %></p>
<p><b>Author: </b><%= book.author %></p>
<p><b>Genre: </b><%= book.genre %></p>
<p><b>Publication Date: </b><%= book.publication_date %></p>
<p><b>Publisher: </b><%= book.publisher %></p>
<p><b>Synopsis: </b><%= book.synopsis %></p>
<% if params[:id] == session[:user_id].to_s || params[:action] == "profile" %>
<%= button_to "Edit Book", book_edit_path(book.id), method: "get", class: "btn btn-primary col-xs-2" %>
<%= button_to "Delete Book", delete_book_path(book.id), method: :delete, data: {confirm: "Are you sure you want to delete this book and all it's reviews?"}, class: "btn btn-danger col-xs-2" %>
<% end %>
</ul>
<% end %>
<% end %>
On view, #user.books are not sorted yet.
You sorted them and assigned it into #books
I think it should be like this
CONTROLLER
def show
#user = User.find_by_id(params[:id])
#books = #user.books.order(current: :desc)
end
VIEW
<% #books.each do |book| %>
<!-- show book records here -->
<% end %>
add default scope in book model
default_scope { order(:current=> :desc) }
and your controller
#user = User.find_by_id(params[:id])
and views
<% #user.books.each do |book| %>
#do whatever
<% end %>
I want to delete something posted by a user. But it's not working the way it normally does despite the fact that I'm mirroring a setup I've used in other apps.
My html:
<div class="section-wrap">
<% #colors.each do |color| %>
<div class="swatch">
<div class="colorblock" style="background-color: <%= color.backgroundcolor %>">
</div>
<h2>PANTONE<sup>2</sup></h2>
<p><%= color.name %></p>
</div>
<div class="controls">
<% if current_user %>
<%= link_to 'Delete', #color, method: :delete %>
<% end %>
</div>
<% end %>
</div>
My controller action:
def destroy
#color.destroy
redirect_to root_path
end
My routes.rb (in which I should not have to specify the delete route):
resources :colors
delete 'colors', to: 'colors#destroy'
And then rake routes gives the route I'd expect:
DELETE /colors/:id(.:format) colors#destroy
But I get undefined method 'destroy' for nil:NilClass
It doesn't look like you've loaded #color, and instance variables are automatically initialized to nil (in contrast with local variables, which raise an exception if you use them without assigning them). Hence, Ruby complains that destroy is undefined on nil. Load #color first:
#color = Color.find(params[:id])
If you're using Color.find_by_id somewhere else in your controller (eg. a before_action), perhaps the ID just doesn't correspond to an existing Color. Unlike find, find_by_id will return nil when the record is missing.
2 issues:
#View
<% #colors.each do |color| %>
<%= link_to 'Delete', color, method: :delete %> #-> #color doesn't exist
<% end %>
#Controller
def destroy
#color = Color.find params[:id]
#color.destroy
redirect_to root_path
end
The above should work for you.
I pass the following to the results/index.html.erb view:
def create
#results = Quiz.where(user_id: current_user.id)
redirect_to results_path
end
(I've changed the above action BACK to create).
Then, in my results/index.html.erb view:
<div class="container">
<!-- Example row of columns -->
<div class="row">
<h1>Results page</h1>
<div class="col-md-12">
<p>Eventually a user's results will appear here...</p>
<p><%= #results %></p>
<p><%= #results.inspect %></p>
<p><%= current_user.quiz %></p>
<h4>Quiz Answer</h4>
<p><%= #results.answer1 %></p>
<p><%= #results.answer2 %></p>
<p><%= #results.answer3 %></p>
<p><%= #results.answer4 %></p>
<p><%= #results.answer5 %></p>
<p><%= #results.answer6 %></p>
<p><%= #results.answer7 %></p>
<p><%= #results.answer8 %></p>
</div>
</div>
<footer>
<p><a class="btn btn-default" href="showmetheskills.html" role="button">next</a></p>
</footer>
</div> <!-- /container -->
(I know it's not 'best practise' to have numbered attributes on a Model; ignore that part.)
I get the error:
undefined method 'answer1' for nil:NilClass
Why is #results nil, when I set it IN THE ACTION Rails is asking for?
The Quiz is created in the QuizzesController:
def new
#user = current_user
#quiz = Quiz.create(user_id: current_user.id)
end
Which triggers quizzes/new.html.erb which renders the quiz partial.
What's the problem?
#results is nil because you've done a redirect. Either render the view
def update
#results = Quiz.where(user_id: current_user.id)
render: 'results#index'
end
Or do the redirect and get the results there which would be my preferred option, but I'd question why you're sending them to the update action without updating anything.
def update
redirect_to results_path
end
def ResultsController
def index
#results = Quiz.where(user_id: current_user.id)
end
end
Either way things like #results.answer1 won't work because you have an active record relation. You either need to loop
<% #results.each do |result| %>
<%= result.answer1 %>
<% end %>
Or grab the first result
#results = Quiz.where(user_id: current_user.id).first
In your case #results is an array and you call some answer1, answer2, answer3... methods(that are not defined yet I guess) on array that also does not exists.
Next:
You initialize #results in update action, but expect it to work in resuzlts/index.html.erb.
To show #results in index html you need to load this variable in index action.
Update
If you want your index action to show something, put this line:
#results = Quiz.where(user_id: current_user.id)
into index action
def index
# here
end
and remove answer1, answer2, answer3.... from index.html.erb, they really makes no sense.
Also, index.html.erb should look like this:
<div class="col-md-12">
<p><%= current_user.quiz %></p>
<h4>Quiz Answer</h4>
<% #results.each do |result| %>
<p><%= result.answer %></p>
<% end %>
</div>
this would work only if you have answer defined for result. Hard to say what is what in your app.