trying to link image to specific model id in rails - ruby-on-rails-4

I'm having a routing issue with an image. In my app I have images of items on the home page. I would like them to link to their image page.
Here is what my items controller looks like:
class ItemsController < ApplicationController
def show
#item = Item.find(params[:id])
end
end
This is what I have in my routes:
Rails.application.routes.draw do
resources :items
end
And this is what I have in the item partial:
<%= link_to(image_tag(item.image.url(:thumb)), item_path(:id)) %>
What I expected after reading the rails routing guide was that this would link to the item page for that image. Here is their example:
photo_path(:id) returns /photos/:id (for instance, photo_path(10) returns /photos/10)
I should also add that this is in my home page controller:
class StaticPagesController < ApplicationController
def home
#items = Item.where.not(category_id: 1)
end
However, that is not working. I've tried several different things, but all produce errors. Is there a simple way to do this?

The normal way to do what you want is this:
<%= link_to item_path(item) do %>
<%= image_tag(item.image.url(:thumb)) %>
<% end %>
You can just pass the instance of the item to item_path and also if you have complicated html for a link, it is usual to put it in a block for the link as shown here (with link_to something do).

Related

Rails 4: (acts as taggable) creating a tag cloud based only on a specific users posts

I am attempting to create a tag cloud based on a users microposts (obvious the counts on each tag for that user) using this in my controller
#tags = #user.microposts.tag_counts_on(:tags)
and this in my view
<% tag_cloud #tags, %w[xxs xs s m l xl xxl] do |tag, css_class| %>
<%= link_to tag, questions_by_tag_user_path(#user, tag: tag.name), class: css_class %>
<% end %>
The problem is, having checked this over and over, this is returning the tag cloud with the sizes based on tag counts based on all microposts and not just the ones by the #user.
I can't see why this is and the documentation is deprecated:
User.find(:first).posts.tag_counts_on(:tags)
Any thoughts?
This would work, if you would call the tag_counts_on on the Posts scope:
Post.where(user_id: 1).tag_counts_on(:tag)

Rails 4 search from "home page" to other models/controllers

UPDATE 4-6-2015:
Double checked here:
https://github.com/activerecord-hackery/ransack
to make sure I had everything right, aside from a few hiccups I think I do. I am not clear how or what automagic makes the f.submit whisk the user away to that model index with nothing in that model filled out, and the index action taking presidence (hence after doing a search takes me to the index view of the groups (what I am searching on) and shows everything from db as if the Group.all was called ignoring the search string (that I can see in the address bar) completely.
Really not sure what I am missing I am sure it something minusculey stupid on my part.
EDIT/UPDATE: So i got most of this working, the search screen is going to that controller. I am not sure what automagic is causing that, I thought my respond_to could trap and send back json so I could this with an ajax call and update the table that is in the main page. THEN if they click on that table it takes them to the edit form of that particular item (i.e. the edit of the correct model).
My visitor_controller.rb:
def index
#search = Group.ransack(name_cont: params[:q])
#groups = #search.result
respond_to do |format|
format.html
format.js
end
end
Adding the routes file too:
Rails.application.routes.draw do
resources :groups
get 'visitors', to: 'visitors#index'
root to: 'visitors#index'
end
So groups is a controller/model that I am trying to search on (one of many, will use the example in the answer to do many when I get the one just working first.)
So I am building an app, I found a "simple search" tutorial for rails 4:
http://www.stefanosioannou.com/rails-4-simple-search-form/
But I think that this assumes you to search from the view/model and all that of your controller. I.e.
I am in the groups view, I want to search my groups all through that controller.
Really what I am doing and finding so hard to do is have a welcome page, that has three search bars. Each bar searches a different model/view/controller.
The welcome page is called visitors and has its own controller, and view just no model.
So my visitors controller has this:
class VisitorsController < ApplicationController
def index
#groups = Group.search(params[:gsearch])
respond_to do |format|
format.html
format.js
end
end
end
I was just trying to get one search bar working for my Group model, so in my Visitors index.html.erb:
<div class="span12">
<h3>Welcome IPA of NM</h3>
<!-- search bar here -->
<% form_tag group_path, :method => 'get' do %>
<p>
<%= text_field_tag :gsearch, params[:search] %>
<%= submit_tag "Search Groups", :name => nil %>
</p>
<% end %>
</div>
This fails though as it says
No route matches {:action=>"show", :controller=>"groups"} missing required keys: [:id]
so here is my groups controller:
class GroupsController < ApplicationController
before_action :set_group, only: [:show, :edit, :update, :destroy]
def show
end
private
# Use callbacks to share common setup or constraints between actions.
def set_group
#group = Group.find(params[:id])
end
end
I am sure somehow the form code in the visitors index.html.erb is working with that group_path which means it is trying to do a show but has no ID yet when just starting? I really am lost, new to rails4 and not sure what I am missing here. I am guessing the convention is do all things from your model/view/controller not a cross views as I am trying to do here? So something I have to do extra to get around the convention or I am doing the whole thing wrong from the get go?
I would highly recommend Ransack for search queries in rails. You can view it here > https://github.com/activerecord-hackery/ransack and you can also watch an awesome rails cast by Ryan Bates over at http://railscasts.com/episodes/370-ransack
Ransack works across the board, you could even search all 3 models from the same form.
Using ransack, you would simply use:
<%= search_form_for #q do |f| %>
# Search if the models name field contains...
<%= f.label :name_cont %>
<%= f.search_field :name_cont %>
<%= f.submit %>
<% end %>
Then the search controller processes this into #results:
def index
#q = params[:q]
#search = Model.search(name_cont: #q)
#results = #search.result
end
Then you would loop through the results on your show/index page.
<% #results.each do |result| %>
<%= result.name
<% end %>
This would show all of your results on one search page. If you wanted to search multiple models, you can either have multiple forms assigning a different instance variable for each one eg: #q1 #q2 #q3 or, you could search them all from one model by using different instance variables for the search and results.eg
def index
#q = params[:q]
#firstsearch = User.search(username_cont: #q)
#secondsearch = Post.search(title_or_description_cont: #q)
#users = #firstsearch.result
#posts = #secondsearch.result
end
Remember to add the routes =)
get 'search', to: 'search#index'

Rails 4 update attribute (belongs_to) with click on link ( within dropdown list on show page)

In my app I have Issue model, which belongs_to Status model. What I need to do is to have dropdown list of links (or spans, doesn't matter) with Statuses Id's on Issue show page, so I could change status clicking on this (could be non-ajax and ajax).
I am rather new to Rails, so I do not know how to implement this, was thinking of few ways to do this, but non seems to be working.
Because you're new, I'll outline what I'd do for you (hopefully it will help):
#config/routes.rb
resources :issues do
get "change_status/:status_id", to: "issues#change_status"
end
#app/models/status.rb
Class Status < ActiveRecord::Base
has_many :issues
scope :not, ->(id) { where('statuses.id != ?', id) }
end
#app/controllers/issues_controller.rb
def show
#issue = Issue.find params[:id]
#statuses = Status.all.not(#issue.id)
end
def change_status
issue = Issue.find params[:id]
issue.status = params[:status_id]
issue.save if issue.status_id_changed?
redirect_to issue
end
#app/views/issues/show.html.erb
<%= #statuses.each do |status| %>
<%= link_to status.title, issue_change_status_path(#issue, status) %>
<% end %>
There's obviously some stuff to explain - if you need me to do that, let me know and I'll give you the details!
You can simply use the link_to rails helper like in the following code:
link_to "Change Status", my_path_to_update_status, remote: true, method: :put
This will send an AJAX PUT request (thank to the remote: true) to your my_path_to_update_status.
Then, you just have to update the status in the action corresponding to the path specified in the link_to helper tag.
More information about the link_to rails helper here

error getting path returned rails 4

I'm trying to access my page gallery/new via a link, so i have created this
<%= link_to 'New gallery' new_gallery_path %>
rake routes gives
gallery_index_path GET /gallery(.:format) gallery#index
POST /gallery(.:format) gallery#create
new_gallery_path GET /gallery/new(.:format) gallery#new
edit_gallery_path GET /gallery/:id/edit(.:format) gallery#edit
gallery_path GET /gallery/:id(.:format) gallery#show
PATCH /gallery/:id(.:format) gallery#update
PUT /gallery/:id(.:format) gallery#update
DELETE /gallery/:id(.:format) gallery#destroy
and within my routes i have
resources :gallery
My view at gallery/new is
<%= nested_form_for #gallery, :html => { :multipart => true} do |f| %>
--content here
<% end %>
whenever i click the link to view this page i get
undefined method `galleries_path
Can someone point out my mistake, please?
You've chosen the wrong name for your resources. It should always be pluralized:
resources :galleries
From this Rails will generate the plural and singular paths correctly. galleries_path for the index, gallery_path for show, etc etc.

How to render a view inside of another view (rails 4)

Hi I want to preface this by saying that I am new to coding.
I have an issue that I believe can be solved in two ways
A. by rendering a partial
B. by updating the controller
( I can totally be wrong but these are what I suspect lol)
I have two controllers/views "reviews" and "logs". and I want them to both appear on the same page.
How can I do this?
I tried rendering a partial but I alway get an error.
and I tried the piece of code below:
which made my reviews show up on the page, but when I add
#log = #user.logs.all
to it, it doesn't pull all the logs to the page like it does for the reviews.
def show
#user = User.find_by_name(params[:id])
if #user
#reviews = #user.reviews.all
render action: :show
else
render file: 'public/404', status: 404, formats: [html]
end
end
First things first. Views refer to actions in controllers. So there can be several views for each controller or even none.
So, if you want to render #reviews and #logs on the same page you should first instantiate both instance variables in the same action and then render both partials in the same action.
How do you do that? Easy.
First you got to the controller you just showed and edit that show action.
def show
# You can set the variable in the if-clause
# And you also need to use static finders with a hash as an argument in Rails4
if (#user = User.find_by(name: params[:id]))
#reviews = #user.reviews.all
#logs = #user.logs.all
# You don't need to call render explicitly
# if you render the view with the same name as the action
else
render file: 'public/404', status: 404, formats: [html]
end
end
Second: you go to your /app/views/reviews/show.html.erb template and put both partials there like this (this is just an example, adjust your markup to fit your needs).
<h1> Reviews and Logs</h1>
<div id="reviews_part">
<%= render #reviews %>
</div>
<div id="logs_part">
<%= render #logs %>
</div>
Now create 2 new partials /app/views/reviews/_review.html.erb and /app/views/logs/_log.html.erb and put all the needed markup there (use regular variables review and log to adress the repeating objects). Rails will automaticaly repeat those partials as many times as needed.
Or you can explicitely call the partial render
<div id="reviews_part">
<% #reviews.each do |review| %>
<%= render review %>
which is the same as
<%= render partial:"reviews/review", locals:{review:review} %>
<% end %>
</div>
Here is the way of rendering partials into views in HAML:
=render :partial => "header"
%h2 Hello World
=render :partial => "footer"
Every partial you render this way, has to be created within the same folder.
Each partial's name has to begin with an underscore (_). This should be the view's directory:
- home
- index.html.haml
- _header.html.haml
- _footer.html.haml