Method Accesibility/Scope - NoMethodError - ruby-on-rails

I'm working on my first rails project and I have a problem that I just cannot figure out.
I generated a Scaffold for an object named Archive
to this object I added the method processfile
when I try to link_to said method from Archives#Index I'm getting this:
undefined method `processfile' for #<Archive:0x702de78>
This is the model archive.rb
class Archive < ActiveRecord::Base
belongs_to :users
attr_accessible :file, :user_id
mount_uploader :file, FileUploader
end
This is the code on the index.html.erb (belonging to archives)
<% #archives.each do |archive| %>
<tr>
<td><%= archive.file%></td>
<td><%= User.find(archive.user_id).name %></td>
<td>
<%= link_to 'Download', archive.file_url %>
::
<%= link_to 'Show', archive %>
::
<%= link_to 'Edit', edit_archive_path(archive) %>
::
<%= link_to 'Delete', archive, confirm: 'Esta Seguro?', method: :delete %>
::
<%= link_to "Process", archive.processfile %>
</td>
</tr>
<% end %>
this is the routes.rb line:
match "archives/processfile/:id" => "archives#processfile", :as => :processfile
the processfile method defined whitin archives_controller.rb doesn't have anything on it, i just wanted to test the functionality since I'm having a hard time getting the grip of the "rails way"
archives_controler.rb
def processfile
# #archive = Archive.find(params[:id])
#do something with the archive
end
All in all, what I ultimately want to achieve is to call the processfile method on a given archive(taken from the index table) to do something with it. On the example, I watered down the method call (not passing an archive or archive.file to it) to make it run, to no avail.
I've searched a lot (on google and in here) and haven't found a clear guide that would address my problem, probably because i'm new and can't fully grasp the concepts behind rails MVC.
I've read something about methods only being accessed by same controlers but I've seen sample code when people call methods on controllers from index views without declaring them as helpers. o.0
I know it's probably a silly confusion, but I can't figure it out :(

The way you've structured your route (i.e., match "archives/processfile/:id" => "archives#processfile") means that it's expecting an archive id to be passed. You need to adjust your link_to to pass one:
# app/archives/index.html.erb
<%= link_to "Process", processfile_path(archive.id) %>
The error you're receiving is because you're trying to call an instance method called processfile on archive, but there's presumably no method by that name. The second parameter of the link_to helper is a path, not an instance method.
EDIT:
If you're looking to make your routes more RESTful (which you should do if you've created an Archive resource), you can generate all your CRUD routes by declaring resource :archives in your routes. Then, within a block, you can declare a block of member routes, all of which will route to the specified action in your archive_controller.rb and enable you to pass an archive id to the action.
# config/routes.rb
resources :archives do
member do
get 'processfile'
end
end

You added the processfile method to your ArchiveController. That does not make the method available to the Archive model. If you want the method to be available to instances of Archive models then you need to put it inside the model as an instance method.
If you what you want to do is place a route to the action processfile in your ArchiveController then you can do so by adding link_to "Process", processfile_path(id: archive.id)

Related

Rails link_to if the association object is nil

I'm continually getting errors where I can't link_to an object because it is not present. Usually the object, say a 'store' has a 'customer' so on the store show page I want to link to customers that have purchased there (through a 'sale' model).
For whatever reason the customer is no longer in the database so when I am doing a link_to warehouse.customer_id customer_path(warehouse) I am getting a no method error on nil or No route matches {:action=>"show", :controller=>"customers", :id=>nil} missing required keys: [:id]
Should I be doing link_to warehouse.customer_id customer_path(warehouse) if warehouse.customer.present? or putting an if statement around it so that I can show the customer_id instead of nothing so
<% if #contract.customer.present? %>
<p><%= link_to #contract.customer_id, customer_path(#contract.customer) %>
<% else %>
<p><%= #contract.customer_id %>
<% end %>
The second option looks messy and will clutter up my view but I don't want to not show the information if the object is not present :/
I also have a routing exception handler in place to redirect to root_url if the object does not exist in the database but that would mean making my link_to customer_path(warehouse.customer_id) instead of just customer_path(warehouse.customer).
link_to_if was created for cases similar to this.
link_to_if #contract.customer, #contract.customer_id, #contract.customer

pass value of td element to rails controller

I'm trying to pass the value of a element to a rails controller!
Currently, I have something like this:
<td id="dbname"><%= link_to db, :action => :show %></td>
This represents a row in an html table, which contains a string value, e.g. "development".
When the user clicks on the "development" link, the <%= link_to ... %> grabs the value from the current clicked and passes that to a rails controller action, in this case the show action.
How can this be achieved!?
UPDATE - generating links:
<% #dbs.each do |db| %>
<tr>
<td id="dbname"><%= link_to db, :action => :show %> </td>
</tr>
UPDATE 2:
this is my index controller:
conn = Mongo::Connection.new
#dbs = conn.database_names #this returns an array of strings (which are the names of the databases)
Now I want to be able to click on of these databases and then to pass the clicked text to the rails controller show action. I'm not sure how I would generate a custom resources path for these links... but I was contemplating of doing it using Ajax or something javascript related. Maybe get the text of clicked link using jQuery and then send an Ajax request to the rails controller with the text as a parameter!
I think that it's a strange thing what you're trying to do, but a solution could be to use javascript to append the id to the href of each link as a query string.
If you could explain a little bit what you're trying to achieve maybe we could find a better solution.
Hope it helps!
Edit:
If you have a table of links I think that you should consider them as a resource and managing them the REST way.
Your controller should have an index and show action and you should declare the links as a resource in the routes file (maybe link it's a reserved word and you will have to use a different name, I'm not sure), the index action will fetch all the links and when you render them, you could specify the link for each one with something similar to "link_path(link.id)" (remember, you should have a show action defined) in the controller you will receive the link id so you could load it with a simple "find" and pass it to the view.
I recommend you to always look for the REST way to solve a problem in ROR.
Edit 2:
Ok let's see if this works for you:
I suppose that you have a model that represent those links that you're talkin about, for example:
class DataBaseLinks < ActiveRecord:Base
end
This model with be backed up by a table in your database, if you have generated it the rails way, you will also have an id column that identify each database link.
in your controller, let's say DataBaseLinksController, you'll have:
class DataBaseLinksController < ApplicationController
def index
#dabatase_links = DataBaseLink.all
end
def show
#database_link = DataBaseLink.find(params[:id])
end
end
(I've avoided all the validations and checks).
All you have to do in your index.html.erb is:
<% #database_links.each do |database_link| %>
<%= link_to database_link.name, database_link_path(database_link.id) %>
<% end %>
This will generate all the links with the correct path to the show action (maybe the route helper is a little bit different, but not so much).
Notice also that you'll have to add into your routes.rb the following line:
resources :database_links, :only => [:index, :show]
How do you see it?
Edit 3:
(I'll delete all my edited answers when we find a correct one)
Ok I'm going to suppose that you are not using something like mongoid so you don't have active record similar objects.
Have you tried this in your view:
<% dbs.each do |dbs_name| %>
<%= link_to dbs_name, :controller => "your_controller", :action => :show, :dbs_name => dbs_name %>
<% end %>

link_to problem

I want to display product count in a link_to, the link_to is a part of partial displayed in application.erb.html, the problem is, I have a method in my application controller named products_on_cart which return products count, when I try this code:
<%= link_to "<%= products_on_cart%>", :controller=>"carts", :action=>"index"%>
rails give me an error:
"syntax error, unexpected '>'
...er=>"carts", :action=>"index"%>"
I don't really understand why, can somebody help me?
You can't use <%= .. %> inside of <%= .. %>.
<%= link_to products_on_cart, [:carts] %>
You're nesting ERb tags. Make sure products_on_cart() is available as a helper method, then rewrite your link_to code without nested ERb tags as follows:
<%= link_to products_on_cart(), :controller => "carts", :action => "index" %>
To make products_on_cart() a helper method, either move it to app/helpers/application.rb, or declare it as a helper in your controller:
def products_on_cart()
# method definition goes here
end
helper_method :products_on_cart
If you only need to access products_on_cart from your views and not from your controllers, putting it in app/helpers/application.rb is the preferred way to go. If you need to use it in both controllers and views, use the helper_method approach above instead.

help a n00b understand rails, specifically inheritance, acts_as_nested_set, awesome_nested_set, sortable_element_for_nested_set

hey there, i'm trying to implement a drag and drop interface for a nested set in my first rails project. i'm new to rails so bear with me. my code is basically identical to this project: http://gist.github.com/128779. my problem is in the partial at this line:
<% for child in root.direct_children do %>
I'm getting a NoMethodError for direct_children which is an instance method of acts_as_nested_set, I believe. At the console if I try to create a new instance of my model, it is likewise unable to access the acts_as_nested_set instance methods, so I don't think the problem is in the partial but in the model.
Again, sorry if my terminology is wrong, I'm new to rails. Anyway, what am I doing wrong? I've got "acts_as_nested_set" in my model, just like the gist example above but my model does not appear to act as a nested set. How do I go about fixing this?
Thanks!
Here's the code for the model I am using (todo.rb):
class Todo < ActiveRecord::Base
acts_as_nested_set
end
And here's the partial:
<% content_tag :li, :id => dom_id(root) do %>
<%= content_tag :span, root.text %>
<% content_tag :ul do %>
<% for child in root.direct_children do %>
<%= render :partial => "tree", :locals => {:root => child}%>
<%end %>
<%end unless root.direct_children.empty? %>
<%end%>
root is passed to the partial from the view like:
<%= render :partial => "tree", :locals => {:root => #root} %>
and #root is defined in the controller like:
#root = Todo.find_by_parent_id(nil)
Again, the code is mostly copied wholesale with very few modifications from the gist link above.
A few things:
Have you checked that you installed the plugin properly? ./script/plugin install git://github.com/rails/acts_as_nested_set.git
Have you set up your table properly? Your model needs to have at least the following 3 columns by default (unless you want to override them): parent_id, lft, rgt. Without these acts_as_nested_set is going to have a hard time figuring out what's going on. I suggest you read the documentation at the top of this file because the readme doesn't say squat, nor does that gist for that matter.
If you've done the above, have you created a root element (not set the parent_id to anything) and then added at least one child to it?
m = Model.new
m.title = "My model's title"
m.save!
m2 = Model.new
m2.title = "My child"
m2.save!
m.add_child(m2)
I just did a quick test using the above, and afterwards I was able to do things like m.root? and m.direct_children. Good luck.
What I make from your title is that you're using quite a bit more than acts_as_nested_set. Try removing some plugins and try again.

Missing template

so i have this code:
<% form_tag(:action => 'find') do%>
Product name:
<%= text_field("cars_", "name", :size => "30") %>
<input type ="submit" value="Find"/>
<%end%>
upon pressing the button I want it to complete the method (def find) found in the controller but its requesting the html.erb file:
Template is missing
Missing template cars/find.erb in view
path H:\Documents and
Settings/owner/My
Documents/NetBeansProjects/RailsApplication5/app/views
in the find def (found in controller)
def find
#car = Car.new(params[:car_])
end
What is the last line of your find method? Generally, if you don't specify the template to render in your controller method, Rails attempts to find a template with the same name as the method. That is why it is saying it can't find cars/find.erb. Without seeing the code in your find action, it is hard to give a better answer.
Your find method should be doing some searching, not initializing with the parameters. I recommend checking out something like thinking sphinx or searchlogic if you want to do searching.
I believe that your code is executing the find action. However, after it finds the car object, it needs to write that into a template that shows the results of your search. By convention, rails looks for a file called find.html.erb in the view folder for that controller. So, the error message you are seeing means that Rails has executed the line of code in your action and is now trying to generate some HTML to send back to the browser
If you create a simple file in the view folder for that controller with contents:
<%= #car.name %>
You should see the results.
However, your code is a bit confusing to me as I don't know why a find method would create a new Car object. I would expect something like this:
def find
#car = Car.find_by_name(params[:name])
end
I would also expect that your form would be more like:
<% form_tag(:action => 'find') do%>
Product name:
<%= text_field_tag("name", :size => "30") %>
<%= submit_tag "find" %>
<%end%>

Resources