I have a Rails model called request_form. In the form I have multiple boxes that can be selected, similar to the "What can we craft for you section" in the following site http://mostlyserious.io/get-started/
I have a field called number_of_guests that can be a handful of values depending on which section is clicked. I plan on using javascript to grab the value of the clicked element and assigning it to the request_no_of_guest param. However, in the form I have that same field rendered 5 times to allow for each selection. What is the best way about this? Is there a better way to handle this? I thought about creating a controller method that loops through each instance of that request_no_of_guests param and determining which instance is populated and then sending that up.
Is this the best way to handle this case?
Well as you did not provide any useful detail I will answer as I understood the question.
Let’s have a quick look at what this might look like. To do so, we’ll imagine a demo app into which you can enter the name of a professor and select their various areas of expertise.
Professor has a field expertise which is String.
The form can be as follows:
<%= label_tag 'expertise_physics', 'Physics' %>
<%= check_box_tag 'professor[expertise][]', 'Physics', checked('Physics'), id: 'expertise_physics' %>
<%= label_tag 'expertise_maths', 'Maths' %>
<%= check_box_tag 'professor[expertise][]', 'Maths', checked('Maths'), id: 'expertise_maths' %>
alter app/controllers/professors_controller.rb
from
params.require(:professor).permit(:name, :expertise)
to
params.require(:professor).permit(:name, expertise:[])
Then in app/models/professor.rb
before_save do
self.expertise.gsub!(/[\[\]\"]/, "") if attribute_present?("expertise")
end
and in /app/helpers/professors_helper.rb
def checked(area)
#professor.expertise.nil? ? false : #professor.expertise.match(area)
end
This way you can grab the different values selected in the form into the expertise attribute, however this is not recommended if you are planning to query the selected options. The right way would be create a new model called Expertise and then create the relationship professor has_many expertises.
But if you are looking for something simple, then use the above code.
Related
I have a model Company that has a type field. There are two subclasses Fleet and Dealer.
I know the inheritance is working so I'm now working towards the views working too. However the views/companies/_form.html.erb is producing this error when I click edit on a specific company object on my webpage:
undefined method `dealer_path' for #<ActionView::Base:0x000000000418c0>
Here is the form_with tag:
<%= form_with(model: company, class: "contents") do |form| %>
*CONTENT*
<%end%>
I want to generate the form based on what company type I am looking at and for all the fields to be populated with their corresponding data.
I found this warning on the ROR site (https://guides.rubyonrails.org/form_helpers.html):
When you're using STI (single-table inheritance) with your models, you can't rely on record identification on a subclass if only their parent class is declared a resource. You will have to specify :url, and :scope (the model name) explicitly.
But I do not understand exactly what this means and I believe it is the key to my solution. I wish there was an example of this situation on that guide.
Any help or suggestions are welcome and appreciated!
UPDATE
I changed the form_with tag to be:
<%= form_with(model: [:company #company], class: "contents") do |form| %>
and from my understanding this now generates the URL companies/:id/edit
This is closer, and now brings me to the companies edit page but I can't update now because the changes don't persist.
My NEW question now is, what routes should I have set up?
If I'm on localhost:3000/companies and I click 'show company', should this take me to /companies/id: or take me to /dealer/id: / /fleet/id: ?
I have managed to route the app so it will take me to /companies/id regardless of the type value of the object. This works well and all CRUD is working well now too.
I didn't log exactly what it was I changed this time as I just reverted to a previous commit and rebuilt from there.
I'm trying to scaffold an app with Rails 4 and I had this little issue with the foreing keys, forms and Entity names. Here are some details:
rails g scaffold user_type name:string
rails g scaffold user name:string pass:string user_type:references
As you can see there is a simple relationship 1:n between an user_type and a user. An it generates the right scaffold on this case. Here is an image of the form generated,
But what I want as a result of the generator is the next form,
So the first change that I want from rails g scaffold is to generate, at least e 1:n relationships with a select input. And also I'm looking for a solution that involves the Models with a label or something. I need a scaffold command that finally generates this.
Witch means that the Entity user_type has his name attribute has a "presentation label".
I understand that I can create a generator from scratch, but I believe that I'm missing some options at the command line, because the change actually really tiny.
And can come up with a solution that involves inserting the right code in each CRUD but i'm planning to use this into a 150 tables database. Any help?
You can replace the templates that the scaffold generator uses by creating alternative templates in a lib/templates/erb/scaffold folder in your application root.
In this case, you will want to copy the original _form.html.erb template and replace the text field with a collection_select:
<%- if attribute.reference? -%>
<%%= f.label :<%= attribute.column_name %> %><br>
- <%%= f.<%= attribute.field_type %> :<%= attribute.column_name %> %>
+ <%%= f.collection_select :<%= attribute.column_name %>, <%= attribute.name.camelize %>.all, :id, :name, prompt: true %>
<%- else -%>
More details can be read in my post on the subject.
(I reference this tutorial in this text)
I want to use the Html.EditorFor (or Html.Editor) helpers.
If a UserControl needs additional data it is passed via
...EditorFor(model => model.Album, new { Artists = Model.Artists, ... })
In the UserControl it's accessed via ViewData[stringKey], ie
... new SelectList(ViewData["Artists"] as IEnumerable, ...
To me this smells a little fishy as I would prefer a strongly typed ViewModel which ensures that specific data is available.
I'm now a little bit stuck as I don't know wheater there's a "typed way" to find or I should accept this way as-is.
How did you solve this issue? Any help appreciated!
Lg
warappa
I would probably change my view model so that I don't need to pass this additional information. You could make for example an album has a collection of artists. Now all tha you will have to do is:
<%: Html.EditorFor(model => model.Album) %>
And in your editor template:
<%: Html.DropDownListFor(x => x.SelectedArtist, new SelectList(Model.Artists)) %>
I have a page that collects information on two objects of the same type. When the page is submitted the action that handles the processing of the information submitted is attempting to use model binding, something similar to:
public ActionResult Submit(Person parent, Person child)
{
//Do some stuff
}
It manages to bind one of them successfully but not the other. Does anyone have any suggestions/resources etc that could help me get this to work?
If needed I can gut/rename and post the actual code for the various pieces.
The solution to this is very much similar to the solution to my question that I posted the other day (I wouldn't at all call this a dupe though).
What you need to do is just include the parameter name in your inputs, eg:
<%: Html.TextBox("Parent.Name") %>
.....
<%: Html.TextBox("Child.Name") %>
and it should all automagically work.
(I think this is MVC2 only, you didn't mention whether you were using 1 or 2)
Would it make sense to have a ParentChild Model with two person instances in it?
I don't think I've seen any examples like this trying to bind two models on post.
I know they now have this in ASP.NET MVC 2.0 <%: Model.CustomerName %>
So when you make HTML helpers is it better to use this way now (provided that you do not want to do HTML encoding)?
Using <%: %> should be used whenever you display user entered/submitted data to make your web pages safer.
But sometimes it's just not viable to HTML encode everything. What if you do want to preserve some HTML formatting? In this case you will have to use the regular <%= %> statement. Let's think of an example where this is the case.
Real-life example
Let's say you have some web content where users can submit their comments. You would like to provide the ability to preserve some formatting (at least line breaks). In this case you will have to preserve <br/> elements when later displaying these comments. You have two choices:
Cleanup and format comments when you store them in the DB - in this case you would strip all HTML tags from submitted comments and then replace all new lines (\n) with <br/>. When you would like to display this comment you could then call <%= Comment %>
Cleanup and format comments when you display them - in this case you would most probably call this <%= Html.Encode(Comment).Replace("\n", "<br/>") %>
Which one is better/safer depends on each particular case, but cleaning up HTML tags is always a nice step to include in any of the two. Everything also depends on allowed formatting definition. Should those be entered as regular tags or something similar to markdown or something completely different depends on you and the code in the end will most certainly depend on it.
Second approach advantages/disadvantages
advantage
Let's say that you do provide some formatting capabilities but after about a year or so you decide to change formatting rules or something related to them (which is quite common). If you use the second approach the new rules will work with old comments as well, because they were stored as is, while the first approach will loose its significance with old data. One example would be if you'd auto-detect web links in these comments in the cleanup/formatting phase. Using the first approach all links in old comments would stay unclickable, but if you used the second one even older comments with links would format them as clickable.
disadvantage
Second approach uses much more processing than the first one, because every comment would have to be preprocessed each time it's displayed, while in the first approach they're processed only once when we store them in the DB. Depending on the formatting/cleanup complexity and quantity of comments on each page this may become significant.
If processing does become a problem you should think of an alternative to use first approach, but while cleaning up and re-formatting the comment you'd save both versions in your DB. Original submitted comments as well as processed ones. So when you do change formatting rules you can always reformat old comments because you stored originals.
Yes, you always want to use <%: Model.CustomerName %> from now on where you can. Only in very specific cases should you use <%= %> but try not to use it at all.
If you are creating your own html helpers that you don't want to be encoded, then just return a MvcHtmlString from them.
E.g. This is a extension method I created to display a tick icon if the passed in value is true.
public static MvcHtmlString MECross(this HtmlHelper html, string value, string text)
{
if (Convert.ToBoolean(value))
{
string spanTag = string.Format("<span class=\"replace icon-cross\" title=\"{0}\"><em></em>{1}</span>",
html.AttributeEncode(text),
html.Encode(text));
return MvcHtmlString.Create(spanTag);
}
return MvcHtmlString.Empty;
}
Note that I Encode and AttributeEncode anything that could be dangerous in my extension method and then return a MvcHtmlString.
HTHs,
Chares