Link_to helper: Nested Routes - ruby-on-rails-5

This driving me crazy...
I've built some test apps with standard routing, but this time wanted to nest b within a. So like this (a and b are examples for ease)
resources :a do
resources :b
end
in the 'b controller' I have index defined as
def index
#b = B.all
end
On the index page I have
<p>B index</p>
<ul class="b">
<% #b.each do |b| %>
<li>
<%= link_to b.name, b %>
</li>
<% end %>
Controller params are set
def B_params
params.require(:b).permit(:name, :description, :this, :that, :a_id)
end
So the error message is when viewing the index.html 'undefined method for b_path'
I'm pretty sure its a routing problem as all of my other index pages work fine. So what is the correct way to route the nested b_path.
I have tried
get '/a/:id/b', to: 'b#index' -----fails
get '/a/:a_id/b', to: 'b#index' ----fails
get '/b', to: 'b#index' ----- not surprising fails
So what am I missing. Is there something else to do or another way of linking once you nest resources
Thanks

OK so I managed to figure this out after what feels like an eternity. Just in case anyone is interested
The fault lied with the reference to 'b' immediately after the link_to b.name statement. It should have been...
<p>B index</p>
<ul class="b">
<% #b.each do |b| %>
<li>
<%= link_to b.name, a_b %>
</li>
So to explain, as I understand it. The three important files once nested are routes.rb where you need to set the correct route for the index... for this example it would be
get '/a/:a_id/b', to: 'b#index'
this comes from running rails routes and seeing the correct path returned there.
Then in the 'b controller' you declare the variable as normal
def index
#b = B.all
end
then in the view/b/index.html.erb you call the variable, but crucially refer to the new b#index path
<% #b.each do |b| %>
<li>
<%= link_to #b.name, a_b_url %>
</li>
<% end %>
I'm sure my understanding is not as complete as it could be yet but i've got it working so onwards and upwards. Happy days

Related

Show value of activity.trackable with public_activity Rails gem

I'm using the public_activity gem to track changes with my Reposts model, which contains a comment_id and belongs_to the Comments table. In the _create.html.erb partial for the create action of a Repost, I can use this code with no errors:
<%= activity.trackable.comment %>
and the view will display this text:
Comment:0x00000004508ee0>
Which proves that it's displaying the Activerecord using the relationship I established between Reposts and Comments. However, once I try to extend the code to show the content field on the Comments table I get an error. For example:
<%= activity.trackable.comment.content %>
Returns the following error:
undefined method 'content' for nil:NilClass
activity.trackable.comment seems to pull the right record. How can I extend this so not only does it pull the record via the established relationship, but that it also pulls another field from that table?
Thanks!
EDIT 1: Full view for views/public_activity/_create.html.erb
<% if activity.trackable %>
<%= link_to activity.trackable.comment, activity.trackable.comment %>
<% else %>
which has since been removed
<% end %>
EDIT 2: Per Leo's assistance, all I had to do was check for nil. Here's what I had to change my code to:
<% if activity.trackable && activity.trackable.comment.present? %>
<%= link_to activity.trackable.comment.content, activity.trackable.comment %>
<% else %>
which has since been removed
<% end %>
I highly recommend adding that additional code to check for nil if you followed along the public_activity Railscast like I did.
So it seems per this particular question, the activity.trackable.comment was returning a NilClass object for some activities causing the exception to be thrown.
The fix of course is to check to make sure comment is not nil by doing the following
<% if activity.trackable && activity.trackable.comment.present? %>
<%= link_to activity.trackable.comment.content, activity.trackable.comment %>
<% else %>
which has since been removed
<% end %>
It seems like you're accessing the wrong object to get a count from. I've used the impressionist_count method for this sort of task in the past, the documentation here might help you.

How to make a search results page with pg_search multisearch that has links to the results?

I finally figured out how to implement pg_search's multisearch feature. But I'm having trouble making a usable search results page that displays links back to the various articles and faqs that contain the search terms. It's a pretty basic setup using Rails 3.2.3:
Models:
I have an Articles and a Faqs model, both with "Title" and "Content" attributes, and this code in both models:
include PgSearch
multisearchable :against => [:title, :content]
Search Form View Code:
The search form passes everything to a controller called "results."
<%= form_tag result_index_path, method: :get do %>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "GO", name: nil %>
<% end %>
Results Controller:
class ResultController < ApplicationController
def index
#pg_search_documents = PgSearch.multisearch(params[:query])
end
end
I would like to make a search results page that displays the title of each result found, with a link back to that item. I figured out how to pull the 'class' attribute out #pg_search_documents. My thinking is to do something like this on the results page:
<ul>
<% #pg_search_documents.each do |pg_search_document| %>
<li><%= link_to pg_search_document.searchable.title, "../#{pg_search_document.searchable.class}/#{pg_search_document.searchable.id}" %></li>
<% end %>
</ul>
An example link that this code yields is: http://localhost/Article/3. If I could figure out how to downcase and pluralize "pg_search_document.searchable.class", I'd be home free. I've tried writing various methods in the model and controller, and tried writing a helper. But this is where my Rails skills fail me.
Any suggestions? Anybody know of a more elegant way of accomplishing this? Any ideas / suggestions are very much appreciated.
I did something similar and just used
<%= link_to pg_search_document.searchable.title, pg_search_document.searchable %>
to let Rails dynamically create the path to the associated record.
Well, it's amazing what walking away from the problem for a little while does. That, and more persistent Googling on basic Ruby. Here's the solution I came up with:
<ul>
<% #pg_search_documents.each do |pg_search_document| %>
<li><%= link_to pg_search_document.searchable.title, "../#{(pg_search_document.searchable.class).to_s.downcase!.pluralize}/#{pg_search_document.searchable.id}" %></li>
<% end %>
</ul>
Still, this seems ugly to me. I'd still be very interested to see something more streamlined and intelligent.

Rails3 form_for hidden_field undefined method 'merge'

My attempt to place a hidden_field within a form_for is crashing within cucumber on an ActionView helper error. Something also about FixNum which escapes me since I haven't dug through the source code. My prices_controller shows this:
#price = Price.new
#commodity = Commodity.find(params[:id])
I want to make the link between price and commodity with this hidden_field:
<%= form_for (#price), :url => prices_path do |f| %>
<% f.hidden_field :commodity_id, #commodity.id %>
.
.
<div class="actions">
<%= f.submit "Submit" %>
</div>
Looked at the form_for api and the above should work. Reading other replies on stackoveflow, I have put the hidden_field in its own div within the form, added a Hidden_field_tag, and placed it within the actions div before the submit line. Looking at the merge msg, I guess it doesn't like something about the line, but it appears OK to me. The commodity_id field is the match field, sam
If you could paste the error message itself, and the relevant lines of the trace, it could help us. Right now, the only thing I see is that the ERB tag before f.hidden_field should be <%=, and I'm not sure about it since I don't use ERB. For what it's worth, merge is usually used with Hash objects. Maybe it can point you in the right direction
EDIT Ok I get it. You have to write f.hidden_field :commodity_id, :value => #commodity.id.

tiny mce display tags in rails 3

I am trying to store content of tinyMCE into "detail" coloumn.
Now when I display the content it displays wit all the <p> tags <i> tags etc.
This Is a security feature in rails3 .
But I don't want the <p> tags to be displayed , I want it to be rendered as HTML.
One way I found was <%= something.detail.html_safe %>
the other way I thought was to create a function in model like
def detail_safe
return self.detail.html_safe
end
and display using <%= something.detail_safe %>
Either ways I need to change the <%= %> tag at many places. Is there an easier solution? Or should I manually change at every place?
Thank you.
In the model:
def detail
self[:detail].html_safe if self[:detail]
end
Please note that you will always get html_safe output in this case when you do model_object.detail.
Not matter how you do it, you will have to change all of your <%= %>.
Your options are:
<%= something.detail_safe %>
<%= something.detail.html_safe %>
<%= raw something.detail %>
The only other option I can think of is turning off XSS protection - but don't do that!

What is the best way to have a multiple model based form for account creation in Devise (RoR)

EDIT NOTE
I am rewording this question entirely now that I have a bit better understanding of rails & devise.
I am looking for a way to utilize a single table structure (Account) to create various account types.
What I am now having a hard time with is a structure where I need my Business to have an account but not necessarily vice versa (an Account could just be a typical user). I think the easiest approach would be just to have a 1 to 1 relation as opposed to inheritance but I could be mistaken there.
The reason its confusing to me is the registration process. If I accept the account information, I believe I could use accepts_nested_attributes_for to accept the account information but im afraid that'll break the workflow that devise is expecting. I considered overriding Devise::RegistrationController but I don't really know how rails is going to handle that (ie, if I call super but I am dealing with a Business rather than an Account - what happens?)
You can use CanCan to make account roles, and ask in your code current_user.role?(:admin)
There is good app template with device/cancan/spike integrated:
https://github.com/augusto/devise-cancan-spike
There is no problem per-se with having a form which manages multiple models, so long as the models are related to one another.
The 'stock' way of achieving this would be to use 'accepts_nested_attributes_for' in your model.
For your situation, you'd do something like this:
class Employee < ActiveRecord::Base
belongs_to :business
accepts_nested_attributes_for :business
end
Then in your registration view, you would use:
<!-- validation errors etc -->
<%= form_for #employee do |f| %>
<!-- all your employee fields etc -->
<%= f.fields_for :business do |b| %>
<p>
<%= b.label :name %>
<br/>
<%= b.text_field :name %>
</p>
<!-- more fields from business -->
<% end %>
<% end %>
If you wanted to handle both employee and 'normal user' registration in the same form, you could probably do something like this (never tried this, but I think it should work!):
<!-- validation errors etc -->
<%= form_for #person do |f| %>
<!-- all your person fields etc, assuming no extras for employee -->
<% if #person.respond_to? :business %>
<%= f.fields_for :business do |b| %>
<p>
<%= b.label :name %>
<br/>
<%= b.text_field :name %>
</p>
<!-- more fields from business -->
<% end %>
<% end %>
<% end %>
P.S. you mentioned in your question that you were worried Devise wouldn't cope with nested attributes. It definitely does, as I do exactly this in one of my applications.