record = Member.find_by_user(params[:member][:user]) - ruby-on-rails

I found a sample code like the title of this post and have a question.
Why is this written like params[:member][:user]?
I got advice from my friend and he explained that [:member] means table name and [:user] means column name included in the table of member.
But I don't get it because table is always plural and it is obvious that he or she are trying to search in table members as showed Member.find.

It is written as params[:member][:user] because params is a nested hash, such as this:
params = {"utf8"=>"✓",
"authenticity_token"=>"uAbvJ/LE1f8eDcANe+TVip5nsWfP/xJxxoGmsQyKFnU=",
"access_token"=>"",
"member"=> {"name"=>"foobar",
"email"=>"foo#bar.com",
"user"=>"jimmy",
"session"=>"2013-01-17 13:15:00 UTC"},
"commit"=>"Submit",
"locale"=>"es"}
This means to get to the value of the user inside of member, you would need to write something like params[:member][:user]. This is typical behavior of forms submitted by Rails, as the model data will be in it's own hash as member is in this example.

Related

Scope parameter as array in Rails 5

I have this scope with the parameter city, the scope receives the parameter, joins a table call Restaurant (because I have the param there) and then it makes a where condition with IN for multiple OR.
scope :by_cities, -> (city) { joins(:restaurant).where('restaurants.city IN (?)', city) }
The thing is that I want to learn how the scope can receive an array of param in the scope, I already have tried a lot of stuff and I'm taking the guide of this guy: Rails 4 scope with argument and this: ActiveRecord where field = ? array of possible values
Logs
Parameters: {"city"=>"SanPedro"}
SELECT "vacancies".* FROM "vacancies" INNER JOIN "restaurants" ON
"restaurants"."id" = "vacancies"."restaurant_id" WHERE (restaurants.city
IN ('SanPedro'))
Route
http://localhost:3000/v1/vacancies?city=SanPedro&Monterrey
But, don't understand very well how to do it, anyone knows about this?
Minimally, there is a problem with how you're forming your url query, here:
http://localhost:3000/v1/vacancies?city=SanPedro&Monterrey
As you can see in your params:
Parameters: {"city"=>"SanPedro"}
Your not getting an array of cities. Try something more like:
http://localhost:3000/v1/vacancies?city%5B%5D=San+Pedro&city%5B%5D=Monterrey
Which should give you something like:
Parameters: {"city"=>['San Pedro', 'Monterrey']}
BTW, you can see how a proper query string should look by doing:
{city: ['San Pedro', 'Monterrey']}.to_query
in your console.
Then, you should be able to do something like:
Vacancy.by_city(params[:city])

Rails can't mass-assign protected attributes for id, created_at

I'm using rails as the server side of a backbone.js site, therefore I'm constantly passing the rails objects back and forth.
I'm noticing errors in rails returning WARNING: Can't mass-assign protected attributes: id, created_at, updated_at.
Of course, I find this strange because I've never had to include these fields
My json looks fairly normal as far as I can tell
Parameters: {"id"=>1, "updated_at"=>"2011-04-21T16:41:02Z"}, "created_at"=>"2012-02-23T21:01:02Z", "action"=>"test update"}
There is nothing wrong with your JSON. The issue is one of security. Rails protects certain attributes by default from being created or updated from a giant hash. This is what the error is referring to when it uses the term "mass-assignment."
The JSON you posted:
Parameters: {"id"=>1, "updated_at"=>"2011-04-21T16:41:02Z"}, "created_at"=>"2012-02-23T21:01:02Z", "action"=>"test update"}
contains the id the created_at and the updated_at fields. When this JSON is passed into the action and the hash is used in a model_object.update_attributes(hash_fields) you will get this error. To avoid this error you can delete the fields from the hash and assign them later, or ideally, let ActiveRecord work it's magic for you and just ignore them.
If you really do need to assign them you can do that like:
model_object.id = id_variable
model_object.created_at = created_at_variable
model_object.updated_at = updated_at_variable
model_object.save
EDIT1 (to address the comment about passing back the id):
If you are using the Rails REST model and calling the controller/:id/action url, you don't need to pass the ID back, as that information is already embedded in the URL. It can be accessed via params[:id] and the hash via params[:model_name] (following the Rails model).
If you are doing something different and the ID must be in the JSON being passed back then you can simply do id = params[:model_name][:id].delete and that will delete the id from the hash and return the value in one call. It's not ideal, but it can get the job done in a pinch.
Those columns are protected by default for mass assignment and cannot be set manually. But, you can override this behavior by defining a method:
def self.attributes_protected_by_default
[] # ["created_at", "updated_at" ..other]
end
This will allow you to assign created_at and updated_at manually.

How to define a Form Override for a Chained Form Field in Active Scaffold

Below example is taken from this documentation page:
https://github.com/activescaffold/active_scaffold/wiki/Chaining-Form-Fields
[Example start]
You can set an array of columns to update multiple columns when a column changes, and chain column updates:
class UsersController < ApplicationController
active_scaffold do |config|
config.columns[:author].form_ui = :select
config.columns[:author].update_columns = [:book, :editorial]
config.columns[:book].form_ui = :select
config.columns[:book].update_columns = :format
end
end
In this example, fields for book, editorial and format are updated when author changes, and when book changes only format is updated. A form override which use the new author or book must be defined for editorial and format columns, in other case those fields won’t change when they will be rendered again.
[Example end]
In the example it states "a form override which use the new author or book must be defined".
Question is how to define those form overrides ??
I have read the documentation on https://github.com/activescaffold/active_scaffold/wiki/Form-Overrides, and tried different form overrides, but with no luck so far, i.e. the columns are not being rendered again.
If you can help me with the code for those form overrides needed in the given example, then I should be able to port that to my code.
Here is the solution to my problem:
I followed the example on "https://github.com/activescaffold/active_scaffold/wiki/Chaining-Form-Fields", but when it did not work for my chained columns (when updating the first column all chained columns updates correctly, but when updating the second column then its chained columns renders to blank lists), then I focused (blindly?) on the details explained just below the example as I thought this was the first step to solve my problem: "A form override which use the new author or book must be defined for editorial and format columns, in other case those fields won’t change when they will be rendered again".
This was however not the case, no form override in the helper was needed to get this to work, in the helper the "options_for_association_conditions" is enough. As the example is for v2.4, maybe the form override is not needed anymore in v3.0+.
The solution is in the next paragraph on the example wiki: "Usually only the value of the changed column is sent, if you need another values to render the updated columns, enable send_form_on_update_column and all the form will be sent". My problem was, that the columns which was chained from the second column needed the value from the first column also, so setting up the second column with "send_form_on_update_column" (i.e. sending the whole form, not just its own value) solved my problem.
In the example this would be:
config.columns[:book].send_form_on_update_column = true

How to retrieve all attributes from params without using a nested hash?

I am currently in the process of making my first iphone app with a friend of mine. He is coding the front end while I am doing the back end in Rails. The thing is now that he is trying to send necessary attributes to me with a post request but without the use of a nested hash, which means that that all attributes will be directly put in params and not in a "subhash". So more specifically what I want to do is be able to retrieve all these attributes with perhaps some params method. I know that params by default contains other info which for me is not relevant such as params[:controller] etc.. I have named all attributes the same as the model attributes so I think it should be possible to pass them along easily, at least this was possible in php so I kind of hope that Rails has an easy way to do it as well.
So for example instead of using User.new(params[:user]) in the controller I have the user attributes not in the nested hash params[:user] but in params directly, so how can I get all of them at once? and put them inside User.new()?
I found the solution to my problem. I had missed to add the attr_accessible to my model which was what initially returned the error when I tried to run code like: User.new(params) having been passed multiple attributes with the post request.
The solution was very simple, maybe too simple, but since this is my first real application in Rails I feel that it might be helpful for other newbies with similar problems.
If you would like to just pass a more limited version of params to new, you should be able to do something like the following:
params = { item1: 'value1', item2: 'value2', item3: 'value3' }
params.delete(:item2)
params # will now be {:item1=>"value1", :item3=>"value3"}
Also see this for an explanation of using except that you mention in your comment. An example of except is something like:
params.except(:ssn, :controller, :action, :middle_name)
You can fetch the available attributes from a newly created object with attribute_names method. So in this special example:
u = User.create
u.attributes = params.reject { |key,value| !u.attribute_names.include?(key)
u.save

How to add parameters to a ruby on rails post?

Say I have a model called User that has the following parameters: favorite_color, favorite_animal, and lucky_number. The user fills in the form containing only favorite_color and favorite_animal. When the form is submitted, I want to run a function that takes the color and animal into account and comes up with a lucky_number. How do I insert a value to the post values without the user filling out the form - how and where do I implement this?
Thank you!
Since the lucky_number won't be known until after the favorite_animal and favorite_color are already recorded, it would be impossible to send it along with the post request. Try using a
before_validation_on_create
that looks something like this:
before_validation_on_create :generate_lucky_number
def generate_lucky_number
self.lucky_number = self.favorite_animal.length + self.favorite_color.length
end
This function just sets the lucky number to the combined length of the strings stored for the favorite color and favorite animal, and will set it before saving the user to the database.
You could build it into your controller logic, or place the code in your model in one of the following callbacks:
before_validation
before_validation_on_create
before_validation_on_update

Resources