Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you pass data from a controller to a model with Ruby on Rails?

How do you pass data from a controller to a model?

In my application_controller I grab the user's location (state and city) and include a before_filter to make it accesible in all my controllers via

before_filter :community

def community
    @city = request.location.city
    @state = request.location.state
    @community = @city+@state
  end

Then I try add the data retrieved in the controller to the model via:

before_save :add_community

def add_community
      self.community = @community
    end

The data, however, never makes its way from the controller to the model. If I use:

def add_community
    @city = request.location.city
    @state = request.location.state
    @community = @city+@state
    self.community = @community
  end

The methods request.location.city and request.location.state do not function from the model. I know that everything else is working because if I define @city and @state as strings, under def_community, then everything works, except I don't have a dynamic variable, just a string placed in the model. Also, I know the requests are working in the controller/views, because I can get them to display the proper dynamic info. The issue is simply getting the data from the controller to the model. Thanks a lot for your time.

like image 224
Laser Avatar asked Apr 19 '12 21:04

Laser


People also ask

How send data from controller view in Ruby on Rails?

To send Data from Controller to View, we've used Instance variable. To send Data from View to Controller, we've used GET/POST method.

What does a controller do in Ruby?

A controller can thus be thought of as a middleman between models and views. It makes the model data available to the view, so it can display that data to the user, and it saves or updates user data to the model.

What does Before_action do in Rails?

When writing controllers in Ruby on rails, using before_action (used to be called before_filter in earlier versions) is your bread-and-butter for structuring your business logic in a useful way. It's what you want to use to "prepare" the data necessary before the action executes.

What decides which controller receives Ruby?

Routing decides which controller receives which requests. Often, there is more than one route to each controller, and different routes can be served by different actions. Each action's purpose is to collect information to provide it to a view.


2 Answers

The class instance variables (those that start with @) in the controllers are separate from those in the models. This is the Model vs the Controller in MVC architecture. The Model and Controller (and view) are separated.

You move info from a controller to a model explicitly. In Rails and other object oriented systems, you have several options:

Use function parameters

# In the controller
user = User.new(:community => @community)

# In this example, :community is a database field/column of the 
# User model    

Docs

Use instance variables attribute setters

# In the controller
user = User.new
user.community = @community
# same as above, :community is a database field

Passing data to models when the data is not a database field

# In the model
class User < ActiveRecord::Base
  attr_accessor :community
  # In this example, :community is NOT a database attribute of the 
  # User model. It is an instance variable that can be used
  # by the model's calculations. It is not automatically stored in the db

# In the controller -- Note, same as above -- the controller 
# doesn't know if the field is a database attribute or not. 
# (This is a good thing)
user = User.new
user.community = @community

Docs

like image 54
Larry K Avatar answered Sep 30 '22 19:09

Larry K


The concept you're wrestling with is MVC architecture, which is about separating responsibilities. The models should handle interaction with the DB (or other backend) without needing any knowledge of the context they're being used in (whether it be a an HTTP request or otherwise), views should not need to know about the backend, and controllers handle interactions between the two.

So in the case of your Rails app, the views and controllers have access to the request object, while your models do not. If you want to pass information from the current request to your model, it's up to your controller to do so. I would define your add_community as follows:

class User < ActiveRecord::Base

  def add_community(city, state)
    self.community = city.to_s + state.to_s  # to_s just in case you got nils
  end

end

And then in your controller:

class UsersController < ApplicationController

  def create  # I'm assuming it's create you're dealing with
    ...
    @user.add_community(request.location.city, request.location.state)
    ...
  end
end

I prefer not to pass the request object directly, because that really maintains the separation of the model from the current request. The User model doesn't need to know about request objects or how they work. All it knows is it's getting a city and a state.

Hope that helps.

like image 43
tsherif Avatar answered Sep 30 '22 19:09

tsherif