ruby on rails global method - ruby-on-rails

I have a user controller which consists of a method named listfolders().
class UserController < ApplicationController
def myaccount()
userId = session[:id]
#listfolders = UsersFolders.listfolders(userId)
#users = User.listusers()
end
end
In the views I have and I'm able to fetch the folders:
<% #listfolders.each do |userfolder| %>
<tr>
<td><b><%= userfolder.foldername %></b></td>
</tr>
<% end %>
PROBLEM: I want to display the folders in all pages like compose,drafs,trash etc ... instead of just for the action.
How can I do it ?

The basic, standard way to do this would be in a helper.
module ApplicationHelper
def listfolders(user_id)
lf = UsersFolders.listfolders(user_id)
render 'users_folders/listfolders', :listfolders => lf
end
end
then in app/views/users_folders/_listfolders.html.erb
<% listfolders.each do |userfolder| %>
<tr>
<td><b><%= userfolder.foldername %></b></td>
</tr>
<% end %>
calling it is as easy as:
<% listfolders(session[:id]) %>

If I understand everything right you need some :before_filter in your controller to initialize #listfolders and #users variables

You can easily move the code to load the folder + the partial template to a cell component and then call that cell from any view.
Check this:
http://cells.rubyforge.org/
It will work just like the render :partial calls but will add a controller like process that should load the user folders and then will create the partial to be rendered.
The other approach that should work is to have a method on the application_controller to load the folders. Then add a before_filter calling that method to every action that should render the folders.
Finally you can create a shared partial to be rendered on each of the views that should be showing that.
Note: The method to load the folders can be defined in a more specific controller if you will only show the folders on actions from the same controller of for a child controller.

Related

Render results on #show without storing data in ActiveStorage

I'm learning RoR by building my first app (yay!). I gotta a question thought as rails guides do not cover this topic:
How to render unique results on #show to a user without storing any data in a model?
Steps I want to take:
Create a basic index view with a form_tag that will allow user to submit a link (string) and click submit button
Write Service Objects that will allow me to parse that link and create a response I want user to see
I want to write a #show method in a separate controller that will allow me to display all the data. (I also want to parse my params[:link] in that method using Service Objects.
I want to finally display this data in a table in #show view (probably I need to create a unique #show/[:id] for each user?
Here's what my app looks like at the moment (more or less):
Static Controller (just to render index.html.erb with a form)
class StaticController < ApplicationController
def index
end
end
Static Index view (yup, parsing imgur link here)
<h1>Hello Rails!</h1>
<%= form_tag("/images", method: "post") do %>
<p>
<%= label_tag(:imgur_link) %><br>
<%= text_field_tag(:imgur) %>
</p>
<p>
<%= submit_tag("Get my cards") %>
</p>
<% end %>
Images Controller (where all the magic SHOULD happen)
class ImagesController < ApplicationController
def show
#collection = params[:imgur_link]
#service1 = service1.new(*args).call
#service2 = service2.new(*args).call
...
end
end
Images Show view
Empty as I'm stuck with the Images controller at the moment.
Any help would be more than appreciated.
Thanks!
There is no reason you should put something into storage just in order to display it. If you get to a point when you have the results in your controller, you could just pass them to view in some #variable
As I see, you have set up the form for step 1. If you also have routes.rb call 'images#show' for POST /images, then you will have params[:imgur_link] available in your show action. This should do:
# config/routes.rb
YourApplication.routes.draw do
# ...
post '/images' => 'images#show'
end
Now you have to somehow process that link. Since I don't know what your results should be, I'm going to assume that you have two classes, Service1 and Service2, both of which accept an URL and return collection of results, and both collections hold the elements of the same class. Then you can leave only unique results for your show view, like this:
# app/controllers/images_controller.rb
class ImagesController < ApplicationController
def show
link = params[:imgur_link]
results1 = Service1.new(link).results
results2 = Service2.new(link).results
#results = (results1 + results2).uniq
end
end
Then you can do something with #results in your show view. E.g.
# app/views/images/show.html.erb
<% #results.each do |result| %>
<%= result.inspect %>
<% end %>

Ruby On Rails Display Image

I am a newbie at it.I have just educated myself for 2 days. And a have a problem.
Example: I have a table , called as tblData, includes 2 columns: id, img_link. img_link contains link to an image.
I want to show all of them in this table(id and image, not image link) into a html file.
So, exactly what I need do?
If you have an image link that you can pull from your database, you can do something like this:
Assuming you have an object assigned and everything's set up:
In your controller for tbl_data (e.g. app/controllers/tbl_data_controller.rb):
class TblDataController < ApplicationController
def your_action
#tbl_data_item = TblData.first
end
end
(The code above is just an example, you should substitute for whatever code/query you wish to run)
In your view template, you can render an image from a link using the following Rails view helper:
<%= image_tag(#tbl_data_item.img_link) %>
This would output the following HTML:
<img src="/path/to/image/from/img_link" />
There's a lot more info on this helper on the Rails api docs. The Rails Guides has some awesome info on getting things set up and running as well. Hope this helped!
UPDATE:
To give you a better example with clearer steps, you would do something like the following:
Set up your routes (app/config/routes.rb):
Rails.application.routes.draw do
resources :tbl_data
end
Create your model, used to communicate with its respective database table (app/models/tbl_data.rb):
class TblData < ActiveRecord::Base
# your model-specific code goes here - validations, scopes, etc.
end
Create the controller, which responds to when a user hits a certain route in your app (app/controllers/tbl_data_controller.rb):
class TblDataController < ApplicationController
def your_action
#tbl_data_items = TblData.all
end
end
Create the view template, that will be rendered for your user(app/views/tbl_data/your_action.rb):
<table>
<% #tbl_data_items.each do |item| %>
<tr>
<td><%= item.id %></td>
<td><%= image_tag(item.img_link) %></td>
</tr>
<% end %>
</table>
The above would show a table with each record in the #tbl_data_items as a row, with 2 columns, one with the id, and one with the actual image for that item.
Create a folder in public called images, put the desired image in that folder.
Put <%=image_tag 'whatevertheimagefilenameis.png', class: 'example-class', id: 'example-id'%> in the html.

How to call a controller method in an associated view file?

I am trying to create a method in a controller file, and then call that method in the index.html.erb view file.
Here are both my index action and my custom method in the controller file:
def index
#mustdos = current_user.mustdos
end
def calculates_mustdos_days_left
((mustdo.created_at + 7.days - Time.now) / ( 60 * 60 * 24)).round
end
helper_method :calculates_mustdos_days_left
And here is the relevant code from my associated my index.html.erb file:
<% #mustdos.each do |mustdo| %>
<tr id="todo-<%= "#{mustdo.id}" %>">
<td><%= calculates_mustdos_days_left %></td>
</tr>
<% end %>
I am getting this error:
NameError in Mustdos#index
And it is referencing this line from my index.html.erb view file
<td><%= calculates_mustdos_days_left %></td>
How can I resolve this? Thanks.
In general, I try to leave my helper methods for when I need them to generate content/output for a view. When I want to calculate and return data regarding a particular Model instance, I either add that code to a Service or the model itself.
app/models/must_do.rb
def days_left
((self.created_at + 7.days - Time.now) / ( 60 * 60 * 24)).round
end
Then, in my view, it's easy to access this off the model's instance:
<% #mustdos.each do |mustdo| %>
<tr id="todo-<%= "#{mustdo.id}" %>">
<td><%= mustdo.days_left %></td>
</tr>
<% end %>
For me, this is a cleaner implementation of the desired behavior. Wanted to offer it as an alternative/additional approach to #IS04's answer.
you could try:
helper_method def calculates_mustdos_days_left(mustdo)
((mustdo.created_at + 7.days - Time.now) / ( 60 * 60 * 24)).round
end
and then in your view file:
<% #mustdos.each do |mustdo| %>
<tr id="todo-<%= "#{mustdo.id}" %>">
<td><%= calculates_mustdos_days_left(mustdo) %></td>
</tr>
<% end %>
but instead controller methods you should use helper methods, also if your method is more general (related to model) and doesn't depend from view, you could define it in your model as #craig.kaminsky written
You can't do it. You can't call methods outside of the controller action you are in in your view. If you have a piece of logic like that you should really try to get it into a model. In this case I would put this method in the mustdo model.
But in those cases where putting the logic into a model does not make sense you can use helper namespaces. It is sort of a miscellaneous drawer for methods that don't quite fit anywhere, like display logic. Helpers go in the app/helpers/ directory. By default there is a helper namespace file in there called application_helper.rb. Any method you put in there will be available in all your controllers and views.

Rails: Having a button in a view call a method in a controller, route not working

Hi I'm making a rails app that uses Zendesk API calls. I have a controller that uses two classes I defined
class TicketsController < ApplicationController
require 'ticket_fields'
require 'ticket_search'
def getTickets
#search_fields = SearchFields.new(client)
#tickets = TicketSearch.new(client)
end
def search_tickets
#ddcustomvalues = [params[:customer_company_id], params[:study_id], params[:type_id], params[:system_id]]
#tickets.search_tickets(ddcustomvalues)
end
end
One class SearchFields uses the api to load values I want to filter tickets by into arrays. My view then uses these values to populate drop down lists.
The other class TicketSearch looks like this.
class TicketSearch
attr_reader :tickets, :text
def initialize(client)
#text = "query"
#tickets = Array.new
client.tickets.all do |resource|
#tickets << resource
end
end
def search_tickets(custom_search_fields)
querystring = "type:ticket+tags:"
custom_search_fields.each_with_index do |field, index|
unless field == ""
if index ==0
querystring += "#{field}"
else
querystring += " #{field}"
end
end
end
#text = querystring
end
end
What I want to happen in my view is when a button is pressed it changes the value of #text to the querystring generated by the drop down list options that were selected. I'm currently doing this for testing to see if my querystring is correct and the button works. What I eventually want it to do is send the querystring to the ZenDesk Server and returns the tickets I filtered for. the #tickets array would then be replaced with the filtered tickets the server returned. Currently my button code looks like this.
<%= button_to 'Search', :action => 'search_tickets' %>
with all the route code I've tried I either get an error upon starting the page. Or when I press the button nothing happens and the #text being displayed in my view remains "query". Can someone help explain what I need to do I don't quite understand how routes work.
==================================================================================
Hey so I made the changes you suggested and did some reading up on AJAX and js and I think I'm almost at the answer my view now looks like this
<div id="test" >
<%= render partial: 'text', locals: { text: #tickets.text} %>
<div id="test" >
and I created a partial _text file that looks like this
<p> Query: <%=text%> </p>
and a js file search_tickets.js.erb
$("#test").html("<%= escape_javascript(render partial: 'text', locals: { text: #tickets.text } ) %>");
any idea what may be going wrong everything loads up okay but the text remains the same in the partial i set up when i hit the button still
the console outputs this after the button is hit
ActionController::RoutingError (No route matches [POST] "/tickets/search_tickets"):
so I guess it may actually be a routing error my route looks like this
resources :tickets do
collection do
put :search_tickets
end
end
and the form tag calling the path looks like this
<%= form_tag search_tickets_tickets_path, remote: :true do %>
<table>
<tr>
<td align = "left" valign="middle"> <font size = 4> Customer Company </font> </td>
<td align = "left" valign="middle">
<%= select_tag "customer_company_id", options_for_select(#search_fields.customer_companies), :prompt => "Select One" %>
</td>
</tr>
......
<tr>
<td> </td>
<td align = "left" valign="middle">
<%= submit_tag "Search" %>
</td>
</tr>
</table>
<% end %>
==================================================================================
(Update)
I think I fixed my last problem by changing my form tag to this
<%= form_tag search_tickets_tickets_path(#tickets), method: :put, remote: :true do%>
however now I get this error from the terminal after I hit the button
NoMethodError (undefined method search_ticket' for nil:NilClass):
app/controllers/tickets_controller.rb:15:insearch_tickets'
how would I pass #tickets as a parameter through my route because clearly its not accessible by search_tickets right now as its giving a nil class error.
Variables
when a button is pressed it changes the value of #text to the querystring generated
It looks to me like you're confused with the stateless nature of Rails - in that, just because a view has been rendered doesn't mean the values / variables are still available for use.
It was mentioned in the comments that it seems you're basing a lot on experience with other frameworks / programming patterns. The best way to describe your solution is that Rails has to "refresh" all your variables / values each time it processes a request; consequently meaning that if you send a button request - you'll have to perform the request as if it were the first one
Ajax
The bottom line is that you need to use an ajax request to pull this off.
To do this, you'll be be best creating a form (not just a button_to), as this will give you the ability to send as many params as you want. You should use form_tag:
#config/routes.rb
resources :tickets do
collection do
get :search_tickets
end
end
#view
<%= form_tag tickets_search_tickets_path, remote: :true do %>
... #-> fields for your params
<%= submit_tag "Search" %>
<% end %>
This will give you the ability to define the following in your controller:
#app/controllers/tickets_controller.rb
Class TicketsController < ApplicationController
def search_tickets
#ddcustomvalues = [params[:customer_company_id], params[:study_id], params[:type_id], params[:system_id]]
#tickets.search_tickets(ddcustomvalues)
respond_to do |format|
format.js #-> loads /views/tickets/search_tickets.js.erb
format.html
end
end
end
#app/views/tickets/tickets_search.js.erb
//JS here to manipulate your original page
Requests
The bottom line here is that if you want to "manipulate" your view without refreshing, unlike "native" application frameworks, where you can rely on a persistent state, with Rails, you basically have to construct the request from scratch (IE passing all the params required for the method to run)

Rendering rails partial with dynamic variables

I'm trying to render a partial based on the taxon the user is inside. In my application.html.erb layout I have the following line of code:
<%= render 'spree/shared/women_subnav' if #enable_women %>
In the taxons controller, inside the show method, I have:
#taxon_id = params[:id].split('/').first
And in taxons#show I have:
<% if #taxon_id == params[:id].split('/').first %>
<%= "#enable_#{#taxon_id}" = true %>
<% end %>
When I run this I get a SyntaxError. But in taxons#show If I just enter:
<% if #taxon_id == params[:id].split('/').first %>
<%= "#enable_#{#taxon_id}" %>
<% end %>
without the '= true' then the page renders, outputting '#enable_women'. So I know it's getting the correct variable, I just need that variable to be set to true. What am I missing?
Thanks so much.
First of all I would like to give you some heads-up:
calling first on a user submittable input is not a great idea (what if I submit ?id=, it would return nil) also non utf-8 encoding will crash your app such as: ?id=Ж
Controllers are beast! I see you are setting the value of a true/false instance_variable in the view, please use controllers do define the logic before rendering its output. especially when parameter dependant.
so for a solution:
in your controller as params[:id] should suggest an INT(11) value:
def action
# returning a Taxon should be a good idea here
#taxon = Taxon.find(params[:id])
# as I would give a Taxon class an has_many relation to a User
#users = #taxon.users
end
and in your action's view
<%= render :partial => "taxons/users", collection: #users %>
of course you would have the great ability to scope the users returned and render the wanted partial accordingly.
if you want more info about "The Rails way" please read:
http://guides.rubyonrails.org/
Have fun!
use instance_variable_set
instance_variable_set "#enable_#{#taxon_id}", true
just a reminder that it's better to do these things inside a controller.

Resources