0

I have a class activity that has the follow atributes:

String type, Date date, String title

By including the associations it also has user_id and place_id.

class Activity < ActiveRecord::Base
   belongs_to :user
   belongs_to :place

In the other side User has many activities and place has many activities

So, the problem is when I want to create a new activity: Scaffold creates the helper _form :

<%= form_for(@activity) do |f| %>
  <% if @activity.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@activity.errors.count, "error") %> prohibited this activity from being saved:</h2>

      <ul>
      <% @activity.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :type %><br>
    <%= f.text_field :type %>
  </div>
  <div class="field">
    <%= f.label :date %><br>
    <%= f.datetime_select :date %>
  </div>
  <div class="field">
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :user_id %><br>
    <%= f.number_field :user_id %>
  </div>
  <div class="field">
    <%= f.label :place_id %><br>
    <%= f.number_field :place_id %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

I want to receive the first 3 fields from the form (type, date and title) but to associate a user and a place I have to do other way. I need the user that is actual logged in and the place is choosen by tiping the name.

My idea to do this is the following:

1) The user issue, I can make a query by using the current_logged_user that I have acess and get his ID.

2) The place issue, I can use the name that I receive from form and query my Places table for the place with the name X and get the ID after.

But, because I don't know too much about rails, how can I do this? How can I use f.text_field and then made the query or whatever and use after in the controller?

Controller has already this stuff :

def create
    @activity = Activity.new(activity_params)
(...)

private
    # Use callbacks to share common setup or constraints between actions.
    def set_activity
      @activity = Activity.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def activity_params
      params.require(:activity).permit(:type, :date, :title, :user_id, :place_id)
    end

1 Answer 1

1

You can structure your rails app to get neither the user_id nor the place_id directly from the form. Especially getting user_id from a submitted form is generally not a good idea. You usually do not want to whitelist user_id at all.

For user_id:

If you are using a gem like devise for user authentication, it gives you access to a method called current_user, which you can use to set the user_id from.

For place_id:

I suggest putting the activity as a sub route of place. e.g. instead of having the form under <host>/activities/new, put it under ``/places/:place_id/activities/new`. In your route file put the route as follows:

resources :places do
    resources :activities
end

Now, in your controller action you can do the following:

def create
    @activity = current_user.activities.new(activity_params)
    @activity.place_id = params[:place_id] (or even safer will be @activity.place = Place.find(params[:place_id], but this will require one more sql query ) 
    (...)
private      

# Never trust parameters from the scary internet, only allow the white list through.
def activity_params
  params.require(:activity).permit(:type, :date, :title)
end

UPDATE:

If you absolutely want to have the form under /activities/new route then you can have a select tag for place_id in your form:

select_tag 'activity[place_id]', options_from_collection_for_select(Place.all, 'id', 'name')

This will create a selection with name 'activity[place_id]' (named this way for params.require(:activity).permit(place_id) ) and options looking like

<option value="1">Barcelona</option>
Sign up to request clarification or add additional context in comments.

5 Comments

I'm not understanding the idea of /places/:place_id/activities/new.Waht I'm going (and suposed) to do is /activities/new. Thank you for the help @AOG
You're welcome. The idea is that associations can go under their parent's url to make both the url more informative and the backend coder's life easier. E.g. you can easily show things like "user activities related to a place".
I will see. Thank you once again!
I think I got the idea. Make a select with all the places in my database, right?
Yea, the first arg for options_from_collection_for_select is the input rails collection, the second is the method (here the id attribute) to use to generate values and the third is the method (here the name attribute) to use to generate option text. Here is the API doc for it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.