Will_paginate, Ruby on Rails, conditions - ruby-on-rails-4

I am using will_paginate for my Rails project. Depending on 'Post' variable its 'mediatype' attribute I use either memo or photo and show results in different parts of the page. Will_paginate paginates both sides of the website together. If I have done 10 posts: 1 memo, 9 posts of photos, and 1 memo and I want to show 5 results per page, I will see on the front page one memo instead of two, and 4 photos. I use the same variable post and I have two different attributes how to make separate paginations for them? Here is my code. In fact I would like to add 'load more' button. It might a bit too complicated, so I will be satisfied with simple version of pagination. Still if you know how to make 'load more' buttons for two parts of the website, I will much appreciate. Thank you.
INDEX VIEW
<% content_for :memo_content do %>
<%= will_paginate #posts %>
<% #posts.reverse_each do |post| %>
<% if post.mediatype == "Memo" %>
<%= post.mediatype %>:
<%= post.title %>;
<% end %>
<% end %>
<% end %>
<% content_for :media_content do %>
<% #posts.reverse_each do |post| %>
<% if post.mediatype == "Photo" %>
<%= post.mediatype %>:
<%= post.title %>;
<% end %>
<% end %>
<% end %>
POSTS_CONTROLLER
def index
#posts = Post.order(name: :asc).paginate(page: params[:page], per_page: 5)
end

you can get count manually in controller and pass this count to will_paginate
Like:
#posts = Post.order(name: :asc).paginate(page: params[:page], per_page: 5)
from #posts get manually for both memo and posts of photos and pass this count in view.
<%= will_paginate #memo_count, :renderer => BootstrapPagination::Rails %>
<%= will_paginate #posts_of_photos_count, :renderer => BootstrapPagination::Rails %>

Related

undefined method `model_name' for nested routes

I want to set up my models, such that my Posts has_many Comments and Comments has_many Replies. Comments are working fine. But my application starts breaking saying
undefined method `model_name' for "/posts/adas/comments/11/replies":String
when I try to setup the replies for comments. I cannot figure out what's triggering this error. I can add replies from my Rails console, and see them in the view, but adding the form_for tag breaks the code. Can anybody please point out what is the mistake and how I should be routing it?
Posts#show.html.erb
<h2>Comments</h2>
<% #post.comments.each do |comment| %>
<p>
<b><%= comment.username %></b>
<%= comment.name %>
<% if current_user.email == comment.username || current_user.admin? %>
<%= link_to 'Delete', [comment.post, comment],
:confirm => 'Are you sure?', :method => :delete %>
<% end %>
<p style = "text-indent: 3em">
<% comment.replies.each do |reply| %>
<i><%= reply.author %></i>
<%= reply.content %>
<% end %>
<%= form_for [#reply, post_comment_replies_path(#post, comment)] do |f| %>
<%= f.label :reply %>
<%= f.text_field :content %>
<%= f.submit("Reply") %>
<% end %>
<% end %>
</p>
</p>
<h3>Add a comment:</h3>
<%= form_for([#post, #post.comments.build]) do |f| %>
<%= f.label :comment %><br />
<%= f.text_area :name %>
<%= f.submit %>
<% end %>
replies_controller.rb
class RepliesController < ApplicationController
def create
#reply = #comment.replies.create(reply_params)
redirect_to post_path(#post)
end
private
def reply_params
params.require(:reply).permit(:content)
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
root 'welcome#index'
resources :posts do
resources :comments do
resources :replies
end
member do
put "like", to: "posts#upvote"
end
end
end
You're almost there, but you're not passing the parameters in the proper way to get the result that you want. At the moment you're passing in a url string where rails is expecting a resource object, hence the undefined method exception.
form_for(record, options = {}, &block)
The method takes a record and a hash of options that are optional.
The suspect line is
<%= form_for [#reply, post_comment_replies_path(#post, comment)] do |f| %>
The square brackets should only be used to define a resource and its associated resources which are then used to generate a url path. You should also explicitly state your url in the options hash unless it can be inferred from the resources you pass into form_for.
So it should look something like this, keeping with the way you are doing things.
<%= form_for #reply, url: post_comment_replies_path(#post, comment) do |f| %>
That's the case if you want to specify a url in form_for. However, why don't you just allow rails to generate the url for you?
<%= form_for [#post, comment, #reply] do |f| %>
This way rails should handle the routes.

How to show spree product variant images only?

Right now I've the following piece of code, which retrieves all images attached to Spree products.
<% #product.images_by_variant.each do |variant_id,images| %>
<ul class="gallery gallery-<%= variant_id %>" data-variant="<%= variant_id %>">
<% images.each do |image| %>
<li>
<%= image_tag(image.attachment.url(:single)) %>
</li>
<% end %>
</ul>
<% end %>
However, there are also images displayed that represent all variants. I want to hide those.
How can I only show variant (different colors for example) for products?
Cheers!
I found the solution. In the products_controller_decorator.rb, I added the following piece of code to the show method:
variants = #product.variants
if variants.blank?
#variants = #product
elsif variants.length > 1
#variants = variants.reject {|variant| variant.is_master? }
end
In the view I rendered the following partial:
<% if #variants == #product %>
<%= render partial: 'product_single/product_gallery', locals: {variant: #product} %>
<% else %>
<% #variants.each do |variant| %>
<%= render partial: 'product_single/product_gallery', locals: {variant: variant} %>
<% end %>
<% end %>

Rails 4 edit form do not display upload photo

I have a mongo rails 4 app, with an embedded photo.
I have no problem in the new form, but in the edit form, if the user has not upload any photo, the form will not display a "add photo button".
Here is the form:
<%= f.fields_for :founder_profile_photos do |founder_photo_f| %>
<%= render partial: 'founder_profile_photo_fields', locals: { f: founder_photo_f } %>
<%= link_to_add_association raw('<i class="fi-plus"> add a founder photo</i>'), f, :founder_profile_photos %>
<% end %>
Here is the partial:
<div class="nested-fields">
<% if f.object.file.to_s.empty? %>
<%= f.file_field :file, label: "Upload a founder photo." %>
<% else %>
<%= image_tag f.object.file, class: 'small-10 medium-10 image-previewer' %>
<% end %>
</div>
Thank you so much for your help. I finally found what was wrong, I needed to build the field photo in the edit action of my controller, other the field does not exist and therefore do not appear in the view.
def edit
if #user.photos.empty?
#user.photos.build
end
end
photo is embedded into the user model (one to many relation) if you have a one to one relation you have to do:
if #user.photo.blank?
#user.photo = Photo.new
end
Thank you very much for all your help, still so much to learn.

Conditioning based on checkbox status

When a potential User is editing their Profile, they have an option to show/hide some information from public view. I did that with
<div class="field">
<%= f.text_field :contact %>
<%= f.select(:contact_type_id, ContactType.all.map {|l| [l.name, l.id]}) %>
<%= f.check_box :visible %>
<%= f.label :visible, "Vidljivo" %>
<%= f.link_to_remove "Izbriši kontakt" %>
</div>
in a partial that's called in the view like this
<%= f.fields_for :contacts do |l| %>
<%= render 'contacts_form', f: l %>
<% end %>
What I now want is to display on a public profile page only that information that the User marked as visible, and I tried it through a different partial
<div class="field">
<% if :visible == true %>
<%= f.text_field :contact %>
<% end %>
</div>
called from
<%= f.fields_for :contacts do |l| %>
<%= render 'contacts_show', f: l %>
<% end %>
but it doesn't work. I tried tons of variations, but it all came down to guessing the right syntax. How do I display only those entries which visibility is marked as "true"?
Why are you displaying the public profile as a form? If you only want to show the information you can iterate over the contact information of the user where the contact type is visible.
I solved it by using a different approach. In my user controller I defined an instance variable #visible and passed it the array consisting of all database entries that have visible parameter set to true. Then I used #visible.each in the view to print the desired content.

Rails 4 use of non-model attributes in params resulting in undefined method `merge' for nil:NilClass

I have a search form on an index page for my Properties model which is using both Ransack and Geocoder to search the Properties model fields as well as narrow the results down based on distance from an address input by the user in the search form.
The address and distance are captured in the form with :nearaddress and :distance, respectively, which I send in params[:near]. I am checking for the presence of them in the controller index action following this answer. The result is “undefined method `merge' for nil:NilClass” when navigating to /properties, so the view will not render. How do I enable these non-model form parameters to be passed to the controller properly? I think this might be a strong parameters issue but I'm stuck on how to permit these attributes that aren't in the Properties model. The error highlights the "f.text_field :nearaddress" line.
index.html.erb:
...form fields that work when excluding the two that follow...
<div class ="field">
<%= f.label :nearaddress, "Address" %>
<%= f.text_field :nearaddress, params[:near] %>
</div>
<div class ="field">
<%= label_tag :distance %>
<%= text_field_tag :distance, params[:near] %> miles
</div>
<div class="actions"><%= f.submit "Search" %></div>
<% end %>
properties_controller.rb:
def index
if params[:near].present? && (params[:near].to_i >0)
#search = Property.near(params[:near]).search(params[:q])
else
#search = Property.search(params[:q])
end
#properties = #search.result(:distinct => true).paginate(:page => params[:page])
...
end
I was able to resolve this problem by removing the "f." and adding "_tag" to the :nearaddress field as well as specifying the params in the controller index:
<%= label_tag :nearaddress, "Near Address" %>
<%= text_field_tag :nearaddress, params[:near] %>
<%= label_tag :distance, "Distance From Address (mi)" %>
<%= text_field_tag :distance, params[:near] %>
<div class="actions"><%= f.submit "Search" %>
<% end %>
if params[:distance].present? && (params[:distance].to_i >0) && params[:nearaddress].present?
#search = Property.near(params[:nearaddress],params[:distance]).search(params[:q])
else
#search = Property.search(params[:q])
end