where to place my forms to follow 'DRY' - ruby-on-rails

I am working on a larger application and I see that I end up repeating the same forms twice etc.
For example when you register and on edit account one is in the #new and the other is in the #edit. I'm assuming this is bad practice and it also takes up a lot of space in the view. How do I gather these forms and then just display them on both pages?

If you use the rails generators they normally create a structure like so:
edit.html.erb
new.html.erb
_form.html.erb
Both new and edit pages render the form partial like so:
<%= render 'form' %>
This keeps the code dry so long as your form is the same for editing and creating.
All partial file names begin with an underscore, and if you want a partial to be available across your whole application put it in views/shared.
Some reading on partials.

Related

Embedded Ruby not being read when calling html_safe

I'm developing a simple app that teaches people english. The app is based on 5 modules of 34 classes each - 170 total. Each class has its own html page.
Since i dont want to create a view for each class, i scaffolded an Aula model ("class" in portuguese) and saved the html of each class in the model's DB, so i could use only the standard Show view paths to show the classes using their individual id's.
Controller code:
def show
#aula = set_aula
end
These HTML pages are being stored in the database as strings and then being outputted on the Show view using the html_safe method.
#show view code:
<%= #aula.aula.html_safe %>
#"aula" is the DB attribute with the html of each class
It rendered the HTML with no problems, and i got what i wanted. But since i'm creating a rails app, i decided to use embedded Ruby code like <%= link_to %> and <% image_tag %> mixed with the HTML of the classes to create links and show images, and the problem is that these links are being outputted as strings as well, just like any other line, instead of being read and executed as actual Ruby code.
I've been doing a lot of research, but so far I can't find exactly how to make the ERB code be read properly.
Maybe I need to save the HTML in the DB using another data type, or I need to use another method to render the HTML.
First, I'll answer your question, then make a suggestion that you think very carefully before using this approach.
The answer in the post https://stackoverflow.com/a/14351129/483133 shows how to render ERB directly from stored HTML text. Modifying this, here is some code you could use:
def show_html
html = #aula.aula
template = ERB.new(html)
template.result.html_safe
end
# Run this from your controller action, for example, with
def show
#aula = set_aula
end
# inside your view show.erb.html
<%= show_html %>
Warning
I would strongly recommend against finding a solution that allows Ruby code stored in the database to be run. If the pages are able to be written in any way by end users, rather than trusted software developers, then you have opened a huge security hole. Any Ruby code could be run on your server.
I would suggest you consider using a client-side rendering solution (such as Handlebars: http://handlebarsjs.com/ ), which allows for basic rendering of data dynamically in HTML, while not allowing code to be run on your server.

Confused about how the render works in rails

I'm still fairly new to rails, but I've been trying to figure it out by building a bunch of simple projects like blogs, forums, clones over the weekend.
One of the blogs that I'm working on is a typical blog with users(devise), posts, and comments. I've been following a tutorial for this.
The thing that I've been really confuse on is setting up the comments and rendering it.
The tutorial teaches me to make a partial for comment in the comment view named _comment.html.erb and then another for form _form.html.erb . I fully understand that to call the form i just do render 'comments/form' but for the comment.html.erb i need to render #post.comments how come it's not 'comments/comment'? Why is it comments with the S?
I've tried reading up on render and plurization on rails, but most of them just talk about the model.
There are two convention over configuration things going on here that may be causing you some confusion but are meant to save time.
Rails will automagically find the right partial if it follows naming conventions, meaning if your model is Comment that the view partial is located in app/views/comments/_comment.html.erb. That means you don't have to specify the location of the partial when calling render, but instead can just pass the model object directly and Rails figures out that you want it to render the partial and finds it on its own.
The reason it's comments plural here is that you are rendering all of the comments as a collection, not just a single comment. It's a convenience feature to allow the developer to simply tell Rails to render a collection and it will automagically know to use the corresponding partial. It's identical to typing:
#post.comments.each do |comment|
render 'comments/comment`, object: comment
end
Note how the above code is calling render directly on a model object so we don't have to bother specifying the location of the partial (again, assuming you followed the convention when naming and locating things). If we named the partial something else, then we'd have to specify the location like your other examples.

One form to update multiple pages in Rails

Fairly new to Rails. I'm trying to create a form that updates two models, and outputs to two separate show pages. One, is this possible, and two, how? I saw a lot of posts about one form being able to update multiple models, but not sure if I can have one form that creates two separate pages.
edit:
Thanks for the comments so far. And, sorry for the lack of clarity. basically I have two models. One is for a "Course preview" page. And the second is for the "Actual Course". Any user can view the Preview page, but will have to purchase the course to be allowed to view the course page.
What I am trying to do is use 1 form to create the "course preview" and the "course" at the same time.
Thanks in Advance!
You can't render two pages at once, a user can only see one page at a time.
But you can create one page that displays the results with some clever coding. If you have two models, say Model1 and Model2, and a view for each one, say model1/show.html.erb, you can change the show.html.erb code from:
<%= #model.name %>
etc...
to
<%= render 'display' %>
Create a file named _display.html.erb, and put the contents from show.html.erb in there. Now, when you visit the show page for Model1, it will call the display partial and render all the information accordingly. Lather, rinse, repeat for Model2.
So, your return page for your dual form would also utilize this very same partial. The results page for your form would look like:
<%= render 'model1/display' %>
<%= render 'model2/display' %>
This pulls the partials for each model type and puts it in the results page.
For more information on using partials, see:
http://guides.rubyonrails.org/layouts_and_rendering.html#using-partials

How to selectively display fields in new/edit views with custom form builder in rails 3.2.12?

In our rails 3.2.12 app, we would like to selectively display fields in new/edit views (using simple_form) based on the access rules. For example, for sales, only customer's name and phone# can be displayed. Since we don't know what the access rule is going to be, we need to dynamically construct the view at run time. One way to accomplish this is to use if in the views and this would make views messy. We thought customform build might help. After reading a few posts online about custom form builder, we still did not have much clue. Can someone provide details about how to implement this with customform builder? Thanks for help!
UPDATE:
Since we don't know what the access rule is going to be, we need to dynamically construct view at run time.
Usually a custom form builder is used to change the structure of the form's HTML more than to control field access.
A couple of suggestions to "clean up" the views:
Using SimpleForm will let you handle form fields/labels as a unit, making it easier to exclude a field using only something like = form_builder.input :credit_card_number if current_user.admin?.
For a more application-wide solution CanCan can help you manage authorization and roles.
Edit:
Based on your comments, it sounds like the following could be a good approach for you if all the columns are treated the same and you don't need to change their order (using HAML, but you could change it to ERB if necessary):
= simple_form_for #model do |f|
= f.error_notification
- #model.columns_available_for(current_user).each do |column|
= f.input column
You can use rails helpers to do that.
For ex.
module SalesHelper
def show_fields
if current_user.admin?
render 'some_partial' #having name and phone field
else
render 'other_partial'
end
end
end
In your views add respective partials and from new or edit just call
<%= show_fields %>

Nested RESTful routes in Rails: how should I organize my views?

Lets say you have an Invoice resource, and each Invoice has nested InvoiceLine resources, i.e. a very common nested resource pattern.
Now, where should one put the view for showing each individual invoice line as a row within the invoice? Should invoice lines be rendered as a partial under invoices/_line.html.erb, or should they get their own full-fledged view under invoices_lines/show.html.erb? Normally the former would be the obvious choice, but when you add AJAX functionality (for adding and editing lines in the invoice show view), things get complicated.
I find myself really struggling with this on a regular basis, and I'm not really sure of the right way to deal with it.
Here's what I'm thinking:
A RESTful route for this will likely look something like this:
map.resoures :invoices do |invoice|
invoice.resources :lines, :controller => :invoice_lines
end
The standard folder structure for the views is:
app/
views/
invoices/
invoice_lines/
Now, when rendering the entire invoice with all of its lines, my inclination would be to make each line into a _line.html.erb partial under invoices/. But then when I want to add some AJAX functionality for adding and editing lines, the PUTs and POSTs are routed to the invoice lines controller, so shouldn't the line rows be rendered by a standard show.html.erb view under invoice_lines.erb?
So should my views look like this:
app/
views/
invoices/
index.html.erb
show.html.erb
_line.html.erb
invoice_lines/
Or like this:
app/
views/
invoices/
index.html.erb
show.html.erb
invoice_lines/
index.html.erb
show.html.erb
I'm stuck between having the InvoiceLinesController render its response to AJAX requests using the partial in invoices/_line.html.erb, or I can put the line row template code in invoice_lines/show.html.erb, and have invoices/show.html.erb render the individual lines as a component or AJAX request to InvoiceLinesController#index.
Neither alternative feels right. Any suggestions on the best practice here?
It feels as if invoice lines controller should have it's own set of views when rendered in the context of the invoice, but Rails doesn't really have an obvious provision for "contextualized" views.
What about to put a partial _line.html.erb into the invoice_lines folder and then use this partial in the invoices_lines/show.html.erb template and the invoices/show.html.erb.
That's how I did it in similar situations.
This way all invoice specific view code is in the invoice folder and all invoice_line code is in the invoice_line folder.
You are DRY: you can use Ajax calls to the invoice_line controller or render the whole thing by displaying invoice/show.html.erb.
invoice_items would be rendered both times through the same partial in invoice_lines/_line.html.erb
I hope this makes sense and is sort of an answer to your question. I'm not yet too experienced with Rails so I can't tell if this is "best practice"

Resources