Joining on new line: displaying on new line - ruby-on-rails

(edit: I've temporarily fixed this by simply placing it in a table, but I'd like to do cool things with each line styling wise and I feel like I'll be restricted with a table)
I'd like to display an array of strings in a view page with each string on its own new line. I have a Story model with columns for title and author_id, and a StoryLine model with columns for story_line, line_index, and story_id (my question does not concern this data structure - I'm confident that this is the right move for my use case). The story text consists of many lines without periods that are split on new lines, so when the text gets inputted, I parse them into the database in the create action as follows:
story_lines = params[:story_text].split("\n")
story_lines.each do |line|
#story_line = #story.story_lines.build
index = story_lines.index(line)
#story_line.line_index = index
#story_line.story_line = line
#story_line.save!
end
When a story gets opened by a user, all the story_lines get displayed in order of their index through the following code in the show action of the controller: #story_lines = #story.story_lines.order(:line_index).pluck(:story_line).join("\r\n")
They then get displayed in the view as follows: <%= #story_lines %>
However, for as many different methods as I've tried of changing this around in my controller and view, it's not displaying them on new lines. It's joining them successfully and in the correct order, but each sentence bumps up right up against the next one, with literally zero spaces inbetween the last word of one sentence and the first word of the next sentence.
Any ideas on how I should do this? I'm almost positive that I could do it by putting each newline in its own row of a table, but this seems like a cheap workaround for something that should be able to be handled with a <br />

What you need is more/better html :)
The problem is not rails - but the fact that this is what happens in a browser when you pump out a whole bunch of text.
If you want newlines to appear in html - then you need to use something that adds breaking-space.
You could use <br> for that (which is literally what br stands for) or you could use paragraphs eg:
<p> <!-- text should always be put inside a block-level object eg a paragraph -->
<% #story_lines.each do |line| %>
<%= line %><br> <!-- br example -->
<% end %>
</p>
<% #story_lines.each do |line| %>
<p><%= line %></p> <!-- p example -->
<% end %>
Obviously only choose one or the other or it'll be duplicated. :)

Related

Rails: How to save formatted text in text_area?

I have a text_area tag which allows the user to enter his Bio. When a user is tyoing and if he hits enter or return, a new line starts. But when he saves his input all the text is displayed in one paragraph. I want functionality similar to what stack overflow has.
For example - I hit enter now
This text appears on a new line*
How can I do this?
This is my code in Rails:
<%= form_for :profile do |profile| %>
<%= profile.text_area :bio %>
<%= f.submit "Save Bio" %></p>
<% end %>
You should use text editor for example ckeditor (to simplify web content creation), and in view try simpleformat or raw:
<%= simple_format("Here is some basic text...\n...with a line break.") %>
<%= raw("Here is some basic text...<br/>...with a line break.") %>
There are many ways to handle this. When displaying text previously inputed in text area you can:
replace newline characters with <br/> tags
use <pre> tag and display text inside that tag
split text by newline characters and then wrap each of the chunks into <p> tags
When using approach 1 or 3, make sure to pass text through raw helper, so that any tags within text are displayed. Be aware though, that user may pass arbitrary html inside the textarea, hence your code may be subject to xss attacks.

How to render horizontal page layout with multiple frames

We have a simple app which has a horizontal layout (left hand side panel and content on the right hand side), with a header and footer. So if you click on a certain object on the left hand side, the view is rendered on the right hand side with navigation panel in the header and footer links. The layout actually renders content on the same page itself for any action on the left hand side and the contents of the left hand side will differ based on the section chosen in the header. How should we go about designing the routes in these cases, which differs from the basic navigation where every action is rendered on a different page.
My routes looks like this..
resources :foos do
resources :foo_bars do
end
end
I would need to show all foos on the left hand side panel and if the user selects a foo it needs to show properties of foo and foo_bars in a table on the right hand side panel. How will the view look for me and how will the URL at the browser look for me? We will have several tabs at the top and based on that you will show foos or similar top level objects
The routes remain the same. You would need to ajaxify your calls.
If your question is:
how should we go about designing routes
The way you have it is just fine if you want to utilize nested resources, and in your case it seems logical.
http://guides.rubyonrails.org/routing.html#nested-resources
Currently, your url will be as follows: /foos/:foos_id/foo_bars/some_action
Let me rename these so things make more sense. Lets say foos is categories, and foo_bars is actions.
Personally, I would override the to_param in the categories model file.
to_param
#return a more readable attribute here
name
end
In this way, your URL would be more closely tied with the names of all the categories on the left side of your page.
So now, if you had a record in the categories table which had the name animal, your URL would look like this: /categories/animal/actions/some_action
That seems pretty logical to me. Make sure in your controller you fetch the record via the proper attribute if you use to_param.
I would apply the same principal to the nested resource as well, then your whole URL would be accurately representing what tab is selected on the page. If you had a record in actions with the name "running", and you had things setup properly, then you could have your url look similar to: categories/animal/actions/running.
You could play around with all the options in your routes file, then use rake routes in terminal to see what changes and what your urls will look like before you even touch the browser.
Here are some extra resources for you.
http://apidock.com/rails/ActiveRecord/Integration/to_param
http://guides.rubyonrails.org/action_controller_overview.html
Hope this helps.
There is no good answer to your question - it all significantly depends on the layout of your application. Besides, there are valid answers here about to_param, and using AJAX, that add important details. But, to give you a head start.
For your views/foos, rewrite your index.html.erb as:
<%= render partial: "show_foos", locals: { foos: #foos, selected_foo: nil }%>
And your show.html.erb as:
<%= render partial: "show_foos", locals: { foos: #foos, selected_foo: #foo }%>
In your foos_controller.rb in show method you need to obtain both #foos and #foo, e.g.:
#foos = Foo.all
#foo = Foo.find(params[:id])
Now, to the fun part. Back to views/foos directory. Create a partial called "_show_foos.erb" (the one that we called both from #index and #show). Do something like:
<table>
<tr>
<td>
<%= render partial: "show_foos_list", locals: { foos: foos, selected_foo: selected_foo }%>
</td>
<td>
<%= render partial: "show_foo_props", locals: { selected_foo: selected_foo }%>
</td>
</tr>
</table>
Please note that's an extremely brute & ugly example that creates a table with two columns: one for the list of foos in the left "panel", the other for displaying the results for the selected foos in the right "panel". In real life use divs and styling. Also, consider pushing the layout to where it belongs - to the appropriate layout file - and using named yields there. But, as I said, a headstart - simple table.
Now, just define the two partials mentioned here. First, the "_show_foos_list.erb" that lists the foos on the left. Assuming each foo has a 'title' attribute, something like:
<% foos.each do |foo| %>
<%= link_to_unless selected_foo && (foo.id == selected_foo.id), foo.title, foo %><br />
<% end %>
Second, the foo & foo_bars on the right - "_show_foo_props.erb":
<% if selected_foo %>
# Here display the Foo attributes
<h2> Foo: <%= selected_foo.title %> </h2>
<% selected_foo.foo_bars.each do |foo_bar| %>
# Here display each FooBar that belongs to Foo
<h3>FooBar <%= foo_bar.title %></h3>
<%= foo_bar.description %>
<% end %>
<% end %>
Again, very crude example. Replace 'title', 'description' with the right sets of parameters, use partials to display FooBars. Do the styling with CSS. Etc, etc, ... Refactor as you see fit.
Talking about the routes. What you get is when you go to your "www.yourapp.com/foos" url is the list of all foos on the left, nothing on the right. Once you press on any foo in the left column, you go to "www.yourapp.com/foos/:id", where :id is the ID of the selected foo (and consider to_param from the other answer here or more advanced techniques to make this part meaningful) and get the list of foos on the left, and the properties of the selected foo and all foo_bars belonging to it on the right.
Hope that helps to start laying out your own implementation based on the rough idea presented here.
If I understand your question correctly, the answers saying Ajax is required are not correct. I have an ancient Perl app (written in 1999) that does this. Am currently re-implementing in Rails, and it's working fine. Frames make it particularly easy to allow the data to scroll while the menu stays fixed.
You do need to use HTML4 frames, which are deprecated in HTML5, It's possible to use an IFRAME for the data rendering frame and be HTML5 compliant, but the result is less usable than the FRAME solution in HTML4, at least with some browsers.
As others have said, your routes are fine.
The trick is to use the target field in the form to direct the Submit response to the rendering frame. My haml code for the "command" frame is
= form_tag admin_menu_path, :method => :put, :target => 'data_frame' do
...
The rest is just a normal form. This form remains constant in (my case) the left frame while responses replace each other in the right data_frame.
The matching frame HTML is:
<frameset cols="360,*">
<frame name="menu_frame" src="...">
<frame name="data_frame" src="admin.htm">
</frameset>
You would have to use an outer frameset to get the header and footer, but this should be straightforward.
I am ready for comments saying frames are far from best practice. But for this particular application, they are perfect: simple, understandable, and extremely browser independent. E.g. my 1999 Perl generated code ran fine on IE 2.0 and Netscape (the ancestor of Firefox, friends). And it's still perfect on every modern browser I can find. Wish Ajax could say the same...
If I've misunderstood your question, I'll happily delete this response.

rails form using database

i have a rails form ive made in which the form fields are extracted from the database. i did it like this because for different products, there are different form fields. i could have made one big order form to do it, and if the product field didnt apply to the product it would be left blank, but it seemed like making the fields being called from a database made more sense because there are 30-40 fields per order. anyways the error in which im running into is when im extracting the row field_type, it prints out the literal value instead of putting it in rails. heres what it looks like:
<% #form_field.each do |field| %>
<p>
<%= "f.#{field.field_type}" %> #this prints out f.text_field
</p>
<% end %>
Instead of printing out f.text_field, i would like it to actually make a text field. I tried using raw but no look seeing as thats for html. is there a way to do this in rails?
You'd need to build up the string and send it to f, like f.send(field.field_type) (untested) along with any arguments needed for that particular form field type.

Need help modifying multiple models example from advanced rails recipes book

I'm developing a simple rails app for my own use for learning purposes and I'm trying to handle 2 models in 1 form. I've followed the example in chapter 13 of Advanced Rails Recipes and have got it working with a few simple modifications for my own purposes.
The 2 models I have are Invoice and InvoicePhoneNumber. Each Invoice can have several InvoicePhoneNumbers. What I want to do is make sure that each invoice has at least 1 phone number associated with it. The example in the book puts a 'remove' link next to each phone number (tasks in the book). I want to make sure that the top-most phone number doesn't have a remove link next to it but I cannot figure out how to do this. The partial template that produces each line of the list of phone numbers in the invoice is as follows;
<div class="invoice_phone_number">
<% new_or_existing = invoice_phone_number.new_record? ? 'new' : 'existing' %>
<% prefix = "invoice[#{new_or_existing}_invoice_phone_number_attributes][]" %>
<% fields_for prefix, invoice_phone_number do |invoice_form| -%>
<%= invoice_form.select :phone_type, %w{ home work mobile fax } %>
<%= invoice_form.text_field :phone_number %>
<%= link_to_function "remove", "$(this).up('.invoice_phone_number').remove()" %>
<% end -%>
</div>
Now, if I could detect when the first phone number is being generated I could place a condition on the link_to_function so it is not executed. This would half solve my problem and would be satisfactory, although it would mean that if I actually wanted to, say, delete the first phone number and keep the second, I would have to do some manual shuffling.
The ideal way to do this is presumably in the browser with javascript but I have no idea how to approach this. I would need to hide the 'remove' link when there was only one and show all 'remove' links when there is more than one. The functionality in the .insert_html method that is being used in the 'add phone number' link doesn't seem adequate for this.
I'm not asking for a step-by-step how-to for this (in fact I'd prefer not to get one - I want to understand this), but does anyone have some suggestions about where to begin with this problem?
There is a counter for partial-collections:
<%= render :partial => "ad", :collection => #advertisements %>
This
will render "advertiser/_ad.erb" and
pass the local variable ad to the
template for display. An iteration
counter will automatically be made
available to the template with a name
of the form partial_name_counter. In
the case of the example above, the
template would be fed ad_counter.
For your problem of detecting whether a row is the first one or not, you could add a local variable when calling the partial:
<%= render :partial => 'mypartial', :locals => {:first => true} %>
As it would be much easier to detect in the main file, whether a row is the first or not I guess.
Instead of detecting whether a phone number is the first, you could also detect whether a phone number is the only one. If not, add remove links next to all numbers otherwise, do not display the remove link. Note that besides showing/hiding the link, you also need to add code, to prevent removing of the last number by (mis)using an URL to directly delete the number instead of using your form.

In Rails, What's the Best Way to Get Autocomplete that Shows Names but Uses IDs?

I want to have a text box that the user can type in that shows an Ajax-populated list of my model's names, and then when the user selects one I want the HTML to save the model's ID, and use that when the form is submitted.
I've been poking at the auto_complete plugin that got excised in Rails 2, but it seems to have no inkling that this might be useful. There's a Railscast episode that covers using that plugin, but it doesn't touch on this topic. The comments point out that it could be an issue, and point to model_auto_completer as a possible solution, which seems to work if the viewed items are simple strings, but the inserted text includes lots of junk spaces if (as I would like to do) you include a picture into the list items, despite what the documentation says.
I could probably hack model_auto_completer into shape, and I may still end up doing so, but I am eager to find out if there are better options out there.
I rolled my own. The process is a little convoluted, but...
I just made a text_field on the form with an observer. When you start typing into the text field, the observer sends the search string and the controller returns a list of objects (maximum of 10).
The objects are then sent to render via a partial which fills out the dynamic autocomplete search results. The partial actually populates link_to_remote lines that post back to the controller again. The link_to_remote sends the id of the user selection and then some RJS cleans up the search, fills in the name in the text field, and then places the selected id into a hidden form field.
Phew... I couldn't find a plugin to do this at the time, so I rolled my own, I hope all that makes sense.
I've got a hackneyed fix for the junk spaces from the image. I added a :after_update_element => "trimSelectedItem" to the options hash of the model_auto_completer (that's the first hash of the three given). My trimSelectedItem then finds the appropriate sub-element and uses the contents of that for the element value:
function trimSelectedItem(element, value, hiddenField, modelID) {
var span = value.down('span.display-text')
console.log(span)
var text = span.innerText || span.textContent
console.log(text)
element.value = text
}
However, this then runs afoul of the :allow_free_text option, which by default changes the text back as soon as the text box loses focus if the text inside is not a "valid" item from the list. So I had to turn that off, too, by passing :allow_free_text => true into the options hash (again, the first hash). I'd really rather it remained on, though.
So my current call to create the autocompleter is:
<%= model_auto_completer(
"line_items_info[][name]", "",
"line_items_info[][id]", "",
{:url => formatted_products_path(:js),
:after_update_element => "trimSelectedItem",
:allow_free_text => true},
{:class => 'product-selector'},
{:method => 'GET', :param_name => 'q'}) %>
And the products/index.js.erb is:
<ul class='products'>
<%- for product in #products -%>
<li id="<%= dom_id(product) %>">
<%= image_tag image_product_path(product), :alt => "" %>
<span class='display-text'><%=h product.name %></span>
</li>
<%- end -%>
</ul>

Resources