I am building an Rails 4.1 webapp and I am using a an ajax form (remote true)
and a create.js.erb file with this content:
$("div.box-content").prepend('<%=j render #comment %>');
$(".empty-message").hide();
$(".textfield").val("");
How can I check if #comment is empty?
Right now it´s adding an empty row when there is no content (I don't want to add a row if comment is not set).
Update
def create
#comment = #object.comments.create(comments_params)
end
You can either check server-side (conditionally output different JavaScript) or you can check in client-side in JavaScript.
Checking server-side involves testing whether #comment is set, and simply not output any of the prepending JavaScript:
<% if #comment.present? %>
$("div.box-content").prepend('<%=j render #comment %>');
<% end %>
$(".empty-message").hide();
$(".textfield").val("");
Checking client-side involves outputting the empty value in a variable so you can inspect it in JavaScript vefore prepending it to your element:
var comment = '<%= j render #comment %>';
if (comment) {
$("div.box-content").prepend(comment);
}
$(".empty-message").hide();
$(".textfield").val("");
I would use the first approach.
Related
Is there a silent tag for groovy simpleTemplateEngine, if not perhaps another template engine?
What I am looking for is a tag which does not print a new line for if statements like <%- -%> for ERB in Ruby.
Take a look at the code below:
import groovy.text.*
def binding = ['Foo':'Bar']
def template = """
<% if(true){ %>
<%= Foo %>
<% } %>
"""
def rendered = new SimpleTemplateEngine(true).
createTemplate(template).
make(binding).
toString()
print rendered
Because it's running in debug mode it prints the source code for the parsed template, we can see that it's printing a new line before and after the desired output:
-- script source --
out.print("""
"""); if(true){ ;
out.print("""
${ Foo }
"""); } ;
out.print("""
""");
/* Generated by SimpleTemplateEngine */
-- script end --
I obviously already tried <%- -%> but I've got a syntax error :(
In posts controller an object contains all active posts:
#posts = Post.where(status: 'active').order(:name)
In the view this object is iterated and I have to perform some operations based of the existence of next post.
<% #posts.each do |post|
if post.next_post_exists?
# do something.
else
# delete author.
end
end
%>
So, what is the best way to check if the next post exists?
def next_post_exists?
#TODO
end
You can simply take a variable for the current post and then check for the presence of the next post.
For example:
<%i=0
#posts.each do |post|
if #posts[i+1].present?
#do something
else
#delete author
end
i+=1
end%>
Try this and let me know if it works.
class Post
def next
self.class.find_by("id > ?", id)
end
end
And at this point you can do:
<% #posts.each do |post|
if post.next.present?
# do something.
else
# delete author.
end
end
%>
To learn rails, I started to write my own (stripped down) version of reddit. Currently, I have my comments routes nested inside my post routes as such:
resources :posts do
resources :comments
end
For my comments controller, under index & create I have the following
def index
#post = Post.find(params[:post_id])
#comments = #post.comments
if params[:comment].nil?
#comment = Comment.new
#comment.post_id = #post.id
else
#comment = Comment.find([:comment])
end
end
def create
#comment = Comment.new(comment_params)
#comment.user_id = current_user.id
#comment.post_id = params[:post_id]
if #comment.save
#flash
redirect_to post_path(#comment.post)
else
#flash
render 'index'
end
end
Which works well, except the last part: render
I want my comments to display on the same page as the other comments (just like reddit), so I would prefer not use the www.example.com/post/4/comment/new path, and instead do it through the www.example.com/post/4/comments path.
I understand that I can do a redirect, however I want to keep the comment text, so the user can make corrections. Is there a way to properly do this with a render, as opposed to me putting the text in a session variable and doing a redirect? I understand this is an edge case, but am trying to use this as a learning opportunity.
You can pass the comment to the index partial - no?
<%= render "index", locals: {comment: #comment} %>
Or try a partial;
<%= render partial: "index", locals: {comment: #comment} %>
How do I expire the main-page fragment in a model?
In my HTML
<% cache 'main-page' do %>
# html here
<% end %>
In my Post Model
after_create :clear_cache
after_update :clear_cache
def clear_cache
ActionController::Base.new.expire_fragment('main-page')
end
This doesn't clear the cache. If I create or update a post, the cache doesn't clear. If I run ActionController::Base.new.expire_fragment('main-page') in rails console it returns 'nil'. If I run Rails.cache.clear instead of ActionController::Base.new.expire_fragment('main-page') in the post model, it works.
I believe your issue is the digest, so if you change your cache to this it should work:
<% cache 'main-page', skip_digest: true do %>
# html here
<% end %>
If you want to use this kind of style, where the cache doesn't expire and relies on detecting model changes to invalidate, you may want to consider using an Observer or Sweeper, which were removed from Rails 4, but are useful for this pattern:
https://github.com/rails/rails-observers
Not the answer you are looking for perhaps, but another way:
Make the cache key based on the max updated_at from the Post model.
Whenever any post changes, the cache key will automatically miss and go retrieve the latest posts to re-cache that part of the view.
module HomeHelper
def cache_key_for_posts
count = Post.count
max_updated_at = Post.maximum(:updated_at).try(:utc).try(:to_s, :number)
"posts/all-#{count}-#{max_updated_at}"
end
end
And then in your view:
<% cache cache_key_for_posts, skip_digest: true do %>
# html here
<% end %>
In my application/index, the user selects a location and directory path from a drop down list. onchange event makes a call to the controller called file_dir where it takes the path, executes a command line call passing back a list of files in that directory to a parameter #files. I then render a partial passing this #files to a local variable. Then in the partial the select tag will display with the list of file passed to it.
I am new to ROR and have not been able to successfully pass a readable local variable. to the partial. Everything works fine with a hardcoded line but not with the local variable.
Can someone please help advise me on the correct way to set this up?
Here is the method called from the first onchange dropdown pass that receives the directory:
def file_dir
unless params[:dir_list].nil?
#dir_path_choice = params[:dir_list]
else
#dir_path_choice = '/watchfolder/indemandvod'
end
# #files = "#{#dir}"
#files = Dir.glob("#{#dir_path_choice}/**/*.{mpg,mov}").map
if #files.nil?
#files = Dir.glob("/watchfolder/hbovod/**/*.{mpg,mov}").map
end
render :partial => 'list_files', :locals => { #list => #files }
end
In irb I tested the #files = Dir.glob("#{#dir_path_choice}/**/*.{mpg,mov}").map line to make sure this was processing correctly. Here is what #files looks like:
1.9.3-p547 :008 > #files
=> #<Enumerator: ["/watchfolder/indemandvod/MJR-TEST.mov", "/watchfolder/indemandvod/MJR-TEST-AWS1.mov", "/watchfolder/indemandvod/MJR-TEST-AWS.mov", "/watchfolder/indemandvod/MJR-TEST2.mov", "/watchfolder/indemandvod/PIX_Gor_SVO40185/PIX_Gor_SVO40185_mezz.mov"]:map>
This data breaks out in the select list, separated by the commas.
NOTE: I did try to pass the #list without the # symbol but I got unidentified local variable or method and couldn't get the code to run with out adding the #. This is like a collection of data so I expect it is interpreting it as an array. Not sure though.
Here is the partial file code:
<p>
<label>Select Partial Test File List:</label><%= #list %><br />
<% unless #list.nil? %>
<%= #list %>
<% else %>
<label> list is empty. </label>
<% #list = Dir.glob("/watchfolder/showtimevod/**/*.{mpg,mov}").map %>
<% end %>
<%= select_tag 'filepath', options_for_select(#list, #selected_filepath) %>
</p>
It does display back on the page and my 'list is empty' always shows and the dropdown box populates with my default 'hardcoded' command line for '/watchfolder/showtimevod/' files list.
The #selected_filepath maintains the selected line in the list.
I don't know what I am doing wrong in passing values to partials.
In my application/index,
What is an "application/index"?
Can someone please help advise me on the correct way to set this up?
The correct way is to get something simple to work first:
app/controllers/some_controller.rb
def file_dir
puts "****#{params[:dir_list]}"
#files = %w[ a b c]
render :partial => 'list_files', :locals => { file_names => #files }
end
views/some_controller/_list_files.htm.erb:
<div>
<%= file_names.each do |fname| %>
<div><%= fname %></div>
<% end %>
</div>
And as with all your posts, in this line:
<%= select_tag(
'filepath',
options_for_select(#list, #selected_filepath) %>
#selected_filepath is undefined.
This is like a collection of data so I expect it is interpreting it as
an array. Not sure though.
You should probably strive to create data that you understand. What are you trying to accomplish with this line:
#files = Dir.glob("#{#dir_path_choice}/**/*.{mpg,mov}").map
that the following line doesn't do:
#files = Dir.glob("#{#dir_path_choice}/**/*.{mpg,mov}")
This:
I did try to pass the #list without the # symbol but I got
unidentified local variable or method and couldn't get the code to run
with out adding the #.
is not sufficient. No one cares what your interpretation of the error message is--what people care about is the EXACT error message, with file names and line numbers, copy and pasted into your post, along with the exact code the error refers to.
If you just want to get your code to work, you can do this:
app/some_controller.rb:
def file_dir
if params[:dir_list].nil?
#dir_path_choice = '/watchfolder/indemandvod'
else
#dir_path_choice = params[:dir_list]
end
#files = Dir.glob("#{#dir_path_choice}/**/*.{mpg,mov}").map
if #files.nil?
#files = Dir.glob("/watchfolder/hbovod/**/*.{mpg,mov}").map
end
render :partial => 'list_files', :locals => {file_names => #files }
end
However, adding map() to the end of your Dir.glob() does nothing useful.
app/views/some_controller/_list_files.html.erb:
<p>
<label>Select Partial Test File List:</label>
<%= select_tag 'filepath', options_for_select(file_names) %>
</p>