Search code examples
ruby-on-railsrubyruby-on-rails-3parametersbefore-filter

I think I'm messing around ... Rails params


I search a lot in those questions but I don't really see my problem and I hope I will ...

( I'm used to code in C, C++ etc... but I'm a newbie in rails ... )

I have a sign_up view and when I submit, rails automatically set every fields of the user that are filled in the form. It's cool but now I want to create a new text_field and take what the user enter as text in this text_field and uses it later without setting any other user's field, I have been told to use before_create and params or things like that but then I'm a noob ... In haml :

do |f|
  = f.text_field :email, :placeholder => "email"

works well (it set the email field with what the user enters)

do |f|
  = f.text_field NewVarThatIsNotAFieldOfCurrentNewUser, :placeholder => "referral code"

Then ofc, this error happens.

Error : undefined local variable or method `NewVarThatIsNotAFieldOfCurrentNewUser' (for the user class ofc)

If you want more information/code I'll edit this question :)

Thank you in advance !


Solution

  • Ruby / Rails is much simpler than C++

    You don't need to "declare" new variables every time you want to use them - you just populate them in order to delcare them. Further, Ruby / Rails is object orientated, meaning that everything you do needs to be based around Objects.


    Var

    Your error is stated as such:

    undefined local variable or method `NewVarThatIsNotAFieldOfCurrentNewUser'
    

    What this means is that you're trying to load a variable which you have not created yet. I mentioned you don't need to declare variables in the same way as C++, but you do need to populate them with data, or at least have them accessible to your app

    In order to do this, you'll need to declare & populate the variable in your controller, although this brings me onto my next point -- regarding the context in which you're trying to use the variable.

    --

    Objects

    As Rails / Ruby is object-orientated, it means that everything you do needs to centre around objects. This is why your error states local variable or method -- objects have "methods" as well as data

    Anyway, the way to fix your issue is to make sure that the attribute that your user has is available when you call / create the new User object. To do this, I would recommend using attr_accessor, although I'm not entirely sure what you're asking to be honest.

    Here's what I'd do:

    #app/models/user.rb
    class User < ActiveRecord::Base
       attr_accessor :new_attribute
    end
    
    #app/views/users/sign_up.html.erb
    <%= form_for @user do |f| %>
       <%= f.text_field :new_attribute %>
       <%= f.submit %>
    <% end %>
    

    This will create what's known as a virtual attribute, which means that it will not be saved into the database (as the database does not have the corresponding attribute supported)


    Fix

    If you wanted to collect data for a "new" attribute the user does not have data for (which is still in the database), you'll likely want to use the following:

    #app/views/users/sign_up.html.erb
    <%= form_for @user do |f| %>
       <%= f.text_field :attribute %>
       <% end %>
    <% end %>
    

    In regards to what you're asking - I believe the attr_accessor method is the most apt. This will give you the ability to "reuse" the data which is submitted without relying on storing it in the database.

    --

    MVC

    Finally, to give you some more context - I don't know how familiar you are with MVC (I presume relatively), but I figured I give you some ideas on how Rails applications work:

    enter image description here

    MVC means that you have a Model, view and Controller. These all work together to provide a base level of functionality for your application - providing you with the capacity to create & edit data from your DB.

    I mention this because if you can appreciate how Rails works from an architectural standpoint, you'll be in a much better position to make use of it. For example, you mention you're confused with before_create, and then tag the question with before_action.

    These two callbacks serve different parts of the Rails framework, and will not, therefore, perform the same functionality.

    -- before_create is for your Model

    -- before_action is for your Controller