setting a link_to with default link label/title - ruby-on-rails

I have a model named product. What i wanted to be able to do was write "product.link" in my view to generate a "link_to product.title, product". I know I can't define the "link" method in the Product.rb file (because link_to does not work there), and i don't want to write "link_to product.title, product" every time i need to create a link to the product.
I was wondering if anyone could suggest the ideal way to go about having a minimal simple way of generating links to my products.
I was also wondering if there was a way in rails to set the default label field to show when i write "link_to product" instead of what it shows now: "#<Product:0x105093f20>"

Add a helper method which does the appropriate thing:
# products_helper.rb
def product_link(product)
# Change these to taste
link_to product.name, product_path(product)
end
Now in your view you can call the following in your view:
product_link product
As for your question about # appearing in the links, this is the link_to helper calling to_s on the object for the html portion of the link. Use a helper as above to define the default text.

Related

How to compare two items within Ruby on Rails?

So I'm trying to re-create GitHub version control for let's say posts. I've found a way to re-create an original post using duplicate AND another method to create a new post based on the original. Cool.
My issue is being able to display both the original and the new on the same page.
What I've attempted thus far is to just rely on the show method with having:
def show
#post = Post.find(params[:id])
end
Then in the view have in the form a checkbox to allow a user to select multiple posts, click a submit, and a new page renders displaying both side by side. Preferably showing the differences between the two but that's a wish list as I deal with this first.
Actually could I just simply do?:
def other_show
#post = Post.where(params[:id])
end
I also added in status as a boolean to help on the view for marking the checkbox. Would I then need to put something in the other_show method about the status?
If you want to "recreate" some sort of version control I suggest you use something like the audited. Instead of building your own. From your example and comments it seems you don't have a clear relation between all related (versions of) posts.
Using this gem, each change to the Post content (for example, if configured properly) would be stored as an audit.
Showing the differences is a different problem. That's usually called a diff and you can find gems that do it for you, for example: diffy
To show 2 different entities on one page you need to give posts_controller both ids.
Declare your show method like this:
def show
#original = Post.find(params[:id])
#compared = Post.find(params[:compared_id])
end
Correct route to this method will look like this:
/posts/:id?compared_id=:another_id
# Example: /posts/1?compared_id=2
To construct such a link in your view, you need to declare link_to method like this:
<%= link_to '1 <> 2', post_path(#post, compared_id: '2') %>
If you want to have a page where user can check 2 checkboxes for certain posts, you'll need to construct such href via Javascript.
But in fact I wouldn't suggest you to modify show method for such a task. It is better to use show method only for showing one entity from database. You can create another method, e.g. compare and pass both parameters there.
def compare
#original = Post.find(params[:original_id])
#compared = Post.find(params[:compared_id])
end
In routes.rb
resources :posts do
get 'compare', on: :collection
end
It will give you helper compare_posts_path, which will lead to /posts/compare and you'll need to pass original_id and compared_id to it, like this:
<%= link_to 'Compare', compare_posts_path(original_id: 'some_id', compared_id: 'some_another_id') %>
It will result to
/posts/compare?original_id=some_id&compared_id=some_another_id

is this the right link_to rails syntax?

<%= link_to "Profile", #user %>
# => Profile
if i use the above code replacing "Profile" with "Category" and #user with #category/#subcategory what do I then point the html link a href etc to?
Check the documentation for this method here.
The first parameter of the link_to method is the displayed text.
Secondly, you can pass in a single instance of an object which will generate a link to the objects #show action.
You may however pass a link explicitly (most common in my opinion).
This can be done by using the Rails path-helpers (user_path(#user)) or by passing in a string.
In your example, if you exchange #user with #category it would link to the categories #show action instead (Assuming you have a Category model and #category isn't nil.
Again, have a look at the documentation of the link_to method and get familiar with it.

Use a params[:value] to reference a controller method in Rails

I currently have a form (using form_tag). One of the fields is a dropdown list of options. Each option value matches the name of a method in my controller. What I want to do is when the form submit button is clicked, it runs the controller method corresponding directly to the value selected in the dropdown field.
I've built a work-around right now, but it feels too verbose:
def run_reports
case params[:report_name]
when 'method_1' then method_1
when 'method_2' then method_2
when 'method_3' then method_3
when 'method_4' then method_4
else method_1
end
# each method matches a method already defined in the controller
# (i.e. method_1 is an existing method)
I had thought that it may work to use the dropdown option value to run the corresponding method in my controller through the form_tag action (i.e. :action => params[:report_name]), but this doesn't work because the action in the form needs to be set before the params value is set. I don't want to use javascript for this functionality.
Here is my form:
<%= form_tag("../reports/run_reports", :method => "get") do %>
<%= select_tag :report_name, options_for_select([['-- Please Select --',nil],['Option 1','method_1'], ['Option 2','method_2'], ['Option 3','method_3'], ['Option 4','method_4']]) %>
<%= submit_tag "Run Report" %>
<% end %>
Any suggestions?
Can I change my controller method to look something like this - but to actually call the controller method to run? I'm guessing this won't run because the params value is returned as a string...
def run_reports
params[:report_name]
end
WARNING: this is a terrible idea
You could call the method via a snippet of code like this in the controller:
send(params[:report_name].to_sym)
The reason this is a terrible idea is that anyone accessing the page could manually construct a request to call any method at all by injecting a request to call something hazardous. You really, really do not want to do this. You're better off setting up something to dynamically call known, trusted methods in your form.
I think you should rethink the design of your application (based on the little I know about it). You have a controller responsible for running reports, which it really shouldn't be. The controllers are to manage the connection between the web server and the rest of your app.
One solution would be to write a new class called ReportGenerator that would run the report and hand the result back to the controller, which would run any of the possible reports through a single action (for instance, show). If you need variable views you can use partials corresponding to the different kinds of reports.
As for the ReportGenerator, you'll need to be a little creative. It's entirely possible the best solution will be to have an individual class to generate each report type.

Multiple options for update action

How can I pass and collect different options into a controller action.
E.g you have a Team model and you want to add or remove Users from the team?
I would assume this would go in the update action of the teams controller, but the update action also need to be able to update team details like name, address, ect.
I tried the following code but that produce some weird results to my css and produces errors.
link_to team_path(user), params[:add] ,:class => 'btn btn-mini pull-right', :method => :put
Weird results are probably caused by the mixed parentheses
params[:add}
what does your model look like? (Teams-Teammember relation?)
But in general:
- you should add actions to the appropriate controller (prob. teams_controller) for
adding and deleting members:
def add_member
end
def remove_member
end
and define routes in config/routes.rb to be able to use this actions (there are plenty of examples how that can be achieved in the comments generated), then you can use the resulting path helper for your link_to tag - check out the available routes and path helpers with
rake routes

Hard coding routes in Rails

Let's say I have this:
<%= link_to "My Big Link", page_path(:id => 4) %>
And in my page.rb I want to show urls by their permalink so I use the standard:
def to_param
"#{id}-#{title.parameterize}"
end
Now when I click "My Big Link" it takes me to the correct page, but the url in the address bar does not display the desired permalink. Instead it just shows the standard:
wwww.mysite.com/pages/4
Is this because I hard-coded an id into the page_path? It also does not work if I use straight html like..
My Big Link
I would appreciate it if anyone could verify this same behavior and let me know if this intended or not. I need the ability to hard code :id's to specify exact pages...
Just use page_path(page). I guess the path helpers don't access the database themself (which is good), but if they are being supplied with an object and that object has a to_param method this method is being used to generate an identifier.
<%= link_to "My Big Link", page_path(page) %>
It's because you are specifying the id:
page_path(:id => 4)
You could specify the path you want in this method:
page_path(:id => "#{id}-#{title.parameterize}")
Where have you defined the to_param method? In the model?
UPDATE TO MY QUESTION ---------------------->
Thanks all for the answers. This was kind of a one off situation. My solution was to simply go with html:
My Big Link
Which produced the desired:
wwww.mysite.com/pages/4-great-title-here
I didn't want to loop through page objects and waste a call to the database for this one link. Much appreciated for all the answers though!

Resources