Here is my issue:
I am setting up internationalization on my site (so we can have multiple translations of the text on the pages). I have followed a rails cast to set up a page that can manage the translations instead of me manually having to edit every yml file.
I have set everything up and can create entries fine, I am trying to add the ability to delete an entry and I have hit a wall. I can't seem to set up the link correctly to delete the entry from redis. The first thing that made this complicated (at least to me) is that I am not deleting an object that was created through active record (like a user etc). So instead of using the active record object to construct the url for the link_to or form_for I have to construct it manually.
From what I have read so far I have to put the link in a form (and set to post since we are modifying the redis db). So I have been trying to create the correct syntax in the form for tag to direct to the action I have set up in the controller.
Controller:
class InternationalizationTranslationsController < ApplicationController
def index
#translations = I18n.backend.store
end
def create
I18n.backend.store_translations(params[:locale], {params[:key] => params[:value]}, :escape =>false)
redirect_to internationalization_translations_url, :notice => "Added translation"
end
def destroy
puts "Key is: #{params[:key]}"
I18n.backend.delete(params[:key])
redirect_to internationalization_translations_url, :notice => "Removed translation"
end
end
View:
<%= form_tag internationalization_translations_path do %>
<p>
<%= label_tag :locale %>
<%= text_field_tag :locale %>
</p>
<p>
<%= label_tag :key %>
<%= text_field_tag :key %>
</p>
<p>
<%= label_tag :value %>
<%= text_field_tag :value %>
</p>
<p><%= submit_tag "Submit" %></p>
<% end %>
</div>
<div class="grid_7 top_padding">
<table class="trans_table">
<% #translations.keys.each_with_index do |key, i| %>
<tr class="<%= i%2 == 0 ? "even" : "odd" %>">
<td><%= key %></td>
<td><%= #translations[key] %></td>
Then I played with form_for and form_tag looking at the documentation (form helpers and form tag docs) eventually ending with these, that still do not work:
<%= form_tag(controller: "internationalization_translations", action: "destroy", method: "post", key: key) %>
<%= submit "Delete" %>
<% end %>
and now
<%= form_tag(internationalization_translations_path, action: "destroy", method: "post", key: key) do %>
<%= submit_tag "Delete" %>
<% end %>
I also played with the link_to for a while before coming across this post which linked to why the delete link/button should be in a form because it is editing the DB so it needed to be post instead of get. I am a little frustrated because this seems like a pretty straight forward task but I am running into some difficulties finding a clear answer regarding my particular issue, specifically the routing for this link for a redis entry and not an activerecord object.
**also since the form for the button is being created in a loop for each entry I should probably have the form named with an index so it is specific for each button?
Any insight or links would be greatly appreciated.
Thanks,
Alan
Ok so I ended up figuring it out resetting some things up and taking marvwhere's advice. I wanted to set it up as a link without a form, how it generated for other controllers that were manipulating active record objects. But since this was a different case making a custom action other than the default destroy action worked.
<%= form_tag(destroy_key_internationalization_translations_path, method: :post) do %>
<%= hidden_field_tag 'key', key %>
<%= submit_tag "Delete" %>
<% end %>
where I created the destroy_key action within the internationalization_translation controller.
Also the deleting of the key from redis needed to be changed. I had to use the actual Redis instance created. So instead of
I18n.backend.delete(params[:key])
in my initializer I had to set a global variable when creating the Redis instance:
TRANSLATION_STORE = Redis.new(:db => 10)
and then call the delete on that object
TRANSLATION_STORE.del(params[:key])
Related
I am building a simple Rails app that has Users, Blogs, and Comments. The last thing I have to do is make a link on the blogs show page where comments show and have those links send the user to the comment/:id/edit page where they can edit their comment.
However, I'm not able to grab the comment ID correctly for some reason and even though I am getting thrown no errors I am not brought to the error form, just a blank web page that has my layout elements.
Here is my blogs controller's show action:
def show
#blog = Blog.find_by_id(params[:id])
#comment = Comment.new
# #current_comment = Comment.find(params[:id])
end
Here is my comments controller's edit action:
def edit
#comment = Comment.find_by_id(params[:id])
end
And here is where the link is in the Blogs show view:
<% #blog.comments.each do |c| %>
<div><%= c.content %></div>
<%= link_to 'Delete', "/comments/#{c.id}", method: :delete %>
<% end %>
The delete function works, but when I try to grab the comment id in the same way for the link to the comment view it does not work. Instead of seeing a number in the url like 1, 2, or whatever the comment id is, I see the #{c.id} syntax. Any thoughts?
<% #blog.comments.each do |c| %>
<div>
<%= link_to c.content, edit_comment_path(c) %>
</div>
<%= link_to 'Delete', c, method: :delete %>
<% end %>
In general you want to avoid hardcoding paths when possible as it makes your code more brittle and verbose.
As you have written it "/comments/#{c.id}/edit" is not even being evaluated since its not inside a ERB tag.
I suppose you mean this part:
<div><%= c.content %></div>
That's because the <div><a href="/comments/#{c.id}/edit"> part is outside a ERB block, therefore it is being interpreted as plain HTML, and that's what you see in the url. There's no variable expansion in plain HTML inside a ERB file.
Either use link_to:
<div><%= link_to c.content, "/comments/#{c.id}/edit" %></div>
or enclose the url part in ERB tags:
<div><%= c.content %></div>
I am building a basic bare bones social media app right now.
I have a user class and a status class.
For each status, there is a "creater" (a user object) and a "subject" (a user object that the status is about). I was able to create tags by using the acts_as_taggable_on gem. What ends up happening is when a user goes to create a post, he/she can select another user from a dropdown menu. The chosen user's id attribute is then stored.
Now I am trying to link to the chosen User's profile. This is my code for show statuses on a profile page.
<% if #statuses %>
<% #statuses.each do |status| %>
<div class="well">
<%= status.content %>
<br></br>
#link to user who's associated with the tagId
<%= link_to User.find(status.tag_list).profile_name, user_profile_path(User.find(status.tag_list).profile_name) %>
<hr />
<%= link_to time_ago_in_words(status.created_at), status_path(status) %> ago
</div>
<% end %>
<% end%>
this is the line where the above code breaks
<%= link_to User.find(status.tag_list).profile_name, user_profile_path(User.find(status.tag_list).profile_name) %>
Can anyone help me out with this?
Not surprised this line is failing:
<%= link_to User.find(status.tag_list).profile_name, user_profile_path(User.find(status.tag_list).profile_name) %>
A couple points:
It's a little cleaner to separate it onto multiple lines
I suspect your problem is because you're passing a profile_name to user_profile_path instead of an id, though I can't be certain without seeing your routes.
Try the following:
<% profile_user = User.find(status.tag_list) %>
<%= link_to profile_user.profile_name, user_profile_path(profile_user.id) %>
i am new to rails and doing a project with the help of Michael Hartl' tutorial of rails 4 http://ruby.railstutorial.org/chapters/following-users#sec-following_and_followers_pages
while creating a form for following users it's showing
First argument in form cannot contain nil or be empty in rails 4
<%= form_for(current_user.relationships.find_by(followed_id: #user.id)) do |f| %>
<div>
<%= f.hidden_field :followed_id %>
</div>
<%= f.submit "Follow", class:"btn btn-large" %>
<% end %>
relationships_controller.rb
def create
#user = User.find(params[:relationship][:followed_id])
current_user.follow!(#user)
redirect_to #user
end
Can you please give me solution to avoid this error? while i am inserting data in relationships table via rails console. it's ok. but it cant create any new object from form and showing this error.
Solution . if i change the first argument like follwing then its working but does not getting the unfollow button
<%= form_for(Relationship.new(followed_id: #user.id)) do |f| %>
You get this error because, the current_user is not following #user and there is no relationship between them, thus current_user.relationships.find_by(followed_id: #user.id) returns nil as a parameter to the form.
Refer Michael Hartl's tutorial properly, you will see
_follow_form.html.erb
<% unless current_user?(#user) %>
<div id="follow_form">
<% if current_user.following?(#user) %>
<%= render 'unfollow' %>
<% else %>
<%= render 'follow' %>
<% end %>
</div>
<% end %>
There are two partials to show the follow form button,
1) When the user is following another user/page there is _unfollow.html.erb partial
_unfollow.html.erb
<%= form_for(current_user.relationships.find_by(followed_id: #user),
html: { method: :delete }) do |f| %>
<%= f.submit "Unfollow", class: "btn btn-large" %>
<% end %>
2) When the user is not following another user there is _follow.html.erb partial
_follow.html.erb
<%= form_for(current_user.relationships.build(followed_id: #user.id)) do |f| %>
<div><%= f.hidden_field :followed_id %></div>
<%= f.submit "Follow", class: "btn btn-large btn-primary" %>
<% end %>
In Hartl's tutorial its not working, but found a solution, its simple, While i am checking if the cuurent_user is following user or not? if not then partial will throw me to follow page.where if create the form with
<%= form_for(Relationship.new(followed_id: #user.id))%>
i can create following users
The error message is
First argument in form cannot contain nil or be empty in rails 4.
This means that in
form_for(current_user.relationships.find_by(followed_id: #user.id))
current_user.relationships.find_by(followed_id: #user.id) returned nil. In other words, of the current user's relationships, none of them had followed_id == #user.id.
To fix this, try to figure out why you are searching for the given #user.id, and why you expect the relationship to exist.
Update
Since you are trying to create a new relationship, you can use
<%= form_for(current_user.relationships.build(followed_id: #user.id)) do |f| %>
instead. find_* tries to find an existing record in the DB, whereas build makes a record in memory with the given attributes (i.e. not saved to DB yet.)
I have a code where a user can select a specific file to be deleted or analyzed.
<% if #files%>
<%= form_tag what_to_do_files_path, method: :get do %>
<%= submit_tag "Delete selected", :name => 'delete' %>
<%= submit_tag "Analyse", :name => 'analyse' %>
<% #files.each do |file| %>
<% if (file.analyzed=="no") %>
<p><td> <%= check_box_tag "files[]", file.id %></td><%= file.name %></p>
<% else %>
<div class="my_profile_info">
<p><td> <%= check_box_tag "files[]", file.id %></td> <%= file.name %></p>
<td class="Info">
Info
</td>
</div>
<% end %>
<%end%>
<%end%>
<%else%>
<%end%>
I need to be able to give a name to every analysis.
For example: user selects 3 files, enters a name in the text field "Analysis of annual profit" and clicks on the button "Analyse".
The name "Analysis of the annual profit" and the names of the files that were selected have to be saved into the table group_analysis.
I have tried something like this after submit_tag "Analyse":
<%= form_for #groupanalysis do |f| %>
<div class="field_label">
<%= f.label :group_name, "Type group name hier" %>
</div>
<br class="clear" />
<br />
<% end %>
but it tells me undefined method model name
Thanks in advance.
I think you may need to take a step back and think of how this form represents the model that you're trying to create or update. Generally speaking the first argument to form_for and form_tag is an object and symbol, respectively, which represent the model that you're working with. The form fields map to each attribute of the object.
According to conventions and/or the :url argument, this will get routed to the appropriate controller and call an action according to the HTTP verb (again, part of many conventions in rails).
Going back to your code examples, you are using the form_tag helper incorrectly and the example using form_for may not be the right implementation. For example you're just displaying a label, with no input nor submit.
I hate to just post a link here and just tell you to read the docs, but in this case I think this is the best first step.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for
I've set up a Rails form roughly following the instructions in this Railscast.
Here's the code for the form:
<% form_tag complete_todos_path, :method => :put do %>
<ul>
<div id="incomplete_todos">
<% #incomplete_todos.each do |todo| %>
<%= render :partial => todo %>
<% end %>
</div>
</ul>
<%= submit_tag "Mark as completed" %>
<% end %>
And here's the code for the todo partial:
<div class="todo">
<li>
<%= check_box_tag "todo_ids[]", todo.id %>
<%=h todo.name %>
<%= link_to 'edit', edit_todo_path(todo) %>
<%= link_to 'delete', todo, :confirm => 'Are you sure?', :method => :delete %>
</li>
</div>
It's working great, but I'm looking to start implementing AJAX and I need each checkbox to have a unique id. Right now, the input tags generated look something like this:
<input id="todo_ids_" name="todo_ids[]" type="checkbox" value="7" />
Every check box has the same id ("todo_ids_"), which is a problem. I suspect the solution is embarrassingly simple, but I'm not seeing it. Any tips?
<%= check_box_tag "todo_ids[]", todo.id, false, :id => "todo_id_#{todo.id}" -%> or whatever you want the id to be.
I consider this a bug with check_box_tag caused by the seemingly hackish nature of manually giving it the name todo_ids[] and the method code calling sanitize_to_id(name). I just ran into this yesterday and I'm contemplating a patch.
I ended up using a solution similar to Ryan's, but as I wrote in the comment I had to make a further change. In the form:
<%= check_box_tag "todo_ids[#{todo.id}]", todo.id %>
In the action called by the form:
Todo.update_all(["completed_at = ?", Time.now], :id => params[:todo_ids].keys)
Note the "params[:todo_ids].keys" at the end, which was a workaround to deal with the odd way the parameters were formatted:
"todo_ids" => {"5"=>"5"}
Can you try this and let us know if it works:
check_box_tag "todo_ids[#{todo.id}]", todo.id %>
This is the expected behaviour of check_box_tag, as this comment on a rejected fix explains.
You can use collection_check_boxes like this (haml syntax, sorry):
# Accumulate todos in a params hash like { todos: { to_complete: [] } }
= collection_check_boxes(:todos, :to_complete, #incomplete_todos, :id, :name) do |todo_builder|
= todo_builder.label do
# This is the result of calling :name on the todo, as specified
# calling the helper
= todo_builder.text
= todo_builder.check_box
Of course you can use partials inside the block, just pass and use the builder inside.
Check more options in the API docs.