Can't find same question. How can I specify select.where for model?
I need to select from different tables by one model and want to get something like this in controller:
params[:id] = 1248 // here is example of request params
id=params[:id] // this id goes to message SQL like table name with prefix:
Message(id).all => select * from messages_1248
How can I get something like this?
Thanks for answers!
UPD:
I have one table with users and many tables with messages (each table is for one pair of users). In users table there is 'messages' column with messages tables id's. And inside user_controller I need to run a query like in my question. Maybe anybody can share an example?
how about little bit change the design, with just 2 tables (user and message) just idea with details below
user table (id,name)
messages table(user_id,message_text)
you setup the relation user has_many messages (please see this link for more guide http://guides.rubyonrails.org/association_basics.html#the-has-many-association
user.rb
has_many :memberships
message.rb
belongs_to :user
for example you need to access user with specific id and the messages for this user
inside users_controller.rb
def show
#user = User.find(params[:id])
# this find user
#messages = #user.messages
# get all the messages for specific users
end
Related
I have general field search in ActiveScaffold working. I'm not sure how to do this more complex searching.
I have two tables, Account and User, and I want to search emails and get back a list of matching accounts. The email field is in User, and Account has_many :users.
I am having trouble thinking through how the query should happen. Ideally I'd like to do something like this:
Account.where(email: 'search_term').all
or
User.where(email: 'search_term').includes(:account).all
If you want to search for data from one table and return results from(including) another, just add those foreign columns as virtual columns:
in User controller:
active_scaffold :user do |conf|
conf.search.columns << :email
conf.list.columns << :account
#...
end
That's it, no queries :)
if account column results appears code like <#23423.. it's because Active Scaffold can't tell how to describe that class records, so you tell it how you want in the model:
class Account << ActiveRecord::Base
....
def to_label
"cod: #{account_number}"
end
I'm trying to create an ordering system so that when an order is placed, the customer logs in/registers and the order is added to their index. I have two controllers and all their respective models/views etc - called orders and customers. I'm assuming I'd need to add a method so that the customer_id is added to the order when it is placed, and then I could display all orders with that id in that particular customer's index - i.e. they can only see their own orders.
It's probably quite a simple question, apologies! But I'm new to rails and can't figure out how to get started on this one. Please can someone suggest how I would go about doing this?
Edit:
Thanks for everyone's help! How would I get the customer index to display only orders for that customer? Would I store the customer_id in a session when they log in, then place that in the order, then find all orders with that id in the index page? I think I know how to get their id into a session at login, but am unsure how to extract this into the customer index view. Any help would be much appreciated!
IF you create your orders table to have a customer_id, and fill that id when the customer places an order, then the customer view of orders should always be scoped to their orders. You will need to differentiate between a customer user and your admin user (perhaps you?), as in (something like):
class customer
has_many :orders
end
class order
belongs_to :customer
end
class OrdersController
def index
# determine the current customer (or admin), then
if current_user.isAdmin?
#orders = Order.all
else
#orders = current_user.orders
end
end
end
#railsdog is correct, however, here is the other part of the puzzle (how to get your customer's ID in the order in the first place):
class OrdersController
def create
#order = Order.new(params[:order])
#order.customer_id = current_user.id
# ...
end
#...
end
Note here the approach of setting the customer_id in the controller, not from the form. The reason for this is that even a hidden form field can be changed by the client, so if you did that without checking on the server side, an attacker could place orders for other customers.
models:
#StatusMessage model
class StatusMessage < ActiveRecord::Base
belongs_to :users
default_scope :order => "created_at DESC"
end
#User Model
class User < ActiveRecord::Base
has_many :status_messages
end
In controller I want to join these two tables and get fields from both table. for example I want email field from User and status field from StatusMessage. When I use :
#status = User.joins(:status_messages)
Or
#status = User.includes(:status_messages)
It gives me only the user table data.
How can I implement this requirement?
You need to use includes here. It preloads data so you won't have another SQL query when you do #user.status_messages.
And yes you can't really see the effect: you need to check your logs.
First of all, I don't think it is possible (and reasonable) what you want to do. The reason for that is that the relation between User and StatusMessage is 1:n, that means that each user could have 0 to n status messages. How should these multitudes of attributes be included in your user model?
I think that the method joints in class ActiceRecord has a different meaning, it is part of the query interface. See the question LEFT OUTER joins in Rails 3
There are similar questions on the net, here is what I have found that matches most:
Ruby on Rails: How to join two tables: Includes (translated for your example) in the user a primary_status_message, which is then materialized in the query for the user. But it is held in one attribute, and to access the attributes of the status_message, you have to do something like that: #user.primary_status_message.status
When you use #status = User.includes(:status_messages) then rails eagerley loads the data of all the tables.
My point is when you use this User.includes(:status_messages) it will loads the data of status_messages also but shows only users table data then if you want first user status_messages then you have to #user.first.status_messages
I need to find an elegant solution to scoped finds based on access control rules. Essentially I have the following setup:
Users
Customers
AccessControl - Defines which user has access to another users data
Users need to be able to access not just their own customers but also shared customers of other users.
Obviously something like a simple association will not work:
has_many :customers
and neither will this:
has_many :customers, :conditions => 'user_id in (1,2,3,4,5)'
because the association uses with_scope and the added condition is an AND condition not an OR condition.
I also tried overriding the find and method_missing methods with the association extension like this:
has_many :customers do
def find(*args)
#get the user_id and retrieve access conditions based on the id
#do a find based on the access conditions and passed args
end
def method_missing(*args)
#get the user_id and retrieve access conditions based on the id
#do a find based on the access conditions and passed args
end
end
but the issue is that I don't have access to the user object / parent object inside the extension methods and it just does not work as planned.
I also tried default_scope but as posted here before you can't pass a block to a default scope.
Anyhow, I know that data segmentation and data access controls have been done before using rails and am wondering if somebody found an elegant way to do it.
UPDATE:
The AccessControl table has the following layout
user_id
shared_user_id
The customer table has this structure:
id
account_id
user_id
first_name
last_name
Assuming the the following data would be in the AccessControl table:
1 1
1 3
1 4
2 2
2 13
and so on...
And the account_id for user 1 is 13 I need to be able to retrieve customers that can be best described with the following sql statement:
select * from customers where (account_id = 13 and user_id = null) or (user_id in (1,3,4))
Sorry if I've completely missed the point here but I'm not 100% sure of what you want to do. Is AccessControl a relationship between User and Customer? If so looks like you just need to setup a many-to-many relationship.
class User
has_and_belongs_to_many :customers
# or this if you need to store meta data in the join table
has_many :customers
has_many :access_controls
has_many :accessible_customers, through => :access_controls
end
I've got a User model that has many Items. A Rating belongs to a User and an Item.
In the DB, I have set ratings.user_id to be not NULL.
when I am creating an Item, I would like to do this:
def create
current_user.items.create(params[:item]).ratings.create(params[:rating]
redirect_to items_path
end
However, this balks with an SQL error "user_id cannot be nil"
so I rewrote the create method as
def create
current_user.items.create(params[:item]).ratings.create(params[:rating].merge({:user_id => current_user}))
redirect_to items_path
end
which works fine.
However, I had thought that chaining the create methods off the current user's receiver would have populated the rating's user_id. Anyone know why not?
TIA.
I'd recommend you normalize this if possible in the database. Maybe take out the user_id attribute from the ratings table and if you need it in your model get it through a join using a :through method
class Rating
has_many :items
has_one :user, :through=>:items
If you created and saved the Item, then made a Rating from that item, it wouldn't pass the user along to the Rating, right? You'd just refer to it as #rating.item.user, right?
When you think about it like that, you wouldn't expect the Item created via the current_user to pass the user information along to the rating.
Make me wonder if you really need the user has_many ratings relationship.
Because Item has many Ratings and that association does not know about the user id. Given that association chain Item would have a user id because it belongs to a user. And Rating would have an item id because it belongs to an item. But the Item to Rating assocation doesn't know anything about a user unless you tell it.