I'm trying to make
<%= link_to #company.name, current_company %>
work. It does work, as long as I stay within the same profile page. As soon as I'm trying to leave it, I get the NoMethodError in StaticPages#about - undefined method `name' for nil:NilClass. I understand the problem lies within the controller (I guess?), but that's it. Can anybody point me in the right direction please.
UPDATED
Updating methods in my satic_pages controller to
def home
#company = Company.new
end
def about
#company = Company.new
end
helps with skipping the error, but instead of the company name the links start to look like
/companies/2
Update: Since you want your link to simply display the company name, you can just do something like <%= link_to #company.name, #company%>
In your controller, you want to reference which company you're linking to, so you can do something like #company = Company.last. This would take the last record that you created. Now, when you load your page, the link should take you to the show page for that company with the last company's name as the text for the hyperlink.
Related
My main difficulty comes from understanding the relationship that the _follow and _unfollow partials have with the create and destroy methods defined in the RelationshipsController from Chapter 11.2.3. I'll just focus on the act of unfollowing a user for now (since the act of following is mostly analogous).
Hartl defines the partial for unfollow as such:
<%= form_for(current_user.relationships.find_by_followed_id(#user), html: { method: :delete }) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
and the corresponding destroy action as such:
def destroy
#user = Relationship.find(params[:id]).followed
current_user.unfollow!(#user)
redirect_to #user
end
What I am having trouble understanding is:
The #user variable in the first line of the unfollow partial .. is this a) defined in the show action that currently displays the page, or b) defined in the destroy action? It appears that the form_for helper already finds the #user to be destroyed, so why does the destroy action needs to find the #user all over again to be destroyed in the controller?
In the destroy method, the #user is found by first finding the Relationship id. I don't see how the Relationship id is passed into the URI in the first place (since seeing a particular user to unfollow shows up as /users/2), much less how it is used to find the #user to destroy. I understand that each Relationship table has an id, a followed_id, and a follower_id, but do not see how the id element itself comes into play here.
Thanks, for reading, and for answering my questions!!
1.) If the partial is rendered within the show action, the variable #user must be defined in that action. Rails won't execute the destroy method so the variable definition in there will never be executed.
Since HTTP is a stateless protocol, the server needs to create the necessary state on every request. That's why #user must be defined in every action.
2.) Where did you check that the url is "/users/2"? As I don't see the whole code I can only make guesses but the following line current_user.relationships.find_by_followed_id(#user) should return a Relationship object. It will be translated into something like "/relationships/8", where 8 is the ID of the Relationship. Because you specify `method: :delete, the destroy action will be invoked.
I think the url "/users/2" is after the destroy action performed the deletion was performed. There could be a redirect in the destroy action. (eg. redirect_to current_user). You can see all the invoked actions in the log file. Try scrolling through the log and see if you can find RelationshipsController#destroy. You will see the invoked url there. Also you could inspect the HTML to see where the <form> tag's "action" attribute points to.
I was given this ruby code to overview. I am still new to ruby on rails. I come from a java background.
in User.rb:
def last_name=name
require 'debugger'; debugger
self[:last_name] = name
end
And told me that this is a setter method. They told me that this get executed in the "form" in this line:
<%= f.label :last_name%>
<%= f.text_field :last_name %>
Ok. Could somebody clarify how this ridiculous syntax can be valid?
1) An instance of the class "User" is never initialized. How is the method even called?
2) Where does the variable "name" comes from? what is the value of it? (the variable name is called nowhere else) And what does this syntax stand for? "def last_name=name" ?? Pass to the method a variable that has not been initialized? It is a short-cut for another syntax just to save typing 2 more symbols?
3) How can this method be called, in the form? I dont see a "User.last_name("David") or anything similar.
Could somebody clarify those piece of code please?
And please dont post links to tutorial or anything else. Just clarify this piece of code
The code you described:
<%= f.label :last_name%>
<%= f.text_field :last_name %>
..is used by the default rails template engine. It is view code.
1) A User instance is likely initialized and populated when the form is submitted.
The form action corresponds to an appropriate controller action, which likely accepts :last_name as a parameter. When you submit the form, the controller action probably instantiates the User instance. Without more code, however, I can't be 100% certain this is the case with your application.
2) The variable name comes from the argument accepted by the last_name method.
Perhaps, to help you understand the method, let's rewrite it:
def last_name= (name)
require 'debugger'; debugger
self[:last_name] = name
end
Either last_name=('John Doe') or last_name = 'John Doe' will execute this method.
3) I think my previous descriptions should help you make sense of this..
MVC. In the action new a new instance of User is created and assigned to #user, which is what will be used for the form.
name comes from the method declaration def last_name=name
The form helpers does last_name=name when it assigns a value to that variable and uses the setter to do that. When you edit the object it will use the getter to display its value in the text field.
You can understand better point #2 with this syntax:
def last_name=( name )
end
The = is part of the function's name.
C equivalent would be
void last_name_equals( char *name ) {}
The rest is a Rails tutorial's job.
I'm new to programming.
I generated an Ideas scaffold. The model has fields: Description (string), Upvotes (integer), Downvotes (integer).
All the normal actions in the ideas_controller.rb work - Index, Show, New, Edit, Create, Update, Destroy.
Instead of telling you the ways I've tried to do the following, I'll just ask:
How do I add a '+1' link next to the 'Show', 'Edit', 'Destroy' links that when clicked increases the Upvotes value by 1 for that idea?
Thanks in advance.
EDIT (With "Skydreamer's" help, I figured it out!)
I adjust the routes.rb to:
resources :ideas do
member do
get 'upvote'
end
end
I add the following to the ideas index.html.erb:
<td><%= link_to '+1', upvote_idea_path(idea) %></td>
Note: if you don't include the (idea), you'll get an error like this:
No route matches {:action=>"upvote", :controller=>"ideas"}
I add the following to the ideas_controller.rb:
def upvote
#idea = Idea.find (params[:id])
#idea.upvotes = #idea.upvotes + 1
#idea.save
redirect_to(ideas_url)
end
In the next lines, I'll say upvote but that works the same for downvote.
First, create a member route upvote, then you can link from your show view to the new action using upvote_idea_path.
Second, create an action upvote in the controller which increases the vote count by 1 and you're done. That's all.
You can achieve this functionality with the thumbs_up gem. It is also Rails 3 compatible.
I have a dropdownmenu which populates from the database. I'm using the following code to do it:-
<%= collection_select(:abc, :SkillSetName, #technologies, :id, :Topic) %>
I have no idea what :abc and :SkillSetName are doing here. I just know that the drop down is being populated with :Topic from my #technologies variable. I want to save the selection made by the user from the drop down menu and send it to the next controller action. I don't want to use f.collection_select
If you don't know what :abc and :SkillSetName are, how are we supposed to know?
Anyway, the user's selection will be in:
params[:abc][:SkillSetName]
If you want to understand what you are doing, have a look at the API for collection_select.
See my answer - RoR: collection_select not setting the value in the DB
:abc stand for your object and :SkillSetName stand for your method.
when you want to save its value you can get it using params[:abc][:SkillSetName]
so i want to make a page the displays a Phrase by select (initially) at random from the database. on that page i want a <%= link_to "next"%> but i was wondering if there was an efficient way to ensure that the next record exists
currently I'm using just
# #phrase is current phrase
<%= link_to "next", phrase_path( Phrase.find( #phrase.id + 1 ) ) %>
yes, i know i should call a #next from the controller, or better yet have a next method in the model to call #phrase.next, but this is for illustrative purposes.
but this often turns up an ActiveRecord::RecordNotFound error because some phrases have been deleted from the db (due to moderation, error, etc...). I could rescue from this and loop that till it works in the controller then pass it or something, but that seems like a bad solution, and not particularly 'railsy'
is there a convenient solution to this anyone has found
figured it out
based on this link which is a little outdated, uses named_scope from back in rails 2. I first rewrote it using the new rails 3 scope style, but then just changed it to a method. just used
def next
Phrase.where("id > ?", self.id).order("id ASC").first
end
def previous
Phrase.where("id < ?", self.id).order("id DESC").first
end
Try creating a next/previous scope on your model, as suggested in http://steve.dynedge.co.uk/2010/01/13/random-previous-and-next-entries-from-active-record-models-using-offset/
This will allow you to do something like:
Phrase.next(5) or Phrase.next(#phrase.id)
Why don't you create a method in the controller called next and pass in the current record id. It would be trivial from there to redirect the user back to the show page for that next resource.
If you are deadset on creating the link in advance, look into creating a helper method to find the next record that exists and make it available in your views. Then you could call that whenever you needed the id of the next available record.
Something like will_paginate might be of help too. I know your page size is just one, but the essence of what you're doing is pagination.