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.
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 am trying to pass an extra variable, that determines whether or not the user has clicked on a particular checkbox, and this variable is not a part of my model. I want to make it so on the controller update function, it can have access to this variable, and see what it was set to. I have seen some other stack overflow answers for this type of problem, and it is generally suggested to do something using hidden_field_tag, something like this:
<% hidden_field_tag "blah", params[:test] %>
or
<% hidden_field_tag :example, "test" %>
When trying this, I did a params.inspect and could not find the "test" param variable, using both of the above options. Should I be trying to retrieve this hidden field tag in a different way? Will it be available in the update request to the controller? If not, does anyone know some way this is possible?
Open to any suggestions,
--Anthony
You would either do it like this
<%= hidden_field_tag 'test' , 'blah' %>
or you could do this
<%= hidden_field_tag :whatever_you_want , 'blah', {:name=>'test'}
You had the name and value reversed in your post. The really important thing is to make sure the form element has the name you want to show up in the params hash. The second example would generate the element with id='whatever_you_want' name='test'.
This is long so I hope you'll bear with me...
I have a model called Update with two subclasses, MrUpdate and TriggeredUpdate. Using single-table inheritance, added type field as a string to Update.
In my view I'm checking which type it is to decide what to display. I assumed since type is a string, I should do
<% if #update.type == 'MrUpdate' %>
This failed, i.e., it evaluated to false when the update was an MrUpdate. I noticed that at this point, #update.type.type is Class. OK, whatever, thought I, so I changed it to:
<% if #update.type == MrUpdate %>
and it worked, i.e., the comparison evaluated to true when the update was an MrUdpate. Then I did it again lower down in my view and it failed again (i.e., it evaluated to false when the update was an MrUpdate.)
Turns out the culprit is a couple of <%= link_to ... %> calls I use and make into buttons with jQuery. If I put this code in my view:
<br>
<%= #update.type.type %><br>
<%= #update.type %><br>
<%= link_to 'New Note', new_note_path(:update_id => #update.id), :class => "ui-button" %>
<br>
<%= #update.type.type %><br>
<%= #update.type %><br>
What I see is:
Class
MrUpdate
(the New Note button)
String
MrUpdate
It's changing from a class to a string! So what the heck am I doing wrong or missing here? Why should a link_to do that? First I'm not clear why it's not a string in the first place, but then really confused as to why it would change...?!? Any help or explanation would be helpful. I can just code it one way at the top and another way at the bottom, but that way madness lies. I need to understand why this is happening.
I figured out what the issue is here. Thanks to fl00r for pointing the way.
Yes, type is a reserved in Ruby 1.8.7 which tells you the class of the object you call it from. But it's also true that it is the name of the field used in Rails to indicate single-table inheriance and to store the name of the class of each instance of the subclass.
So I naively tried to access the value of the type field using #update.type. But what this was doing at the top of the view was calling the type method of the Object class in Ruby. For whatever reason, after the link_to calls, it was then access the value of the type field of the updates table.
While trying to figure this out I called #update.type in the Rails console and saw this message: "warning: Object#type is deprecated; use Object#class". Finally it registered what I was doing. When I changed my calls to:
<% if #update.class == MrUpdate %>
everything works as expected. I never saw a call to determine the type in any of the pages I found via Google about STI. This despite the fact that they all recommended using only one controller, wherein sometimes you must need to determine the class of the instance you have.
So, dumb mistake--pilot error. But maybe this will help someone else who gets tripped up on this.
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]
In Ruby on Rails 3 How would I create a view that decides by a parameter what link in view links to?
For example to a page in my view I pass a type parameter which displays all projects in my data base and depending on the type links to either the new show or edit action.
I am interested in only passing on the path of the link.
I would like to write something like:
<% link_to(enter_here_path) do %>
<div class="blah"><%=#project%></div>
<%end%>
You could use a conditional which returns the proper location or even creates the link, probably best wrapped in a helper method.
Something like that:
def your_link_method(type="delete")
case type
when "delete"
link_to …
when "foobar"
link_to …
else
link_to …
end
end
end
As a sidenote: This kind of construct smells IMO and I'd probably rethink my design first, before I implement a solution like this. Even if you can probably find a simpler and more elegant way to write it.