I'm coming from Asp.Net MVC world and I'm confused how to approach Rails 3 forms from model perspective.
In Asp.Net MVC it is a bad practice to bind to business model forms in templates. The proper approach is to create a class for each form, create properties which are only needed in form and attach validation attributes to them. Then in code check for ModelState.IsValid and assign values from form model to business model. This leads to separation of concepts and also prevents properties hijacking (when hackers might post additional values together with proper values and change business model properties in his cruel way).
From all tutorials and books I've read there is no seperation of this concept in Rails world - you put validation in your business model and you bind your model to the form in the template.
Is it the right approach in Rails 3 and I should follow it? Or I should follow Asp .Net MVC approach and create a separate model with validation just for forms?
In rails, updates of models generally happen via mass-assignment. For example, a form posts a ton of attributes to your update action, your update action calls:
Model.update_attributes(params[:model])
and all the values in the passed hash are updated on the model. The problem then is what happens if a hacker adds
params[:model][:users_attributes][:email] = 'hacker#example.com'`
and updates the model's associated user's email address?
In Asp.Net MVC it seems like you simply don't allow this in the form template and the value can never get to your models, but in rails this is not the way things are done (correct me if I am misunderstanding Asp.Net MVC). In Rails, everything in a model (by default) can be mass-assigned, and so your fear is warranted.
In the link I supplied, you can see "For a normal user account, for example, you only want login and password to be editable by a user. It should not be possible to change the status attribute through mass assignment."
class User < ActiveRecord::Base
attr_accessible :login, :password
end
This means any other properties must be set manually and the object saved, thus preventing the same type of property-hijacking that Asp.Net's form templates protect against. In Rails, anything that should be mass-assignable should be in your attr_accessible and then ActiveRecord is the gatekeeper. No matter how your forms are written or what a hacker does to their HTML, those attributes can only be updated explicitly by your code, not by Rails' behind-the-scenes stuff.
Related
I am in the process of developing an ASP.NET MVC4 application where one of the requirement is to allow the administrator of the application to add additional data capture fields in the screens. What would be the best approach to address this?
There are different approaches.
First we have to note, that the Model itsself should be strongly typed. That leaves you with the option to put your dynamic data into the Viewbag. Therefor you should put your second model, or dynamic model, which is not type of your first trongly typed model, into the ViewBag in your Controller action.
The second option is putting your additional datafields, which the administrator can add to the view or hide in the view into your strongly typed ViewModel, and just let the administrator tinker with the visibility of the fields.
In addition to that, you could generate two views for 1 action, one which the basic datafields and one with the full set.
Kind regards
In my application each user has it's own menus depending on changing information on the database.
This way when a user logs-in I have to keep the parameters he can choose somewhere in a Station state table.
So when he choose the parameters I'll retrieve the correspondent option id and make a response from there.
I'm keeping this value in a Current Session object but I'm encountering several problems.
What's the best practice for doing this?
I'm reading several articles that state the Session object is not a good idea in ASP.NET MVC.
Session objects can still be used within MVC check out the answer here Using Session objects in MVC, Is it really bad?
It points to 2 other questions that had a similar question.
What kind of problems are you having?
You can use Asp.Net Cookies, you can create, assign and destroy within the controller
Follow this link Cookies in ASP.Net MVC 5 for more help ...
I have a Backbone.js application with RoR for the backend.
The typical backbone.js setup is it gets the data from the table, and updates/saves data to that same table. However, my backbone model is made of a universal list of vendors, and I want a user to be able to "select" a vendor, which would dump into a DIFFERENT table, called user_selected_vendors.
I don't even know how to set this up in backbone. Any ideas?
Its hard to give specific advice without seeing some code examples.
In general though, you should think of your Rails backend as providing JSON service endpoints for your Backbone code to talk with. When your Rails app receives requests from the Backbone front end, you can do whatever is necessary with the request data. You are not limited to providing JSON endpoints which directly map to your database tables.
Also, based on the name of your user_selected_vendors table, it seems like you are not taking advantage of the ActiveRecord associations. What you may really want is something along the lines of adding has_many :vendors association to your User model. See: http://guides.rubyonrails.org/association_basics.html#the-has_many-association
This is an incredibly newbish question, but I can't seem to find the answer.
I'm building an app that utilizes external APIs heavily, and I'm fairly new to Rails, so it's still a little rough to get around. I can't, for the life of me, figure out how to accept user input and execute a function in my app without writing to a model.
For example, I just want to let a user type in a Twitter username and have it display on the page. I know how to make a form to cache the search in a model, but I can't figure out how to just... make a function happen on a page. I've been breaking my brains on this for several days now.
Please help? :/
You don't need a model to use Rails, but if you don't need ActiveRecord at all, you might benefit from a lighter framework like Sinatra. That doesn't answer your question, but it's worth thinking about if you really have no database requirement for your application.
It sounds like you're just trying to access non-resourceful user input, which is accessible in the controller via the params hash. So, assuming you have set up a valid route for the form action, you use your controller to extract GET or POST parameters.
For example:
# You define a non-resourceful route in routes.rb for your form action.
get 'twitternames/show'
# Form action directs user to GET the following route after filling in the form.
http://example.com/twitternames/show?user=foo
# The controller action extracts the data.
def show
#user = params[:user]
# render the view unless you tell rails to do something else
end
# show.html.erb
<%= #user %>
Creating the right route is the key. Once you've defined a route that can break a URL into the proper segments, the rest will fall into place.
Back-end: I have a model (User) that has_many of another model (ContactPreference).
Front-end: An interface allowing the user to reorder, add, and delete contact preferences for a particular user.
I'd like to let the user commit all their changes all at once with a single form submit. The way I'm doing this now is with allows_nested_attributes_for :contact_preferences in the User model, and naively POSTing the attributes of the edited preferences list. It works just fine except for a glaring bug: If a user deletes a contact preference, the ID simply isn't sent, and the preference doesn't get deleted from the DB.
allows_nested_attributes_for has support for deleting objects from the collection, but it requires the client to keep track of what IDs were deleted and pass a '_destroy' => 1 parameter. This is messy logic that I'd rather avoid; I just want objects deleted unless they are explicitly included in the parameters. allows_nested_attributes_for doesn't support this behavior as far as I can tell, so I'm looking to implement my own solution.
What's the most efficient (in terms of database access) way to do this kind of update? Do I delete everything and rebuild the list from scratch? Do I load the association and pick out objects that aren't explicitly included? Perhaps there's some clever ActiveRecord magic I can use?
My personal feeling is that doing this using the :destroy => 1 flag set a lot less messy than the alternative. The alternative would be loading the association on the server, comparing the incoming parameters, figuring out which records are missing, then deleting the missing ones and updating the remaining ones. That's a lot of extra logic, DB operations, and worst of all, you'll have to hand-rework the accepts_nested_attributes_for which is a non-trivial feat.
HTML give you a little trick/hack to accomplish this without JS. Add a checkbox to each record with name :destroy. Use the high-level form helpers, e.g. check_box, not check_box_tag (which requires a lot of things to get right manually), or a higher level form helper such as the simple_form gem.
If the flag is not checked, then HTML won't submit anything, and the record stays. If the flag is checked, HTML will submit the :destroy flag, and it will be deleted with the built-in server-side mechanisms out of the box.
You didn't say much about your front-end code; it sounds like you have a bunch of JS on there. You probably hide the record when the user "removes" it, you can simply add the destroy flag programmatically in that case, if you don't want to use the check box method above. This will be a lot simpler and less error prone than trying to second-guess the backend behavior.